Openbox:Pipemenus:Audacious control alternative

From Openbox

(Difference between revisions)
Jump to: navigation, search
(Replaced some characters with html codes)
Line 249: Line 249:
 
  chomp($title);
 
  chomp($title);
 
  chomp($lgth);
 
  chomp($lgth);
 +
# replace some special characters by their html codes
 +
$title =~ s/&/&/g;
 +
$title =~ s/"/"/g;
 +
$title =~ s/\$/$/g;
 +
$title =~ s/</&amp;#60;/g;
 +
$title =~ s/=/&amp;#61;/g;
 +
$title =~ s/>/&amp;#62;/g;
 +
$title =~ s/\\/&amp;#92;/g;
 +
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
 +
$title =~ s/_/__/g;
 
  say "  <item label=\"$song. $title ($lgth)\">";
 
  say "  <item label=\"$song. $title ($lgth)\">";
 
  say "    <action name=\"Execute\">";
 
  say "    <action name=\"Execute\">";

Revision as of 08:19, 30 June 2014

The idea for this menu came from this other audacious menu, but this is a slightly expanded version. The "Show/hide main window" feature depends on wmctrl - this is needed to detect if the window is shown or not and set the item label/action accordingly. If you do not have wmctrl abd have other means of getting the information, adjust code accordingly or remove the item. The "add/remove files" features depend on zenity to create the file selection and text entry boxes - again, if you don't have zenity, adjust code (the appending of files to the end of playlist can be done via audtool --filebrowser-show on).

