Playing a local file or directory from the command line

I’ve got mopidy 2.2.3 setup with the local-sqlite plugin for playing music stored on a local disk. For normal use, everything is working well!

Sometimes though, I want to play a specific file or folder of files from the command line, where I have the file/folder name and path. At that point, going to the UI and seaching for the file is a bit of pain.

Based on earlier posts here, I’ve written a script that wraps mpc to do this. The script (see below) doesn’t quite do everything, and is longer than I initially expected… Before I finish it off, I wanted to check if this was still the best way to go about doing something like this?

A few issues, most worked around:

  • File names need to be relative to the root of the media_dir setting, then prefixed with “local:track:”
  • File names need to be URL escaped (eg for spaces)
  • “mpc add” doesn’t seem to work with directories, need to list all the files in a directory and add them individually not sure if this is the best solution
  • Only files which have been seen by a “mopidy local scan” can be added/played, anything added since then will refuse to add problem unsolved

Is there a better way? Can I do the directory thing better? Can I handle un-scanned files?

The (I think) relevant bit of my mopidy config is

[local]
library = sqlite
scan_flush_threshold = 100
media_dir = /media/music/music/

And the script I’ve written (only takes a single argument at the moment, of a single file or folder to play) is

#!/bin/bash
# Plays a single file File or Directory, which is located within the 
#  Local Library area
# TODO Support multiple files / directories, wildcard arguments etc

# Mopidy Local media_dir directory
BASE="/media/music/music/"
# URI prefix used by Mopidy for local files
MPREFIX="local:track:"

# Zap any playlist that might exist
mpc clear

# Grab the single argument of the file or directory to play
MUSIC=$1
# Convert to an absolute path, so we're consistent on relative vs absolute
MUSIC=`readlink -f $MUSIC`

# Let the user know what we're adding, before we mangle stuff (more)
echo ""
echo "Adding music from $MUSIC"

# Converts a file to a suitable URL with prefix and escaping
function add {
   RPATH=${1#"$BASE"}
   echo " - $RPATH"

   ESCPATH=$(python -c "import urllib, sys; print urllib.quote(sys.argv[1])"  "$RPATH")
   mpc add "${MPREFIX}${ESCPATH}"
}

# Directories are not supported, so find and add all files within them
if [[ -d $MUSIC ]]; then
   find $MUSIC -type f -print0 | sort -z | while read -d $'\0' FILE
   do
      add "$FILE"
   done
else
   add "$MUSIC"
fi

# Off we go!
echo ""
mpc play

This is an old verison of Mopidy, FYI we won’t fix issues in this version.

With regards to scanning, check out the file backend.

Thanks for the version tip! I hadn’t realised how behind the version in Ubuntu was. I’ve swapped to using the mopidy apt repo

I’ve had a try with the file backend. Config used (snippet) is now:

[local]
library = sqlite
scan_flush_threshold = 100
media_dir = /media/music/music/

[file]
media_dirs = /media/music/music/

With this in place, I can do “mpc add file:///path/to/music/file” and have the specific file played. Adding a directory doesn’t seem to work, still seem to have to list all the files in the directory myself and add them individually. I assume that’s expected?

One other difference between using the local backend “local:track:relative-path” URIs and the file-based “file:///” ones is that the local ones get album art while the file ones don’t.

Is not required for the latest version of Mopidy-Local.

I thought we did correctly support adding directories but I’m not as a computer right now to try it. Is there anything in the log reporting an error?

Correct, there’s no album art support. There’s an issue and I think even a PR for it.

OK, I looked at your script and I think I understand your issue with adding tracks. You cannot infer anything from Mopidy URIs (other than the scheme). In this case, you cannot infer any sort of directory structure. For example, I have a track with URI:

local:track:USB/Converge%20-%20You%20Fail%20Me/07%20You%20Fail%20Me.mp3

But the fact that resembles the directory structure on the filesystem cannot be assumed, it just happens to be the current implementation. Clients shouldn’t try and build or manipulate these Mopidy URIs. For example, even though the file on my filesystem is located in “/var/lib/mopidy/media/USB/Converge - You Fail Me/” , none of the following mean anything to Mopidy-Local:

local:track:USB/Converge%20-%20You%20Fail%20Me
local:directory:USB/Converge%20-%20You%20Fail%20Me
local:track:USB/Converge%20-%20You%20Fail%20Me/../

You should only use URIs that Mopidy has given you. In this case I need to do:

mpc add "Local media/Albums/You Fail Me"

And I get that URI by browsing Mopidy’s virtual filesystem.

Mopidy-Local hides the actual system filesystem. Mopidy-File is probably more what you want as it directly exposes the filesystem.