Mercurial > vixm
view vixm/ui.py @ 8:79340745c952
Reimplemented enqueuing & quit properly, implemented list and number commands
author | Josef "Jeff" Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 19 Aug 2006 19:41:06 -0400 |
parents | f87b969fa973 |
children | eaa800169f5b |
line wrap: on
line source
# all the user interface related bits import time, sys, re from threading import Thread import xmms import playlist, song, util def run(): """ this is where we start execution """ # first, let's create the two playlists print "Creating playlists..." lists = {} lists[playlist.LIST_PRIO] = playlist.playlist() lists[playlist.LIST_DEFAULT] = playlist.playlist(allowrandom=True) # read in the info for all the songs in XMMS's playlist print "Loading songs from XMMS's playlist..." songs = [] listlength = xmms.control.get_playlist_length() for i in range(0,listlength): s = song.song(i) lists[playlist.LIST_DEFAULT].enqueue(s) print "Instanciating ui thread..." ui = uiThread(lists) ui.start() while not ui.shutdown: time.sleep(1) class uiThread(Thread): """ This is the main ui thread class, it does all the magic necessary to have a vi-like interface """ def __init__(self, lists): Thread.__init__(self) self.lists = lists self.shutdown = False def __enqueue(self, id): s = self.lists[playlist.LIST_DEFAULT][id] print "Enqueuing song: %s (%s)" % (s["title"], util.strtime(s["time"])) self.lists[playlist.LIST_PRIO].enqueue(s) def __cmd(self, txt): # commad list: # quit 'q[!]' # quit fails if there are list changes in # memory that haven't been saved. The optional # '!' forces the quit # # number '[range]n [playlistid]' # prints playlist [playlistid] (default is # LIST_PRIO) with each entry being numbered. # If optional range is supplied, only the # songs in that range are printed. The range # string is standard ed-like line range (see # below for details) # # list '[range]l [playlistid]' # virtually identical to the number command # above, however the lines are not numbered. # The same rules apply to the range and # playlistid arguments # # enqueue 'a songid' # enqueue a song songid from LIST_DEFAULT onto # LIST_PRIO. The enqueued song is added to the # end of LIST_PRIO # # dequeue 'd songid' # remove songid from LIST_PRIO. The songid is # the id in LIST_PRIO, NOT LIST_DEFAULT # # range: # '' first entry; shortcut for '1' # '%' entire list; shortcut for '1,$' # '$' last entry # 'n' entry on line n # 'm,n' range of entries starting on line m and # ending on line n. Both m and n are included # in the list. m or n can both be an integer, # '' or '$'. # command table format: # "command regexp": # (function to call, range allowed) def __cmd_quit(ui, start, stop, args): ui.shutdown = True def __cmd_number(ui, start, stop, args): __do_list(ui, start, stop, True, args) def __cmd_list(ui, start, stop, args): __do_list(ui, start, stop, False, args) def __cmd_enqueue(ui, start, stop, args): try: id = int(args[0])-1 if (id < 0) or \ (id >= len(ui.lists[playlist.LIST_DEFAULT])): raise ValueError except ValueError: print "Invalid song id" return ui.__enqueue(id) def __cmd_dequeue(ui, start, stop, args): print "not implemented yet" def __do_list(ui, start, stop, number, args): # get the list id from the argument or default to # LIST_PRIO try: if args[1]: listid = int(args[1]) else: listid = playlist.LIST_PRIO if listid < 0 or listid >= len(ui.lists): raise ValueError except ValueError, e: print "Invalid list number" raise e max = len(ui.lists[listid]) if not max: return start = fixupint(start, max) stop = fixupint(stop, max) # starting number should be less than the ending # number, as well as positive; ending number should # be less than or equal to the size of the playlist if start > stop or \ start < 1 or \ stop > max: raise ValueError i = 1 pfx = "" for s in ui.lists[listid]: if i < start or i > stop: i += 1 continue if number: pfx = "%d. " % (i,) print "%s%s (%s)" % (pfx, s["title"], util.strtime(s["time"])) i += 1 cmdtable = { "q([!]){,1}": (__cmd_quit, False), "n( ([0-9]+)){,1}": (__cmd_number, True), "l( ([0-9]+)){,1}": (__cmd_list, True), "a ([0-9]+)": (__cmd_enqueue, False), "d ([0-9]+)": (__cmd_dequeue, False), } def special2int(s): if s == '$': return -1 if s == '': return 1 return int(s) def fixupint(i, m): if i == -1: return m return i range_str = "(%|\\$|(\\$|[0-9]+){,1}(,(\\$|[0-9]+)){,1}){,1}" for c in cmdtable: rstr = "^" rstr += (cmdtable[c][1] and range_str or "") rstr += c rstr += "$" m = re.search(rstr, txt) if not m: continue gr = m.groups() start = end = -1 if cmdtable[c][1]: # parse range info if gr[3]: # we got a 'm,n' start = (gr[1] or '') end = gr[3] elif gr[1]: # we got a 'n' start = gr[1] end = gr[1] elif gr[0]: # we got a '$' or '%' start = (gr[0] == '%' and '1' or '$') end = '$' else: # no range specified start = '1' end = '1' start = special2int(start) end = special2int(end) gr = list(gr) gr.pop(0) gr.pop(0) gr.pop(0) gr.pop(0) gr = tuple(gr) try: cmdtable[c][0](self, start, end, gr) except ValueError: print "Invalid argument/value" return print "Invalid command \"%s\"" % (txt,) def run(self): while not self.shutdown: tmp = sys.stdin.readline().strip() # FIXME: we should use regexps for this # # search: '^\/(.+)' # enqueue: '^([0-9]+)' # commands: '^([A-Za-z]+)(([^ ]*) *)*' if tmp.startswith("/"): # '/ABC' - searching print "Searching not yet implemented" else: # 'ABC' - commands self.__cmd(tmp)