MOCP

A couple of weeks ago I figured that my logging for the MP3 playing did not work any more. So I fixed it and re-initiated a central storage place for the log file created by the Perl file. I also wanted to extend the Perl script with an md5checksum function that identifies the played songs, so I could track the files even if I renamed them. Well, that did not work.

I used the opportunity to replace the Perl script with ruby, since more and more of my scripts are being written in ruby anyway. Changing the parameter OnSongChange in the mocp config file with the new script was all that was necessary:

OnSongChange = "mocp.log.rb -f %f -l /home/user/played_songs.log"

Putting also the script in place:

#!/usr/bin/env ruby
# Script to logg the played songs from MOCP into a logfile or into a playlist.
#
require 'rubygems'
require 'thor'

module MocpLogger

  class MocpLogger < Thor

    class_option :file, :aliases => '-f', :type => :string, :required => true
    class_option :log, :aliases => '-l', :type => :string, :required => false
    class_option :playlist, :aliases => '-p', :type => :boolean, :required => false, :lazy_default => true

    default_task :default

    $metadata = [
        :artist   => '',
        :title    => '',
        :duration => '',
    ]

    $time_now = Time.new

    desc 'Default task', 'default', :hide => true
    def default

      if not options[:file].nil? and File.exists?(options[:file])
        $metadata = readExifData(options[:file])
        $metadata[:md5sum] = getMd5sum(options[:file])

        outputdata = {
          :timestamp => $time_now,
          :artist    => $metadata[:artist],
          :title     => $metadata[:title],
          :duration  => $metadata[:duration],
          :file      => options[:file],
          :md5sum    => $metadata[:md5sum],
        }

        if options[:playlist] and options[:log]
          writePlaylist(options[:log], outputdata)
        elsif options[:log]
          writeLogFile(options[:log], outputdata)
        end

      end

    end

    # Helper method to get the md5sum hash of a file
    desc 'Create md5sum', 'Create md5sum', :hide => true
    def getMd5sum(file)
     `md5sum #{file}`.split(' ').first
    end

    # Helper method to write the logfile
    desc 'Write Logfile', 'Write the logfile', :hide => true
    def writeLogFile(logfile, dataHash)
      dataHash.each do |key,value|
        dataHash[key.to_sym] = '"' + value.to_s + '"'
      end
      File.open(logfile,'a') { |file| file.write( dataHash.values.join(';').to_s + "\n" ) }
    end

    # Helper method to write the playlist
    desc 'Write playlist', 'Write the playlist', :hide => true
    def writePlaylist(playlistfile, dataHash)

      # Adjust file-extension if necessary
      if not File.extname(playlistfile) == '.m3u'
        playlistfile  = playlistfile + '.m3u'
      end

      if not File.exists?(playlistfile)
        File.open(playlistfile,'w') { |file| file.write ( "#EXTM3U\n" ) }
      end
      File.open(playlistfile,'a') { |file| file.write ( "#EXTINF:#{dataHash[:duration]},#{dataHash[:title]} - #{dataHash[:artist]}\n" + dataHash[:file] + "\n" ) }
    end

    # Helper Method to get some stuff from the file.
    desc 'Read ExifData', 'Read Exif Data', :hide => true
    def readExifData(inputFile)
      data = Hash.new
      exifData = `exiftool #{inputFile}`
      exifData.each_line do |line|
        matches = line.match(/^(?<key>\D+)\ \:\ (?<value>.*)$/)
        if not matches.nil?
          case matches[:key]
          when /artist/i
            data[:artist] = matches[:value].chomp
          when /title/i
            data[:title] = matches[:value].chomp
          when /duration/i
            timematches = matches[:value].match(/(?<hours>\d{1,3})\:(?<minutes>\d{2})\:(?<seconds>\d{2})/)
            data[:duration] = timematches[:hours].to_i * 3600 + timematches[:minutes].to_i * 60 + timematches[:seconds].to_i
          end
        end
      end
      data
    end

  end

end

MocpLogger::MocpLogger.start

Now the script will read the MP3 tags and create a logfile that can later be used to run some statistics:

...
"2016-01-01 21:40:40 +0100";"Alt-J";"Breezeblocks";"227";"/musikk/alt_j/2012-an_awesome_wave/04-breezeblocks.mp3";"fe8a235cb155acce66877daffc2742b1"
"2016-01-01 21:44:27 +0100";"Alt-J";"(Interlude 2)";"77";"/musikk/alt_j/2012-an_awesome_wave/05-interlude_2.mp3";"2f572d35e92f483ae495a46f88239f3c"
"2016-01-01 21:45:45 +0100";"Alt-J";"Something Good";"218";"/musikk/alt_j/2012-an_awesome_wave/06-something_good.mp3";"d33bc929446b4d8acf2e15c724900422"
"2016-01-01 21:49:23 +0100";"Alt-J";"Dissolve Me";"239";"/musikk/alt_j/2012-an_awesome_wave/07-dissolve_me.mp3";"f79102b3dfed575505b5c6a609e2eee9"