This menu consists of two files - the actual menu (audmenu) and the script (audctrl) that controls adding and removing songs. Both need to be executable. The script needs to be in your PATH (or you would need to specify the full path to it everywhere in the code of audmenu. The path to audmenu should be specified at the beginning of the script.

The audctrl script also provides a more extended "previous song" feature - audtool does not jump from first to last song even when repeat is on (it only allows jumping from last to first when selecting "next song").


audmenu:

#!/usr/bin/perl
# A pipe menu for openbox to control Audacious.
# Depends on wmctrl, zenity and an additional script audctrl.
# All the functionality of audctrl can be incorporated into this script (as was done with the playlist submenu),
# but this way, it can be used independently of this menu in a complementary way to audtool.
# audctrl should be in your PATH

sub say {print @_, "\n"}

# specify path to this script (needed because it calls itself to create the playlist submenu)
my $path = "$ENV{HOME}/obmenus";

my $pid = `pidof audacious`;
my $status;
my $curr_song;
my $curr_song_lgth;
my $curr_song_pos;
my $plst_lgth;
my $title;

# if audacious is running, get info on playlist
if ( $pid == "" ) {
    $status = 'off';
} else {
    $status = `audtool --playback-status`;
    $curr_song = `audtool --current-song`;
    $curr_song_lgth = `audtool --current-song-length`;
    $curr_song_pos = `audtool --playlist-position`;
    $plst_lgth = `audtool --playlist-length`;
}

chomp($status);
chomp($curr_song);
chomp($curr_song_lgth);
chomp($curr_song_pos);
chomp($plst_lgth);

# print playlist submenu and exit if arg1 is pls
 if ( "$ARGV[0]" eq "pls" ) {
    print_plst();
    exit 0;
}

# otherwise, start printing the main menu
say "<openbox_pipe_menu>";

# if audacious is not running, print "start" option and exit; else determine status and set playlist menu label
if ( $status eq "off" ) {
    say "  <item label=\"Start audacious\">";
    say "    <action name=\"Execute\">";
    say "      <execute>";
    say "        audacious";
    say "      </execute>";
    say "    </action>";
    say "  </item>";
    say "</openbox_pipe_menu>";
    exit 0;
} elsif ( $status eq "stopped" ) {
    if ( `audtool --current-song` ne "No song playing.\n" ) {
	$title = "Stopped: $curr_song_pos. $curr_song ($curr_song_lgth)";
    } else {
	$title = "Stopped";
    }
} elsif ( $status eq "paused") {
    $title = "Paused: $curr_song_pos. $curr_song ($curr_song_lgth)";
} else {
    $title = "Playing: $curr_song_pos. $curr_song ($curr_song_lgth)";
}

# unless playlist is empty, print it as menu, otherwise - just put a separator with the status
if ( $plst_lgth == 0 ) {
    say "<separator label=\"$title\" />";
} else {
    say "<menu id=\"pls\" label=\"$title\" execute=\"$path/audmenu pls\" />";
    say "<separator />";
}

# play/pause song
if ( $status eq "playing") {
    say "  <item label=\"Pause\">";
} else {
    say "  <item label=\"Play\">";
}
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playback-playpause";
say "      </execute>";
say "    </action>";
say "  </item>";

# stop playback
say "  <item label=\"Stop\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playback-stop";
say "      </execute>";
say "    </action>";
say "  </item>";

# play next/previous song; 'audctrl prev' accounts for the case where repeat is on and current song is number 1
say "  <item label=\"Next\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playlist-advance";
say "      </execute>";
say "    </action>";
say "  </item>";
say "  <item label=\"Previous\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audctrl prev";
say "      </execute>";
say "    </action>";
say "  </item>";
say "<separator />";

# toggle "stop after current song"
if ( `audtool --playlist-stop-after-status` eq "off\n" ) {
    say "  <item label=\"Stop after current song\">";
} else {
    say "  <item label=\"Continue after current song\">";
}
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playlist-stop-after-toggle";
say "      </execute>";
say "    </action>";
say "  </item>";

# toggle "repeat playlist"
if ( `audtool --playlist-repeat-status` eq "off\n" ) {
    say "  <item label=\"Repeat playlist\">";
} else {
    say "  <item label=\"Do not repeat playlist\">";
}
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playlist-repeat-toggle";
say "      </execute>";
say "    </action>";
say "  </item>";

# toggle "shuffle playlist"
if ( `audtool --playlist-shuffle-status` eq "off\n" ) {
    say "  <item label=\"Shuffle playlist\">";
} else {
    say "  <item label=\"Do not shuffle playlist\">";
}
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playlist-shuffle-toggle";
say "      </execute>";
say "    </action>";
say "  </item>";
say "<separator />";

# add songs to end of playlist
say "  <item label=\"Append files to playlist\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audctrl add";
say "      </execute>";
say "    </action>";
say "  </item>";

# add songs to playlist at position...
say "  <item label=\"Add files to playlist\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audctrl add_pos";
say "      </execute>";
say "    </action>";
say "  </item>";

# remove songs from playlist
say "  <item label=\"Remove songs from playlist\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audctrl del";
say "      </execute>";
say "    </action>";
say "  </item>";

# clear playlist
say "  <item label=\"Clear playlist\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --playlist-clear";
say "      </execute>";
say "    </action>";
say "  </item>";

# clear all but the current song
say "  <item label=\"Clear all but the current song\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audctrl clear";
say "      </execute>";
say "    </action>";
say "  </item>";
say "<separator />";

# show hide main window
if ( `wmctrl -lp | tr -s ' ' | cut -d' ' -f3` =~ /^$pid$/m ) {
    say "  <item label=\"Hide main window\">";
    say "    <action name=\"Execute\">";
    say "      <execute>";
    say "        audtool --mainwin-show off";
} else {
    say "  <item label=\"Show main window\">";
    say "    <action name=\"Execute\">";
    say "      <execute>";
    say "        audtool --mainwin-show on";
}
say "      </execute>";
say "    </action>";
say "  </item>";

# shutdown audacious
say "  <item label=\"Shutdown Audacious\">";
say "    <action name=\"Execute\">";
say "      <execute>";
say "        audtool --shutdown";
say "      </execute>";
say "    </action>";
say "  </item>";

say "</openbox_pipe_menu>";

# playlist submenu (called by passing a 'pls' argument to this script)
sub print_plst {
    my $plst_lgth = `audtool --playlist-length`;
    chomp($plst_lgth);
    say "<openbox_pipe_menu>";
    foreach my $song (1..$plst_lgth) {
	my $title = `audtool --playlist-song $song`;
	my $lgth = `audtool --playlist-song-length $song`;
	chomp($title);
	chomp($lgth);
# replace some special characters by their html codes	
	$title =~ s/&/&amp;/g;
	$title =~ s/"/&#34;/g;
	$title =~ s/\$/&#36;/g;
	$title =~ s/</&#60;/g;
	$title =~ s/=/&#61;/g;
	$title =~ s/>/&#62;/g;
	$title =~ s/\\/&#92;/g;
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
	$title =~ s/_/__/g;
	say "  <item label=\"$song. $title ($lgth)\">";
	say "    <action name=\"Execute\">";
	say "      <execute>";
	say "        audtool --playlist-jump $song";
	say "      </execute>";
	say "    </action>";
	say "  </item>";
    }
    say "</openbox_pipe_menu>";
    return;
}


audctrl:

#!/usr/bin/perl
# Additional functions to control Audacious. Depends on zenity.

# Remove all but the current song
sub clear_others {
    my $plst_lgth = `audtool --playlist-length`;
    chomp($plst_lgth);
    if ( $plst_lgth > 1 ) {
	my $curr_song = `audtool --playlist-position`;
	chomp($curr_song);
	my $del = 1;
	PLS: foreach my $song (1..$plst_lgth) {
	    if ( $song == $curr_song ) {
		$del = 2;
		next PLS;
	    }
	    system("audtool --playlist-delete $del");
	}
    }
    exit 0;
}

# Remove songs at positions (needs zenity)
sub del {
    my $sel = `zenity --entry --text="Remove songs at positions (coma separated):" | tr -d ' '`;
    if ( "$sel" eq "" ) { exit 1 };
    chomp($sel);
    my @pos = split(',' , "$sel");
    my $iter = 0;
    foreach (sort { $a <=> $b } @pos) {
	my $del = $_ - $iter;
	system("audtool --playlist-delete $del");
	if ( $? != 0 ) {
	    system("zenity --error --text=\"No such song number\!\"");
	    exit 1;
	}
	$iter++;
    }
    exit 0;
}

# Add songs to specified positions or the end of the playlist
sub add {
    my ($check) = @_;
    my $sel = `zenity --file-selection --title="Add files" --filename=/media/Music/ --multiple`;
    if ( "$sel" eq "" ) { exit 1 };
    chomp($sel);
    my @files = split(/\|/ , "$sel");
    my $pos = -1;
    my $cmd;
    if ( $check ) {
	$pos = `zenity --entry --text='Insert files at position:' | tr -d ' '`;
    }
    if ( "$pos" eq "" ) { exit 1 };
    my $plst_lgth = `audtool --playlist-length`;
    chomp($plst_lgth);
    if ( $check && ( $pos < 1 || $pos > $plst_lgth ) ) { exit 2 };
    foreach (@files) {
	if ( $check ) { system("audtool --playlist-insurl \"$_\" $pos") }
	else { system("audtool --playlist-addurl \"$_\"") };
	if ( $? != 0 ) { exit $? };
    }
    exit 0;
}

# Jump to previous song - accounts for the case when repeat is on and the current song is number 1
sub prev {
    if ( `audtool --playlist-repeat-status` eq "on\n" && `audtool --playlist-position` == "1\n" ) {
	my $plst_lgth = `audtool --playlist-length`;
	chomp($plst_lgth);
	system("audtool --playlist-jump $plst_lgth");
    } else {
	system("audtool --playlist-reverse");
    }
    exit 0;
}

if ( "$ARGV[0]" eq "clear" ) { clear_others(); }
elsif ( "$ARGV[0]" eq "del" ) { del(); }
elsif ( "$ARGV[0]" eq "add" ) { add( 0 ); }
elsif ( "$ARGV[0]" eq "add_pos" ) { add( 1 ); }
elsif ( "$ARGV[0]" eq "prev" ) { prev(); }
else { exit 1; }
Personal tools