#!/usr/bin/env python import os, sys, signal, time, urllib, math debug = False # write a debug message if debugging is enabled def debugmsg(dbgstring): global debug if debug: global dbgout dbgout.write(dbgstring+"\n") dbgout.flush() # prepare the context menu items def initmenu(): os.system('dcop amarok script addCustomMenuItem "QuickMark" "Set Mark"') os.system('dcop amarok script addCustomMenuItem "QuickMark" "Clear All Marks"') # delete the context menu items def cleanmenu(signum, frame): os.system('dcop amarok script removeCustomMenuItem "QuickMark" "Set Mark"') os.system('dcop amarok script removeCustomMenuItem "QuickMark" "Clear All Marks"') cleanmarks() # clear all marks def cleanmarks(): global marklist for mark in marklist: os.system('dcop amarok script removeCustomMenuItem "QuickMark" "'+maketitle(mark)+'"') marklist = [ ] # make a context menu item title from a mark def maketitle(mark): return 'Mark '+mark['num']+': '+mark['title'] # open debugging output if debugging enabled if debug: dbgout = file('/tmp/quickmark-debug.txt','w+') debugmsg('Init') # set up menu context entries initmenu() # trap death for killing context menu entries signal.signal(signal.SIGTERM, cleanmenu) # perpare the list of marks marklist = [ ] # main loop while True: # read amarok input stdinbuf = sys.stdin.readline() debugmsg('STDIN: '+stdinbuf) data = stdinbuf.split() # if its a context menu click on one of our entries if data[0] == 'customMenuClicked:' and data[1] == 'QuickMark': # if its a mark selection if data[2] == 'Mark': # find what mark was selected mark = marklist[ int(data[3].replace(':','')) - 1 ] # mute the player, load the media, seek, unmute, and report in status bar os.system('dcop amarok player mute') os.system('dcop amarok playlist playMedia "'+str(mark['url'])+'"') # this delay prevents a bug when playMedia is called on a file which isnt in the playlist -- # apparently seek is called before playMedia finishes loading the file into the playlist, and the # seek does not take place.. this is a bad hack.. my guess is on a real slow machine, we'd # need *more* of a delay to prevent it but I figure 1 second should be long enough to load a # damn track.. I thought of making it poll dcop to tell when the current URL matches the URL we # call, but that seems so inefficient (though it would be slow-machine friendly...) time.sleep(1) os.system('dcop amarok player seek '+str(mark['pos'])) os.system('dcop amarok player mute') os.system('dcop amarok playlist shortStatusMessage "QuickMark: Mark loaded ('+mark['title']+')"') debugmsg('Loaded mark: '+mark['url']+' pos '+str(mark['pos'])) # if its a mark set elif data[2] == 'Set': playerstatus = int(os.popen('dcop amarok player status').readline().strip()) debugmsg('Player status: '+str(playerstatus)) if playerstatus in [1,2]: # load pertinent data fileURL = os.popen('dcop amarok player encodedURL').readline().strip() filePos = os.popen('dcop amarok player trackCurrentTime').readline().strip() # make a marklist entry for this num = len(marklist)+1 # format a nice time nicetime = str(int(math.floor(int(filePos) / 60)))+':'+str( int(filePos) % 60 ).rjust(2,'0') # format a nice title artist = os.popen('dcop amarok player artist').readline().strip() track = os.popen('dcop amarok player title').readline().strip() title = artist+' - '+track cutlen = 50 if len(title) > cutlen: showtitle = urllib.unquote(title[:cutlen]+'...') + ' @'+nicetime else: showtitle = urllib.unquote(title) + ' @'+nicetime # make the mark mark = { 'num': str(num), 'url':fileURL, 'pos':filePos, 'title':showtitle } marklist.append(mark) # add the context menu entry for this mark os.system('dcop amarok script addCustomMenuItem "QuickMark" "'+maketitle(mark)+'"') # report in statusbar mark was created os.system('dcop amarok playlist shortStatusMessage "QuickMark: Mark set ('+mark['title']+')"') # debug debugmsg('Set mark: '+mark['url']+' pos '+str(mark['pos'])) else: os.system('dcop amarok playlist shortStatusMessage "QuickMark: Cannot set marks while stopped."') # if its a request to clear all marks elif data[2] == 'Clear': # clear all marks cleanmarks() os.system('dcop amarok playlist shortStatusMessage "QuickMark: Cleared all marks"') # clearing all marks debugmsg('Cleared all marks')