Autarchy of the Private Cave

Tiny bits of bioinformatics, [web-]programming etc

    Generate .mood moodbar files for your whole music collection

    10th April 2011

    Amarok moodbar wiki page has 2 nice scripts to generate .mood files for your whole music collection (to be displayed by amarok when playing).

    Both scripts should be started from the directory where you keep your music. The .mood files will be generated next to the source music files (in the same directories). You can modify the scripts to have the moods stored to $HOME/.kde/share/apps/amarok/moods/, so as not to clutter your music directories.

    Script for multicore CPUs (will not overwrite existing mood files):

    #!/bin/bash
    NUMCPU="$(grep ^processor /proc/cpuinfo | wc -l)"

    find . -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma)' | while read i ; do

    while [ `jobs -p | wc -l` -ge $NUMCPU ] ; do
    sleep 0.1
    done

    TEMP="${i%.*}.mood"
    OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'`
    if [ ! -e "$OUTF" ] ; then
    moodbar -o "$OUTF" "$i" &
    fi
    done

    Script for single-threaded moods generation (will only overwrite the last-generated mood file from a previous run):

    #!/bin/bash
    DIR=${1:-.}
    LAST=.moodbar-lastreadsong
    C_RET=0

    control_c() # run if user hits control-c
    {
    echo "$1" > "$LAST"
    echo "Exiting..."
    exit
    }

    if [ -e "$LAST" ]; then
    read filetodelete < "$LAST" rm "$filetodelete" "$LAST" fi exec 9< <(find "$DIR" -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma)') # you may need to add m4a and mp4 while read i do TEMP="${i%.*}.mood" OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'` trap 'control_c "$OUTF"' INT if [ ! -e "$OUTF" ] || [ "$i" -nt "$OUTF" ]; then moodbar -o "$OUTF" "$i" || { C_RET=1; echo "An error occurred!" >&2; }
    fi
    done <&9 exec 9<&- exit $C_RET

    That same page has a link to an older, somewhat more polished ruby script for the same task. It requires a running instance of Amarok, and uses it's media collection to find music files and create mood files for them. This script can potentially (after a little editing) store .mood files either with the music or to the $HOME/.kde/... path mentioned above. It is for an older version of Amarok, and thus is not likely to work with e.g. Amarok 2.4


    #!/usr/bin/ruby

    # Simple moodbar file management utility by Joe Rabinoff
    # This is also my first ever ruby script so bear with me

    $moodbar_folder = "#{ENV['HOME']}/.kde/share/apps/amarok/moods/"

    def usage()
    print "This is the moodbar file management utility\n"
    print "\n"
    print "Usage is:\n"
    print " moodbar_util.rb -rename Rename mood files" \
    + " from any old naming scheme to the current one\n" \
    + " (not applicable when mood" \
    + " files are stored with music)\n"
    print " moodbar_util.rb -calcall Calculate all un-calculated" \
    + " mood files\n"
    exit(1)
    end

    def check_amarok_running()
    result = `dcop 'amarok*'`.split("\n")
    return (result.length > 0)
    end

    def get_devices()
    result = `dcop amarok collection query 'SELECT id, lastmountpoint FROM devices;'`.split("\n")
    ret = Hash.new()
    result.each_index do |i|
    ret[result[i].to_i] = result[i+1] if i % 2 == 0
    end
    return ret
    end

    def mood_name(url, deviceid)
    ret = url.gsub(/\//, ',')
    return deviceid.to_s + "," + ret
    end

    def rename()
    print "Renaming mood files from outdated naming schemes...\n"

    # As far as I can tell, the best way to do this is just select all
    # tracks, check the old possible moodbar names, and rename them
    tracks = `dcop amarok collection query 'SELECT url, deviceid FROM tags;'`.split("\n")
    devices = get_devices

    0.step(tracks.length-1, 2) do |i|
    url = tracks[i].sub(/\.[^\.]*$/, '.mood')
    deviceid = tracks[i+1].to_i

    path = url.sub(/\./, '')
    if devices.has_key?(deviceid)
    path = devices[deviceid] + path
    end
    moodfile = $moodbar_folder + mood_name(url, deviceid)
    moodfile1 = $moodbar_folder + path.gsub(/\//, ',')

    next if FileTest.exists?(moodfile)

    if FileTest.exists?(moodfile1)
    system("mv", "-f", moodfile1, moodfile)
    print "Moved ", moodfile1, " to ", moodfile, "\n"
    end

    end

    end

    def calcall()
    print "Calculating all nonexisting moodbars...\n\n"

    tracks = `dcop amarok collection query 'SELECT url, deviceid FROM tags;'`.split("\n")
    devices = get_devices
    withMusic = (`dcop amarok script readConfig MoodsWithMusic`.chomp == "true")

    0.step(tracks.length-1, 2) do |i|
    url = tracks[i]
    deviceid = tracks[i+1].to_i

    moodfile = ""

    songpath = url.sub(/\./, '')
    if devices.has_key?(deviceid)
    songpath = devices[deviceid] + songpath
    end

    if withMusic
    moodfile = songpath.sub(/\.[^\.]*$/, '.mood')
    moodfile = File.dirname(moodfile) + "/." + File.basename(moodfile)
    else
    moodfile = $moodbar_folder \
    + mood_name(url.sub(/\.[^\.]*$/, '.mood'), deviceid)
    end

    next if FileTest.exists?(moodfile) && FileTest.size(moodfile) > 0
    next unless FileTest.exists?(songpath)

    print "Saving moodbar for ", songpath, "\n"
    print " to file ", moodfile, "\n"
    system("moodbar", "-o", moodfile, songpath)
    print "\n"

    end

    end

    $mode = ARGV[0]

    if !check_amarok_running
    print "Amarok is not running! Please start Amarok and re-run " \
    "this script.\n"
    end

    if $mode == "-rename"
    rename
    elsif $mode == "-calcall"
    calcall
    else
    usage
    end

    StumbleUponDeliciousCiteULikePocketKindle ItEvernotePinterestShare

    3 Responses to “Generate .mood moodbar files for your whole music collection”

    1. Scott Says:

      The shell script offered on KDE.org for multi-core CPUs will peg all cores at 100% and eventually lock up the machine even without using all available RAM. This version takes steps to avoid that problem.


      #!/bin/bash -

      # This program creates moodbar files for use with Amarok. It is designed for
      # multi-core processors, but will also run on single-core processors. This is
      # a modified version of the script offered on KDE's website. Changes in this
      # version include using $HOME/Music by default unless a different directory is
      # specified on the command line, changing $NUMCPU to $NUMTHREADS, using one-
      # less core than is installed in the system, and launching moodbar using nice.
      # I found that the version on KDE's site pegged all 8 cores in my CPU and
      # locked up my computer after a time while using very little of the 32GB of
      # installed RAM. Additionally, I included several more filename extensions to
      # the regex in the find command line.
      #
      # This version is designed to be run from a cron job. Mine is set up to run
      # once per week. This version also checks to ensure that moodbar is installed.
      #
      # On dual-core and single-core processors this program will run one instance
      # of moodbar. Effectively, only quad-core, or higher, processors will be used
      # with multiple threads of execution. Moodbar is very CPU-intensive. Nice is
      # about all that can be done to hold it back on single-core CPUs. On dual-
      # core, and higher, CPUs, one core is held in reserve for other tasks as an
      # additional measure.
      if ! which moodbar &>/dev/null; then
      echo 'moodbar must be installed to use this program'
      exit 1
      fi
      MUSIC=${1:-$HOME/Music}
      if [[ -d $MUSIC ]]; then
      cd $MUSIC
      else
      echo "$MUSIC is not a directory or does not exist"
      exit 1
      fi
      NUMTHREADS=$(( $(grep ^processor /proc/cpuinfo | wc -l) - 1 ))
      [[ $NUMTHREADS -gt 0 ]] || NUMTHREADS=1
      find . -type f -regextype posix-awk \
      -iregex '.*\.(wav|mp3|ogg|oga|flac|fla|wma|aiff|aac|m4a)' | \
      while read i ; do
      while [[ $(jobs -p | wc -l) -ge $NUMTHREADS ]] ; do
      sleep 0.1
      done
      TEMP="${i%.*}.mood"
      OUTF=$(sed 's#\(.*\)/\([^,]*\)#\1/.\2#' <</dev/null &
      fi
      done

    2. Scott Says:


      if [[ ! -e "$OUTF" ]] ; then
      nice moodbar -o "$OUTF" "$i" &>/dev/null &

      Somehow this code was not included in my previous comment. it goes just above the “fi” at the end of the script

    3. Bogdan Says:

      Scott,
      thanks for sharing!

      I think I haven’t used mood files generation since I’ve switched to Clementine as my primary music player and configured BitTorrent Sync of my music between 3 PCs I’m using the most frequently… This setup seems to only have minor drawbacks, and lots of benefits – including in-file storage of rating, score, play and skip counts, so that every separate Clementine instance will be aware of updates made on other PCs.

    Leave a Reply

    XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>