view vixm/ui.py @ 7:f87b969fa973

Little cleanup; change of plans - try to make it more like ed first
author Josef "Jeff" Sipek <jeffpc@josefsipek.net>
date Sat, 19 Aug 2006 17:23:15 -0400
parents 50745af6a63b
children 79340745c952
line wrap: on
line source

# all the user interface related bits

import time, sys
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: %d. %s (%s)" % (id, s["title"],
				util.strtime(s["time"]))
		self.lists[playlist.LIST_PRIO].enqueue(s)

	def __list(self, cmd, parts):
		i = 1

		if len(parts) > 1:
			try:
				listid = int(parts[1])
				if listid < 0 or listid >= len(self.lists):
					raise ValueError
			except:
				print "Invalid list number"
				return
		else:
			listid = playlist.LIST_PRIO

		for s in self.lists[listid]:
			print "%d. %s (%s)" % (i, s["title"],
					util.strtime(s["time"]))
			i += 1

	def __cmd(self, txt):
		parts = txt.split()
		cmd = parts[0]

		# 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 '$'.

		if cmd == "quit":
			self.shutdown = True
		elif cmd == "list":
			self.__list(cmd, parts)
		elif cmd == "lists":
			print "#0 LIST_PRIO"
			print "#1 LIST_DEFAULT"
		else:
			print "Invalid command \"%s\"" % (cmd,)

	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 and enqueues
				try:
					id = int(tmp[1:])
				except:
					self.__cmd(tmp[1:])
					continue

				# we got something numeric, let's enqueue
				self.__enqueue(id)