A little tool for command-line playlist building

For the last few years, I’ve been amassing a collection of little scripts I use every day to build playlists, both for Audacious and for MPlayer.

About a week ago, I realized that they’d started to duplicate each others’ functionality and refactored them into a single script which has different default behaviours depending on what it’s called as (but you can also use command-line flags).

So far, here are the behaviours it implements based on what you call it as (either via MPRIS [1] [2] or using a command provided via --exec such as mplayer):

Add the given paths to the playlist.
Like aq but start the first one playing too.
Like aq but use locate -i to search for the first argument, filter for known media types and filter for the following arguments, then display a chooser.
Like laq but start the first one playing too.
Randomly select -n NUM songs (default: 10) from the paths provided (default: XDG_MUSIC_DIR) and add them to the playlist.
Like rap but start the first one playing too.

…and all of these are just aliases to options listed in --help.

Until two days ago, the chooser was a simple little thing where you were given a numbered list of filenames and you typed in a sequence of numbers, optionally including Python-style start:stop slice syntax.

Now, if you’ve got urwid installed, you get a nice ncurses-style pseudo-GUI, complete with mouse interaction… though the scroll wheel support is preliminary and I’m still trying to figure out how to set up Tab-based focus switching.

Here’s a screenshot:

I haven’t had time to fully bring the codebase up to spec, write the last few new features, and write a test suite for it, but it’s good enough for my day-to-day use so, if you want to give it a try, it’s on GitHub in ssokolow/profile as home/bin/lap. (It has its own GitHub repo now.)

The queue option in the chooser can be toggled via the Q key or Meta+Q and, once you’ve selected all the tracks you want using Spacebar or the mouse, press Enter to commit.

In case I ever move it to its own repo and forget to update the link, you can also grab the revision at the time of this posting.

CC BY-SA 4.0 A little tool for command-line playlist building by Stephan Sokolow is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This entry was posted in Geek Stuff. Bookmark the permalink.

6 Responses to A little tool for command-line playlist building

  1. ohnonot says:

    i’d like to try your script but can’t get it to work. on first invocation, just with lap (it resides in ~/bin), i get this:
    Traceback (most recent call last):
    File "/home/me/bin/lap", line 472, in
    ['xdg-user-dir', 'MUSIC']).strip())
    File "/usr/lib/python2.7/subprocess.py", line 568, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
    File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
    File "/usr/lib/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
    OSError: [Errno 2] No such file or directory

    next i tried
    lap -vv -e mplayer ap /home/me/music
    which returned an empty results list although there are music files in subfolders there. i even copied one mp3 to /home/me/music, but to no avail.
    i don’t like to use xdg-user-dir but i installed it anyway; now calling lap without arguments does not do anything. it doesn’t quit either, just sits there.
    this is arch linux.

    • Sorry about that. That’s a side-effect of the aforementioned lack of time to bring it up to my usual standards. (I’ve got exams at the end of the month and learning enough about urwid to do it took longer than I expected.)

      I’ve added a quick check to provide a more reasonable error message if xdg-user-dir isn’t available.

      lap -vv -e mplayer ap /home/me/music is just a case of me not providing clear usage examples yet. It returns no results because you’re telling it “Use locate to find all files containing ‘ap’, then filter for only the ones containing ‘/home/me/music'”. (Filtering for only media files comes automatically, but it’s not yet configurable)

      Just run lap -e mplayer /home/me/music instead. (locate matches against full paths by default)

      The option parser is the main thing that still needs a major rewrite once my exams are over so, at the moment, you can only access the urwid chooser via the lap/laq behaviours.

      (I’m still working out how to design the new setup to be consistent while still minimizing the harm to my muscle memory, which expects a chooser from lap/laq with no options but not from ap/aq/rap/raq.)

      As for actually accessing the ap behaviour, either rename it to ap or create a symlink named ap. (Reworking the option parser to ensure that you can call “lap” but use an option to disable the locate portion is also planned but I first want to look into how things like the nose test runner implements options which can be set via config file too.)

      Let me know if there are any other rough edges that bother you and I’ll see if I can squeeze in a quick patch or two per day.

  2. ohnonot says:

    now it works; i’m just not quite sure what it’s supposed to be, other than some kind of minimalistic audioplayer. also it does not start to play by default, and -r option throws another error:
    lap -r -e mplayer /home/me/music/
    Traceback (most recent call last):
    File "/home/me/bin/lap", line 487, in
    results = gather_random(args, opts.wanted_count)
    File "/home/me/bin/lap", line 350, in gather_random
    chosen.append(choices.pop(random.randrange(0, len(choices))))
    File "/usr/lib/python2.7/random.py", line 217, in randrange
    raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width)
    ValueError: empty range for randrange() (0,0, 0)

    but hey, your exams are surely more important now!

    • Replying takes practically no time so I don’t mind.

      That one is actually an honest-to-goodness bug. I forgot that randrange() fails catastrophically when given an empty range and never tested it against a directory with fewer items than I was requesting.

      (Now you see a more specific example of what I mean when I say that writing a proper test suite takes time… time to audit the code and build a list of all the corner cases and failure modes that need to be tested.)

      I’ve pushed a fix. Keep in mind that rap/raq take absolute paths.

      As for what it’s used for, if you omit the -e mplayer, it will use the MPRIS D-Bus API to act as a command-line “add files to playlist” dialog for your existing media player.

      That’s actually my primary use for it. I’ll feed lap or laq a query and then pick some matches to be added to my existing Audacious playlist. (In other words, I mainly use it as a way to add search-based playlist-building to my existing media player without having to commit to an additional indexing daemon.)

      I use the -e mplayer support in combination with my F12-triggered quake-style terminal as a faster alternative to navigating my way through the file system, finding the files I want, and then double-clicking them. (Especially when I want a playlist without having to use something heavier like SMPlayer)

  3. ohnonot says:

    thanks again.
    now it just says ‘no results’… 🙁
    but this add to playlist thing is good. wonder if it work with moc – haven’t installed any other player (yet).
    btw, can i ask you sth about you gtk recent scrubber? that’s what originally drew my attention to your other scripts…

    • Sure. Ask away. Probably better to move the conversation to e-mail for that though. Just use the From address on one of the notifications I sent you or the contact form linked in the blog header.

      The “no results” part should be fixed when I have time to design the new option parsing setup with more consistent and flexible behaviour between the various different personalities.

      I haven’t used MOC (Audacious is the only thing which plays all the weird chiptune formats I listen to) but give the MPRIS mode a try and, if it doesn’t work, figure out how to enqueue a bunch of paths from the command line and I’ll show you how to use --print0 or --exec to hook them up together.

Leave a Reply

Your email address will not be published. Required fields are marked *

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution under the same terms as the associated post.

All comments are moderated. If your comment is generic enough to apply to any post, it will be assumed to be spam. Borderline comments will have their URL field erased before being approved.