#!/usr/bin/env python
#-*- coding: utf-8 -*-

# Mostly written by Daelstorm
# Based on code written by deadchip from BMP-Remote-PyGTK,

import cgi
import dbus
import dbus.glib
import curses
import gtk, gobject
import os, sys
import select, string, re, ConfigParser, codecs, locale, thread, signal
import time
from time import sleep
import threading, time,  getopt, pwd

version = "0.2.6"

config_dir = str(os.path.expanduser("~/.bmpty/"))
config_file = config_dir+"config"

charset = None
terminal_title = None

def usage():
	print ("""BMPty is a D-Bus client for BMPx, the Next-Generation Music Player
Authors: Daelstorm, Deadchip & the BMPx team
Version: %s
	Default options: none
	-c,	--config <file>		Use a different config file
	-v,	--version		Display version and quit
	-r,	--charset <encoding>	Examples: iso8859-1(default), utf-8,
					iso8859-7, iso8859-15
					Recommended: Gnome-Terminal

	-t,	--title-enable		Terminal's title set to Track
	-d,	--title-disable		Terminal's title never set
	-h,	--help			Display this help and exit
	""" %version)
	sys.exit(2)
	
try:
	opts, args = getopt.getopt(sys.argv[1:], "hc:r:vtd", ["help", "config=", "charset=", "version", "title-enable", "title-disable"])
	
except getopt.GetoptError:
	usage()
	sys.exit(2)
for opts, args in opts:
	if opts in ("-h", "--help"):
		usage()
		sys.exit()
	if opts in ("-c", "--config"):
		#print args
		config_file=str(os.path.expanduser(args))
	if opts in ("-r", "--charset"):
		print args
		charset=str(os.path.expanduser(args))
	if opts in ("-t", "--title-enable"):
		terminal_title = "yes"
	if opts in ("-d", "--title-disable"):
		terminal_title = "no"
	if opts in ("-v", "--version"):
		print "BMPty version: %s" % version
		sys.exit(2)
		
parser = ConfigParser.ConfigParser()

# default config
bmpty_config = {"display":{"title_format":'long', "terminal_title": "no", "charset": "iso8859-1" } 	}

	
supported_formats = ["mp3", "ogg", "flac", "mpc", "m4a", "aac"] # , "wma", "wav", "mod"]

def create_config():
	parser.read([config_file])

	bmpty_config_file = file(config_file, 'w')
	
	for i in bmpty_config.keys():
		if not parser.has_section(i):
			parser.add_section(i)
		for j in bmpty_config[i].keys():
			if j not in ["nonexisting", "hated", "options"]:
				parser.set(i,j, bmpty_config[i][j])
			else:
				parser.remove_option(i,j)
	parser.write(bmpty_config_file)
	bmpty_config_file.close()	


def read_config():
	
	parser.read([config_file])
	for i in parser.sections():
		for j in parser.options(i):
			val = parser.get(i,j, raw = 1)

			if j in ['title_format', 'terminal_title', "charset"] :
				bmpty_config[i][j] = val
			elif i == 'aliases':
				bmpty_config[i][j] = val
			else:
				try:
					bmpty_config[i][j] = eval(val, {})
				except:
					bmpty_config[i][j] = None

def update_config():
	bmpty_config_file = file(config_file, 'w')
	for i in bmpty_config.keys():
		if not parser.has_section(i):
			parser.add_section(i)
		for j in bmpty_config[i].keys():
			if j not in ["dead_config"]:
				parser.set(i,j, bmpty_config[i][j])
			else:
				parser.remove_option(i,j)
	parser.write(bmpty_config_file)
	bmpty_config_file.close()
	
def check_path():
	if os.path.exists(config_dir):
		if os.path.exists(config_file) and os.stat(config_file)[6] > 0:
			read_config()
		else:
			create_config()
			
	else:
		os.mkdir(config_dir, 0700)
		create_config()
check_path()


# Override Config Settings with Command-Line settings
if charset != None:
	bmpty_config["display"]["charset"] = charset
	
if terminal_title != None:
	bmpty_config["display"]["terminal_title"] = terminal_title

# Looping thread for key presses
class capturekeys( threading.Thread):
	def __init__(self, BMPMonitor):
		threading.Thread.__init__(self)

		self.BMPMonitor = BMPMonitor
		
		#self.stdscr = curses.initscr()
		self.BMPMonitor.stdscr = curses.initscr()
		self.BMPMonitor.h, self.BMPMonitor.w = self.BMPMonitor.stdscr.getmaxyx()
		
	def run(self):
		while 1:
			keys = []

			try:
				c = self.BMPMonitor.stdscr.getkey(self.BMPMonitor.h-1, self.BMPMonitor.edit.x)
				keys.append(c)
			except:
				pass

			if not keys:
				d = 1000
			else:
				d = 0
			
			sleep(0.01)
			while keys:
				#sleep(0.01)
				
				c, keys = keys[0], keys[1:]
				
				try:
					#self.BMPMonitor.error_bar("hello")

					if self.BMPMonitor.edit.process(c):
						# if TRUE
						
						line = self.BMPMonitor.edit.line
						yes = self.BMPMonitor.edit.inputmode
						#self.BMPMonitor.error_bar("ERROR: Linedit: " + str(line)+" " + str(yes))
						#sleep(1)
						
						#yes =0
						#if yes == 0:
						#	break
						if yes == 2:
							return
						else:
							pass
							#self.BMPMonitor.editwin.clear()
							#self.BMPMonitor.editwin.refresh()
							#self.BMPMonitor.edit.clear()
						#	self.BMPMonitor.edit.reset()
					
						
							
				except Exception, e:
					self.BMPMonitor.error_bar("ERROR: Process: " + str(e))


		
class BMPMonitor(capturekeys):
	def __init__(self):
		
		self.statusText = ''
		self.status=''
		self.title=''
		self.titlestring = ''
		self.lasttitle = ''
		self.uri = ''
		self.metadata = []
		self.length = 0
		self.stdscr = None
		self.currentTrack = 0
		self.selectedTracks =[]
		self.playlist_dict = {}
		self.highliteTrack =0
		self.playlists = []
		self.seeking = False
		self.activeplaylist = None
		self.statusstatic =  "00:00"
		self.current_pos = 0
		self.selectall=False
		self.from_a = 0
		if "title_format" in bmpty_config["display"]:
			pass
		else:
			bmpty_config["display"]["title_format"] = "long"
		
		# Init DBus shizzle
		
		
		
		try:
			self.bus = dbus.SessionBus()
		except:
			print "ERROR: D-Bus Session Not Found"
			os._exit(1)
		try:	
			self.bmpx_obj = self.bus.get_object('org.mpris.bmpx', '/org/mpris/bmpx/SystemControl')
			self.bmpx = dbus.Interface(self.bmpx_obj, 'org.mpris.bmpx')
			self.bmpx.connect_to_signal('SetPlaystatus', self.bmpx_set_playstatus)
		except:
			print "ERROR: BMPty Cannot Access BMPx via D-Bus"
			os._exit(1)
		# Start Curses
		#self.stdscr = curses.initscr()
		# Start Keygrabber
		self.capturekeys = capturekeys(self)
		self.stdscr.nodelay(1)	
		
		try:
			pass
		#curses.curs_set(0) # doesn't work in XTerm
		except:
			pass
		self.stdscr.keypad(1)
		curses.start_color()
		curses.noecho()
		
		
		#curses.mousemask(curses.BUTTON1_CLICKED)
		curses.mousemask(curses.ALL_MOUSE_EVENTS)
		#curses.mouseinterval(30)
		self.colors = {}
		if curses.has_colors() == True:
			try:
				curses.use_default_colors()
				curses.can_change_color()
				curses.init_pair(1, curses.COLOR_RED, -1)
				curses.init_pair(2, curses.COLOR_YELLOW, -1)
				curses.init_pair(3, curses.COLOR_CYAN, -1)
				curses.init_pair(4, curses.COLOR_BLUE, -1)
				curses.init_pair(5, curses.COLOR_GREEN, -1)
				curses.init_pair(6, curses.COLOR_BLACK, -1)
				curses.init_pair(7, curses.COLOR_WHITE, -1)
				curses.init_pair(8, curses.COLOR_MAGENTA, -1)
				curses.init_pair(9, 0, curses.COLOR_WHITE)
				curses.init_pair(10, curses.COLOR_GREEN, curses.COLOR_BLACK )
				curses.init_pair(11, curses.COLOR_YELLOW, curses.COLOR_BLACK)
				curses.init_pair(12, curses.COLOR_BLACK, curses.COLOR_CYAN)
				curses.init_pair(13, curses.COLOR_RED, curses.COLOR_WHITE)
				curses.init_pair(14, 0, curses.COLOR_RED)
				curses.init_pair(15,curses.COLOR_WHITE, curses.COLOR_BLUE)
				curses.init_pair(16,curses.COLOR_WHITE, curses.COLOR_YELLOW)
	
			except AttributeError:
				curses.init_pair(1, curses.COLOR_RED, 0)
				curses.init_pair(2, curses.COLOR_YELLOW, 0)
				curses.init_pair(3, curses.COLOR_CYAN, 0)
				curses.init_pair(4, curses.COLOR_BLUE, 0)
				curses.init_pair(5, curses.COLOR_GREEN, 0)
				curses.init_pair(6, curses.COLOR_BLACK, curses.COLOR_WHITE)
				curses.init_pair(7, curses.COLOR_WHITE, 0)
				curses.init_pair(8, curses.COLOR_MAGENTA, 0)
				curses.init_pair(9, 0, curses.COLOR_WHITE)
				curses.init_pair(10, curses.COLOR_GREEN, curses.COLOR_BLACK )
				curses.init_pair(11, curses.COLOR_YELLOW, curses.COLOR_BLACK)
				curses.init_pair(12, curses.COLOR_BLACK, curses.COLOR_CYAN)
				curses.init_pair(13, curses.COLOR_RED, curses.COLOR_WHITE)	
				curses.init_pair(14, 0, curses.COLOR_RED)
				curses.init_pair(15,curses.COLOR_WHITE, curses.COLOR_BLUE)
				curses.init_pair(16,curses.COLOR_WHITE, curses.COLOR_YELLOW)
				
			self.colors["red"] = curses.color_pair(1)
			self.colors["yellow"] = curses.color_pair(2)
			self.colors["yellowhite"] = curses.color_pair(16)
			self.colors["cyan"] =  curses.color_pair(3)
			self.colors["blue"] = curses.color_pair(4)
			self.colors["green"] =  curses.color_pair(5)
			self.colors["black"] = curses.color_pair(6)
			self.colors["white"] = curses.color_pair(7)
			self.colors["magenta"] = curses.color_pair(8)
			self.colors["greybg"] = curses.color_pair(9)
			self.colors["greenbg"] = curses.color_pair(10)
			self.colors["hotkey"] = curses.color_pair(11)
			self.colors["blackcyan"] = curses.color_pair(12)
			self.colors["redwhite"] = curses.color_pair(13)
			self.colors["blackred"] = curses.color_pair(14)
			self.colors["bluebg"] = curses.color_pair(15)
				
		else:
			self.colors["yellowhite"] = self.colors["bluebg"] = self.colors["blackcyan"] = self.colors["blackred"] = self.colors["redwhite"] =  self.colors["hotkey"] = self.colors["greenbg"] =self.colors["greybg"] = self.colors["magenta"] = self.colors["white"] = self.colors["black"] = self.colors["green"] =  self.colors["blue"] = self.colors["cyan"] = self.colors["yellow"] = self.colors["red"] =  curses.color_pair(0)
			
			
	
		
		self.bmpx.connect_to_signal('SetStreamPos',  self.bmpx_set_stream_pos)
		self.bmpx.connect_to_signal('SetVolume',     self.bmpx_set_volume)
		self.bmpx.connect_to_signal('TrackChange',     self.bmpx_track_change)
		self.bmpx.connect_to_signal('TracklistItemsAdded',     self.bmpx_playlist_item_added)
		self.bmpx.connect_to_signal('TracklistRowsSwapped',  self.bmpx_playlist_item_swapped)
		self.bmpx.connect_to_signal('TracklistItemsRemoved',       self.bmpx_playlist_item_removed)
		self.bmpx.connect_to_signal('TracklistListSorted',     self.bmpx_playlist_item_sorted)
		self.bmpx.connect_to_signal('ListAdded',     self.bmpx_playlist_added)
		self.bmpx.connect_to_signal('ListDeleted',     self.bmpx_playlist_added)
		self.bmpx.connect_to_signal('ListRenamed',     self.bmpx_playlist_added)
		#self.bmpx.connect_to_signal('AddUriList',     self.bmpx_playlist_new)
		self.bmpx.connect_to_signal('SetRepeat',     self.setrepeat)
		self.bmpx.connect_to_signal('SetShuffle',     self.setshuffle)
		
		self.bmpx.SendStatus()
		self.shuffle = self.bmpx.ShuffleGet()
		self.repeat = self.bmpx.RepeatGet()
	
		self.currentVolume = int( self.bmpx.VolumeGet() )
		self.currentBitrate = None
		self.update_info()
		self.set_title()
		self.instructionstring = [ \
"-Scroll List-"\
"\n Up/Down"\
"\n PgUp/PgDown"\
"\n-Items-"\
"\n Play:  Enter\n Select: Insert Select All: A"\
"\n Delete: Del"\
"\n Format: Alt-T"\
"\n-Lists-\n Reload: Alt-O"\
"\n New:    Alt-N"\
"\n Rename: Alt-R"\
"\n Delete: Alt-E"\
"\nFor more help,\nPress ?",
\
"\nVol:  - +"\
"\n-Switch list-\n      Alt-Left\n      Alt-Right"\
"Seek: Left"\
"\n      Right\nJump:      J\nAdd Files: I"\
"\nSave:      F2\nQuit:      F8\n\nFor more help,\nPress ?"]
	
	def setshuffle(self, bool):
		if bool != self.shuffle:
			self.shuffle = bool
			if self.shuffle == True:
				self.shuffwin.addstr("\nShuffle", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"] )
			else:
				self.shuffwin.addstr("\nShuffle", self.colors["redwhite"] | curses.A_REVERSE)
			self.shuffwin.refresh()
		
	def setrepeat(self, bool):
		if bool != self.repeat:
			self.repeat = bool
			if self.repeat == True:
				self.repwin.addstr("\nRepeat", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"] )
			else:
				self.repwin.addstr("\nRepeat", self.colors["redwhite"] | curses.A_REVERSE )
			self.repwin.refresh()

	def set_title(self):
		if bmpty_config["display"]["terminal_title"] == "yes":
			if os.path.expandvars("$SHELL") in  ("/bin/bash", "/bin/sh"):
				os.system("echo -ne \"\033]0;BMPty %s: %s [%s]\007\" " %(version, self.decode_language(self.titlestring), self.statusText))	
		else:
			return
		
	def bmpx_playlist_new(self, playlist_num):
		#print playlist_num
		self.build_playlists(-1)
		
	def bmpx_playlist_added(self, playlist_num):
		#print self.bmpx.GetTracklists()#self.playlists = self.bmpx.GetTracklists()
		self.build_playlists(-1)
		
	def bmpx_playlist_item_sorted(self, playlist_num):
		self.build_playlists(playlist_num)
	
	def bmpx_playlist_item_swapped(self, playlist_num, track_a, track_b):
		#self.error_bar("Playlist: %d T: %d N: %d" % (playlist_num, track_a, track_b))
		width = len(str(len( self.playlist_dict[playlist_num] ) ))
		string = self.playlist_dict[playlist_num][track_a]
		if track_b < track_a:
			del self.playlist_dict[playlist_num][track_a:track_a+1]
		else:
			del self.playlist_dict[playlist_num][track_a:track_a+1]
		self.playlist_dict[playlist_num].insert(track_b, string)
		self.display_playlist()

	def bmpx_playlist_item_added(self, playlist_num, tracks, track_nums):
		#self.error_bar("Playlist: %d T: %s N: %d" % (playlist_num, str(tracks), track_nums))
		
		#print "Playlist:", playlist_num, "Tracks:",tracks, "Number:",track_nums
		
		#sleep(1)
		width = len(str(len(self.playlist_dict[playlist_num])+ track_nums))
	
		for i in tracks:
			metadata =  self.bmpx.GetMetadataForListItem(playlist_num, i)
			string, time = self.getmetadata(i, metadata["location"], width)
			self.playlist_dict[playlist_num].insert(i, [string, time])
	
		self.display_playlist()
		'''
		'''
		#self.build_playlists(playlist_num)
		
	def bmpx_playlist_item_removed(self, playlist_num, tracks, track_nums):
		for i in tracks:
			del self.playlist_dict[playlist_num][i:i+1]
			
		self.display_playlist()
		
	def bmpx_track_change(self):
		self.update_info()
		self.set_title()
		
		if self.titlestring != self.lasttitle:
			try:
				self.onlinetitle.addstr("\n"+self.decode_language(self.titlestring)[:self.w-22])
				self.onlinetitle.refresh()
				
				self.titletime.addstr("\n"+self.statusstatic)
				self.titletime.refresh()
			except Exception, e:
				self.error_bar( "ERROR: title" + str(e))
	
		
		
		try:
			self.bitwin.addstr("\nBitRate: %s" % str(self.currentBitrate))
			self.bitwin.refresh()
		except Exception, e:
			self.error_bar("ERROR: modifying BitRatebox: " + str(e))
		self.display_playlist()
			
	def bmpx_button_press(self, widget, event):
		pass
	
	def bmpx_volume_changed(self, widget):
		
		volume = int(widget.get_value())
	
		if self.currentVolume != volume:
			self.currentVolume = volume
			self.bmpx.VolumeSet (volume)
	
	def bmpx_play_current(self, widget):
		self.bmpx.PlayCurrent()
	
	def bmpx_play_next(self, widget):
		self.bmpx.PlayNext()
	
	def bmpx_play_prev(self, widget):
		self.bmpx.PlayPrev()
	
	def bmpx_play_pause(self, widget):
		self.bmpx.PlayPause()
	
	def bmpx_play_stop(self, widget):
		self.bmpx.PlayStop()
	
	
	
	def bmpx_set_volume(self, volume):
	
		self.currentVolume = int(volume)
	
		#self.volwin.clear()
		self.volwin.addstr("\nVolume:  %s%%" % str(self.currentVolume))
		self.volwin.refresh()
	
	def bmpx_set_stream_pos(self, stream_pos):
		if self.seeking == False:
			minutes = int(stream_pos) / int(60)
			seconds = stream_pos % 60;
			self.current_pos = stream_pos
			minutes_length = int(self.length) / int(60)
			seconds_length = int(self.length) % int(60)
		
			self.statusnew ='%2.2d:%2.2d' % (minutes, seconds) 
			self.statusstatic = '%2.2d:%2.2d' % ( minutes_length, seconds_length)
			if self.status != self.statusnew:
				self.status = self.statusnew
				try:
					#self.onlinetime.clear()
	
					self.onlinetime.addstr("\n"+self.status)
					self.onlinetime.refresh()
					
				except Exception, e:
					self.error_bar( "ERROR: Online Time" + str(e))
		else:
			self.seeking = False
		
	def display_statusbox(self):
		try:
			
			if self.statusText == 'PAUSED':
				self.onlinestatus.addstr("\n%s:" %self.statusText)
			elif self.statusText == 'PLAYING':
				self.onlinestatus.addstr("\n%s:" %self.statusText)
			elif self.statusText == 'STOPPED':
				self.onlinestatus.addstr("\n%s:" %self.statusText)
			
			self.onlinestatus.refresh()
		except Exception, e:
			self.error_bar( "ERROR: Display Statusbox" + str(e))
			
	def decode_language(self, string):

		try:
			string = string.encode(bmpty_config["display"]["charset"])
		except:
			pass

		return string
		
	def bmpx_set_playstatus(self, playstatus):
	
		if playstatus == 2:	    #Stopped
			self.statusText = 'STOPPED'
		elif playstatus == 4:	    #Playing
			self.statusText = 'PLAYING'
		elif playstatus == 8:	    #Paused
			self.statusText = 'PAUSED'
		self.update_info()
		
		if self.titlestring != "":
			self.set_title()
		self.display_statusbox()
		self.onlinetitle.addstr("\n"+self.decode_language(self.titlestring)[:self.w-22])
		self.onlinetitle.refresh()
		return 1
	
	def run(self):
		self.capturekeys.start()
	
	
	def create_title(self):	
		try:
			self.set_title()
			
			self.highliteTrack=self.bmpx.GetCurrentTrack()
			
			self.onlinetitle =  curses.newwin(1, self.w-21, 0, 0)
			self.onlinetitle.bkgdset(" ", curses.A_REVERSE | curses.A_BOLD)
			self.onlinetitle.idlok(1)
			self.onlinetitle.scrollok(1)
			self.onlinetitle.clear()
			
			try:
				self.onlinetitle.addstr("\n"+self.decode_language(self.titlestring)[:self.w-22])
			except Exception,e:
				self.error_bar("title problem  %s" % str(e))
			self.onlinetitle.refresh()
			
			self.titletime =  curses.newwin(1, 6, 0, self.w-21)
			self.titletime.bkgdset(" ", curses.A_REVERSE | curses.A_BOLD)
			self.titletime.idlok(1)
			self.titletime.scrollok(1)
			self.titletime.clear()
			self.titletime.addstr("\n"+self.statusstatic)
			self.titletime.refresh()
			
		except Exception, e:
			self.error_bar("ERROR: title " + str(e)[:60])
			
	def create_errorbar(self):
		self.editwin = curses.newwin(0, self.w, self.h-1, 0)
		self.editwin.attron(self.colors["redwhite"])
		self.editwin.bkgdset(" ",  curses.A_REVERSE | self.colors["redwhite"])
		self.editwin.scrollok(1)
		self.editwin.idlok(1)
		self.editwin.clear()
		self.editwin.addstr("\nBMPty ", curses.A_REVERSE | self.colors["redwhite"])
		self.editwin.refresh()
		
	def create_mainwindow(self):
		try:
			self.mainowin =  curses.newwin(self.h-2, self.w-15, 1, 0)
			#self.mainowin.bkgdset(" ",   self.colors["greybg"])
			self.mainowin.idlok(1)
			self.mainowin.clear()
			self.mainowin.border()
			self.mainowin.refresh()
			
			self.mainwin =  self.mainowin.subwin(self.h-4, self.w-17, 2, 1)
			self.mainwin.scrollok(1)
			self.mainwin.idlok(1)
		except Exception,e :
			self.error_bar("ERROR: Creating MainWindow: "+ str( e)[:60])
			
	def create_instructions(self):
		try:
			self.instructions =  curses.newwin(self.h-7, 15, 4, self.w-15)
			self.helpshow = True
			self.instructions.bkgdset(" ",  curses.A_REVERSE| curses.A_BOLD| self.colors["greybg"])
			self.instructions.idlok(1)
			self.instructions.scrollok(1)
			self.instructions.clear()
			self.instructions.addstr(self.instructionstring[1])
			self.instructions.refresh()
		except Exception,e :
			self.error_bar("ERROR: Creating Instructions: "+ str( e)[:60])

			
	def create_timebox(self):
		try:
			self.onlinetime =  curses.newwin(1, 6, 0, self.w-6)
			self.onlinetime.bkgdset(" ",  curses.A_UNDERLINE|curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"])
			self.onlinetime.idlok(1)
			self.onlinetime.scrollok(1)
			self.onlinetime.clear()
			self.onlinetime.addstr("\n"+self.status)
			self.onlinetime.refresh()
		except Exception, e:
			self.error_bar("ERROR: Timebox: " + str(e)[:60])
			
	def create_volumebox(self):
		try:
			self.volwin =  curses.newwin(1, 15, 1, self.w-15)
			self.volwin.bkgdset(" ",  curses.A_UNDERLINE|curses.A_BOLD| self.colors["bluebg"])
			self.volwin.idlok(1)
			self.volwin.scrollok(1)
			self.volwin.clear()
			self.volwin.addstr("\nVolume:  %s%%" % str(self.currentVolume))
			self.volwin.refresh()
		except Exception, e:
			self.error_bar("ERROR: Volumebox: " + str(e))
			
	def create_bitratebox(self):
		try:
			self.bitwin =  curses.newwin(1, 15, 2, self.w-15)
			self.bitwin.bkgdset(" ",  curses.A_UNDERLINE|curses.A_BOLD| self.colors["bluebg"])
			self.bitwin.idlok(1)
			self.bitwin.scrollok(1)
			self.bitwin.clear()
			self.bitwin.addstr("\nBitRate: %s" % str(self.currentBitrate))
			self.bitwin.refresh()
		except Exception, e:
			self.error_bar("ERROR: BitRatebox: " + str(e))
			
	def create_repeatbox(self):
		try:
			
			self.repwin =  curses.newwin(1, 7, 3, self.w-7)
			self.repwin.bkgdset(" ")
			self.repwin.idlok(1)
			self.repwin.scrollok(1)
			self.repwin.clear()
			if self.repeat == True:
				self.repwin.addstr("\nRepeat", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"])
			else:
				self.repwin.addstr("\nRepeat",  self.colors["redwhite"] | curses.A_REVERSE)
			
			self.repwin.refresh()
		except Exception, e:
			self.error_bar("ERROR: Repeatbox: " + str(e))
			
	def create_shufflebox(self):
		try:
			
			self.shuffwin =  curses.newwin(1, 8, 3, self.w-15)
			self.shuffwin.bkgdset(" ")
			self.shuffwin.idlok(1)
			self.shuffwin.scrollok(1)
			self.shuffwin.clear()
			if self.shuffle == True:
				self.shuffwin.addstr("Shuffle", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"])
			else:
				self.shuffwin.addstr("Shuffle", self.colors["redwhite"] | curses.A_REVERSE)
			self.shuffwin.refresh()
			self.awin =  curses.newwin(1, 1, 4, self.w-8)

		except Exception, e:
			self.error_bar("ERROR: Shufflebox: " + str(e))
				
	def create_statusbox(self):
		try:

			self.onlinestatus =  curses.newwin(1, 9, 0, self.w-15)
			self.onlinestatus.bkgdset(" ",  curses.A_UNDERLINE|curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"])
			self.onlinestatus.idlok(1)
			self.onlinestatus.scrollok(1)
			self.onlinestatus.clear()
			self.display_statusbox()
		except Exception, e:
			self.error_bar("ERROR: Statusbox: " + str(e))
			
	def build(self, stdscr, line = ""):
		self.stdscr = stdscr
		self.stdscr.clear()
		self.stdscr.refresh()
		self.h, self.w = self.stdscr.getmaxyx()
		#if  self.h >=15 and self.w >=77:
		try:
			
			continue_build = 1
			#uri = self.bmpx.GetCurrentUri()
			#if uri[-3:] in ("ogg", "mp3"):
			#	metadata = self.bmpx.GetMetadataForUri(uri)
	
			self.create_errorbar()
			
			self.create_title()
			self.create_mainwindow()
			

			self.build_playlists(-1)
			
			self.create_timebox()
			self.create_volumebox()
			self.create_bitratebox()
			
			self.create_statusbox()
			self.create_shufflebox()
			self.create_repeatbox()
			
			self.create_instructions()
			
			self.playwin =  curses.newwin(2, 15, self.h-3, self.w-15)
			self.playwin.bkgdset(" ",  curses.A_REVERSE| curses.A_BOLD| self.colors["blackcyan"])
			self.playwin.idlok(1)
			self.playwin.scrollok(1)
			self.playwin.clear()
			self.playwin.addstr(" Z  X  C  V  B\n<< [> || [] >>")
			self.playwin.refresh()
			
		except Exception, e:
			self.error_bar("Error: Building" + str(e))

		try:
			self.edit = editor(self.editwin, self.mainowin, self, self.escaped, line)
			self.stdscr.nodelay(1)	
		except Exception,e :
			self.error_bar("ERROR: Edit window: "+ str( e))
		
		
	def error_bar(self, string):
		#self.editwin.clear()
		
		self.editwin.addstr("\n"+self.decode_language(str(string)))
		#self.editwin.addstr("\n"+string)
		self.editwin.refresh()
	
	def build_playlists(self, value):
		try:
			if self.bmpx.GetCurrentTracklistNumber() == -1:
				self.bmpx.CurrentTracklistSet(0)
				self.playlist_dict = {}
			else:
				self.playlist_dict[value] = []
			self.playlists = self.bmpx.GetTracklists()
			if self.activeplaylist == None:
				self.activeplaylist = self.bmpx.GetCurrentTracklistNumber()
			
	
			x = 0 # playlist number
			self.playliststamps ={}
			for playlist in self.playlists:
				#stamp = self.bmpx.GetTracklistTimestamp(x)
				#self.error_bar(stamp)
				'''
				if x not in self.playliststamps.keys():
					self.playliststamps[x] = stamp
				else:
					if stamp == self.playliststamps[x]:
						pass
					else:
						# Playlist was renamed
						pass
				'''
				if int(value) != -1: # Specific Playlist chooser
					if x != int(value):
						x += 1 # increase playlist number for non-chosen playlists
						continue
					
				t =0 # track number
				self.playlist_dict[x] = []
				try:
					thelist = self.bmpx.GetTracklist(x)

				except:
					self.error_bar("Problem with list: %d" % x)
	
				if  thelist == []:
					#self.playlist_dict[x] = []
					x +=1 # increase playlist number for empty playlists
					
					continue
	# 			if self.playlists != []:
	# 				if self.bmpx.GetCurrentTracklistNumber() in range(len(self.playlists)):
				
				width = len(str(len(thelist)))
				for track in thelist:
				
					string, time = self.getmetadata(t, track, width)
						
					#self.playlist_dict[x].append([t, string])
					self.playlist_dict[x].append([string, time])
				
					t +=1
				x += 1
				
			self.display_playlist()
	
			
		except Exception, e:
			self.error_bar(  "ERROR building playlist: " + str(e))
		
	def format_title_string(self, artist_s, album_s, track_nums, title_s):
		if bmpty_config["display"]["title_format"] == "long":
			if album_s != "" and artist_s != "" and track_nums !=str(0):
				titlestring  = "%s - %s - %s - %s" % (artist_s, album_s, track_nums, title_s)
				
			elif album_s == "" and artist_s != "":
				titlestring  = "%s - %s" % (artist_s,  title_s)
			elif artist_s == "" and album_s != "":
				titlestring  = "%s - %s" % (album_s,  title_s)
			elif artist_s == "" and album_s == "":
				titlestring  = "%s" % (title_s)
			else:
				titlestring  = "%s - %s - %s" % (artist_s, album_s, title_s)
		elif bmpty_config["display"]["title_format"] == "short":
			if artist_s != "":
				titlestring  = "%s - %s" % (artist_s, title_s)
			else:
				titlestring  = "%s" % (title_s)
		elif bmpty_config["display"]["title_format"] == "title":
			titlestring  = "%s" % (title_s)
		elif bmpty_config["display"]["title_format"] == "brackets":
			if artist_s != "":
				titlestring  = "[%s] - %s" % (artist_s, title_s)
			else:
				titlestring  = "%s" % (title_s)
		return titlestring
			
	def getmetadata(self, t, TRACK, WIDTH):

		if TRACK[-3:] in supported_formats or TRACK[:4] in ("cdda", "http"):
			metadata = self.bmpx.GetMetadataForUri(TRACK)
			try:
				title_s = cgi.escape(metadata['title']).strip()
				title_s = title_s.replace("&amp;", "&")
			except:
				if TRACK[:4] == "cdda":
					s = TRACK.split("/")
					title_s = "CDrom track %s " % s[-1]
				else:
					title_s = TRACK
			try:
				artist_s = cgi.escape(metadata['artist']).strip()
				artist_s = artist_s.replace("&amp;", "&")
			except:
				artist_s = ""
			try:	
				album_s = cgi.escape(metadata['album']).strip()
				album_s = album_s.replace("&amp;", "&")
			except:
				album_s = ""
			try:
				length = int(metadata['time'])
			except:
				length=0
			try:
				track_nums = cgi.escape(metadata['track-number']).strip()
			except:
				track_nums = 0

		else:
			length = 0
			track_nums = 0
			artist_s = ""
			album_s = ""
			title_s = TRACK[7:-4]
		
		titlestring = self.format_title_string(artist_s, album_s, track_nums, title_s)

		minutes = int(length)/60
		seconds = str( int(length) - (60 * minutes))
		minutes= str(minutes)
		if len(minutes) < 2:
			minutes = '0' + minutes
		if len(seconds) < 2:
			seconds = '0' + seconds
			
		time = minutes+":"+str(seconds)
		return titlestring, time

	def update_info(self):
		try:
			self.uri = self.bmpx.GetCurrentUri()
		except:
			self.uri =""
		if self.uri == "":
			return 0
		
		TRACK = self.uri
		if self.uri[-3:] in supported_formats  or self.uri[:4] in ("cdda", "http"):
			metadata = self.bmpx.GetMetadataForUri(self.uri)
				
			try:
				title_s = cgi.escape(metadata['title']).strip()
				title_s = title_s.replace("&amp;", "&")
			except:
				if TRACK[:4] == "cdda":
					s = TRACK.split("/")
					title_s = "CDrom track %s " % s[-1]
				else:
					title_s = TRACK

			try:
				artist_s = cgi.escape(metadata['artist']).strip()
				artist_s = artist_s.replace("&amp;", "&")
			except:
				artist_s = ""
			try:	
				album_s = cgi.escape(metadata['album']).strip()
				album_s = album_s.replace("&amp;", "&")
			except:
				album_s = ""
			try:
				length = int(metadata['time'])
			except:
				length=0
			try:
				track_nums = cgi.escape(metadata['track-number']).strip()
			except:
				track_nums = 0
			try:
				self.currentBitrate = cgi.escape(metadata['bitrate'])
			except:
				self.currentBitrate = 0
			self.metadata = metadata
			self.length = length
			
			minutes_length = int(self.length) / int(60)
			seconds_length = int(self.length) % int(60)
			
			self.statusstatic = '%2.2d:%2.2d' % ( minutes_length, seconds_length)
	
		else:
			titlestring =self.uri
			self.length = 0
			self.currentBitrate = 0
			track_nums = 0
			title_s= ""
			artist_s = ""
			album_s = ""
			self.statusstatic = "00:00"
			
		titlestring = self.format_title_string(artist_s, album_s, track_nums, title_s)
		
		self.currentTrack = self.bmpx.GetCurrentTrack()+1
		width =1
		if self.playlist_dict != {}:
			if self.bmpx.GetCurrentTracklistNumber() in range(len(self.playlist_dict)):
				#self.error_bar(str(len(self.playlists[self.bmpx.GetCurrentTracklistNumber()])))
				width = len(str(len(self.playlist_dict[self.bmpx.GetCurrentTracklistNumber()])))
	
		ta = str(self.currentTrack) # add 1 for zero correction
		while len(ta) <width:
			ta = " "+ta
		tra = "[%s]" % ta # track number
		self.titlestring = " %s %s" % (tra, titlestring)
	
		
		return 1
	
	def display_playlist(self):
		# Draw Current Playlist Title in bold, others normally
		self.playlists = self.bmpx.GetTracklists()
		#self.current_playlist = self.playlists[self.bmpx.GetCurrentTracklistNumber()]
		
		self.mainowin.border()
		pos = 1
		try:
			
			for playlists in self.playlists:
				
				if pos > self.w-25:
					break
				if playlists == self.playlists[self.activeplaylist]:
					self.mainowin.addstr( 0, pos, "<")
					pos += 1
					self.mainowin.addstr( 0, pos, self.decode_language(playlists) , curses.A_BOLD | self.colors["cyan"])
					pos +=len(self.decode_language(playlists))
					self.mainowin.addstr( 0, pos, ">")
					pos += 2
				else:
					self.mainowin.addstr( 0, pos, "<"+self.decode_language(playlists) + ">")
					pos = pos + len(self.decode_language(playlists))+2 +1
			
		except Exception,e:
			self.error_bar("Display playlist title:" + str(e))
		self.mainowin.addstr( self.h-3, self.w-37, "< Playlist %d of %d >" % (self.activeplaylist+1, len(self.playlists) ) )
		self.mainowin.refresh()
		# Draw playlist
		if self.playlist_dict[self.activeplaylist] == []:
			self.mainwin.clear()
			self.mainwin.addstr("       This playlist is Empty")
			
			self.mainwin.refresh()
			return
		
		
		playlength = len(self.playlist_dict[self.activeplaylist])
		if self.highliteTrack > len(self.playlist_dict[self.activeplaylist]) -1:
			self.highliteTrack = len(self.playlist_dict[self.activeplaylist]) -1
		
		try:
			height = self.h-4
			self.from_a = self.highliteTrack-height/2
			
			if self.from_a < 0:
				self.to = self.highliteTrack+(height-height/2)-self.from_a
				self.from_a = 0
			else:
				self.to = self.highliteTrack+(height-height/2)
			#debug scrolling
			#self.mainowin.addstr(str(from_a)+"::"+str(to) )
			#self.mainowin.refresh()
			#sleep(1)
			self.current = self.bmpx.GetCurrentTrack()
			self.current_tracklist = self.bmpx.GetCurrentTracklistNumber()
			self.mainwin.clear()
			self.mainwin.scrollok(0)
			#self.error_bar("%d:%d" % (self.current_tracklist, self.activeplaylist) )
			
			
			width = len(str(len(self.playlist_dict[self.activeplaylist])))
			
			
			#for t, string in self.playlist_dict[self.activeplaylist][self.from_a:self.to]:
			t = 0
			for string, time in self.playlist_dict[self.activeplaylist][self.from_a:self.to]:
				
				#self.display_item(t, string, width)
				#self.error_bar(string)
				#self.error_bar(self.playlist_dict[self.activeplaylist].index(string)-1)
				#self.playlist_dict[self.activeplaylist][self.from_a:].index(string)
				self.display_item(t+self.from_a, string, time, width)
				t +=1
			
		except Exception, e:
			self.error_bar("Display playlist :" + str(e))
		
		self.mainwin.refresh()
		#self.error_bar("display-playlist [%s] %s" % (time.strftime("%H:%M:%S"), self.highliteTrack) )
		
	def display_item(self, t, string, time, width):

		ta = str( t + 1 )
		while len(ta) <width:
			ta = " " + ta

		tra = "[%s] " % ta # track number in brackets
		string = tra+string
		
		# If string is longer than width of terminal - padding, add only one space
		if len(self.decode_language(string)) > self.w-23:
			z = " "
		else:
			# Otherwise, add spaces to fill the empty void
			z = " " * (self.w-22 - len(self.decode_language(string)) )
		
		# Force string to fit, add spaces, and time
		string = string[:self.w-18-len(time)] +z+time

		if t == self.current and self.current_tracklist == self.activeplaylist:
			try:
				if self.selectedTracks != []:
					if t in self.selectedTracks:
						if t == self.highliteTrack:
							self.mainwin.addstr( self.decode_language(string), curses.A_REVERSE | curses.A_BOLD | self.colors["red"])
							raise Exception, ""
						self.mainwin.addstr( self.decode_language(string), curses.A_REVERSE | curses.A_BOLD | self.colors["yellow"])
						raise Exception, ""
				if t == self.highliteTrack:
					self.mainwin.addstr( self.decode_language(string),curses.A_BOLD | self.colors["cyan"] | curses.A_REVERSE )
				
				else:
					self.mainwin.addstr( self.decode_language(string),curses.A_BOLD | self.colors["cyan"] )
			except Exception,e:
				#self.error_bar("ERROR: Current Track: "+str(e))
				pass

		elif t in self.selectedTracks:
			try:
				if t == self.highliteTrack:
					self.mainwin.addstr( self.decode_language(string), curses.A_BOLD | self.colors["yellowhite"])
					raise Exception, ""
				self.mainwin.addstr( self.decode_language(string), curses.A_REVERSE | self.colors["yellow"])
			except Exception,e:
				#self.error_bar("ERROR: Selected: "+e)
				pass
		elif t == self.highliteTrack:
			try:
				self.mainwin.addstr( self.decode_language(string), curses.A_REVERSE )

			except Exception, e:
				
				pass
		else:
			try:
				self.mainwin.addstr( self.decode_language(string))
			except Exception, e:
				#self.error_bar("Display track: "+ str(e))
				pass
			
	def switchplaylist(self, direction):
		if self.activeplaylist == None:
			self.activeplaylist = self.bmpx.GetCurrentTracklistNumber()
		if self.activeplaylist == -1:
			self.activeplaylist = 0
		
		try:
			self.playlists = self.bmpx.GetTracklists()
			
			self.selectedTracks = []
			if len (self.playlists) > 1:
				if direction == "right":

					if self.activeplaylist +1 in range(len(self.playlists)):
						self.activeplaylist += 1
					else:
						self.activeplaylist = 0
				else:
				
					if self.activeplaylist - 1 in range(len(self.playlists)):
						self.activeplaylist -= 1
					else:
						self.activeplaylist = len(self.playlists)-1
				# Sync Highlighted track with Current track on current playlist
				if self.activeplaylist == self.bmpx.GetCurrentTracklistNumber():
					self.highliteTrack = self.bmpx.GetCurrentTrack()
				else:
					# Clean up highlighted track, force to last item on the playlist
					if self.highliteTrack > len(self.playlist_dict[self.activeplaylist]) -1:
						self.highliteTrack = len(self.playlist_dict[self.activeplaylist]) -1
					else:
						self.highliteTrack = 0
				
				self.display_playlist()
		except Exception, e:
			self.error_bar("ERROR: Switch to next playlist: "+str(e))
			
	def escaped(self, key, line):
		#print key
		if key == "KEY_RESIZE":
			self.stdscr.keypad(1)
			self.build(self.stdscr, line)
		elif key == "KEY_MOUSE":
			
			(id,x,y,z,event)=curses.getmouse()
			#self.error_bar("%s, %s, %s, %s, %s" % (id,x,y,z,event))
			if event in (1, 2, 128, 4096, 8192):
				# Ignore PRESSED and RELEASED
				return
			
			elif y == 0:
				if x >= 0 and x < self.w-15:
					# Clicking  on the Track bar, shows the track 
					# and it's position in the playlist
					self.activeplaylist = self.bmpx.GetCurrentTracklistNumber()
					self.highliteTrack = self.bmpx.GetCurrentTrack()
					self.display_playlist()
			elif y in (2, 3, 4) and x >= self.w-15:
				if x >= self.w-15 and x < self.w-7:
					if self.shuffle == False:
						self.bmpx.ShuffleSet(True)
					else:
						self.bmpx.ShuffleSet(False)
				elif x >= self.w-17:
					if self.repeat == False:
						self.bmpx.RepeatSet(True)
					else:
						self.bmpx.RepeatSet(False)
			elif y >=2 and y<= self.h-2 and x < self.w-15:
				y = y -2
				if event in (64, 256):
					track = self.from_a+y
					if track  in self.selectedTracks:
						self.selectedTracks.remove(track)
					else:
						self.selectedTracks.append(track)
					self.display_playlist()
				elif event in (4, 8, 16384):
					# Button 1 Click
					# Button 1 Double-Click
					# Button 3 Click
					self.highliteTrack=self.from_a+y
					#self.error_bar(str(self.highliteTrack)+":"+str(y)+":"+str(self.from_a))
					if self.activeplaylist != self.bmpx.GetCurrentTracklistNumber():
						self.bmpx.CurrentTracklistSet(self.activeplaylist)
					if self.highliteTrack > len(self.playlist_dict[self.activeplaylist]) -1:
						self.highliteTrack =  len(self.playlist_dict[self.activeplaylist]) -1
					#if event == 4:
					if event in (8, 16384):
						self.bmpx.PlayListTrack(self.activeplaylist, self.highliteTrack)
					self.display_playlist()
					
			elif y >=self.h-2 and x >= self.w -15:
				if x >= self.w-15 and x < self.w-11:
					self.bmpx.PlayPrev()	
				elif x >= self.w-11 and x < self.w-9:
					self.bmpx.PlayCurrent()	
				elif x >= self.w-9 and x < self.w-6:
					if self.statusText == "STOPPED":
						self.bmpx.PlayCurrent()
					else:
						self.bmpx.PlayPause()
				elif x >= self.w-6 and x < self.w-3:
					self.bmpx.PlayStop()	
				elif x >= self.w-3 :
					self.bmpx.PlayNext()
				pass
			elif y >self.h-2 and x >= self.w-37 and x <  self.w-15:
				self.switchplaylist("right")

		elif key in( "KEY_LEFT", "CC", chr(2)):
			#s = "%d %% %d = %d" % ( self.length , self.current_pos,  percent)
			#self.error_bar(s)
			if self.seeking == False:
				
				if self.current_pos != 0:
					percent =  (float(self.current_pos)/float(self.length)*100)#
				else:
					percent=0
					self.seeking = True
					return
				if percent != 0:
					self.bmpx.Seek(int(percent)-2)
				else:
					self.bmpx.Seek(0)
				self.seeking = True
		elif key in("KEY_RIGHT", chr(6) ):
			#s = "%d %% %d = %d" % ( self.length , self.current_pos,  percent)
			#self.error_bar(s)
			if self.seeking == False:
				if self.current_pos != 0:
					percent =  (float(self.current_pos)/float(self.length)*100)#
				else:
					percent=0
					self.seeking = True
					return
				if percent not in ( 99, 100):
					self.bmpx.Seek(int(percent)+2)
				else:
					self.bmpx.Seek(100)
				
				#self.bmpx.SetStreamPos()
				self.seeking = True
			
		elif key == "list_left":
			self.switchplaylist("left")
		elif key == "list_right":
			self.switchplaylist("right")
		elif key == "jump":
			width = len(str(len(self.playlist_dict[self.activeplaylist])))
			line = line.strip()
			if line == "":
				self.error_bar("BMPty")
				return
			if line.isdigit():
				line = int(line)
				for t, string in self.playlist_dict[self.activeplaylist]:
					if line == t+1:
						self.error_bar("Jumped to: %s" % string[:-5])
						self.highliteTrack =t
						self.display_playlist()
						sleep(0.4)
						self.error_bar("BMPty")
						return
				self.error_bar("Nothing Matches: %d " % line)
			else:
				line_ignorecase =  re.compile('.*' + line + '.*', re.DOTALL | re.I)
				for t, string in self.playlist_dict[self.activeplaylist]:
					if re.match( line_ignorecase,string):
						self.error_bar("Jumped to: %s" % string[:-5])
						self.highliteTrack = t
						self.display_playlist()
						sleep(0.4)
						self.error_bar("BMPty")
						return
				self.error_bar("Nothing Matches: %s" % line)
				
		elif key == "file":
			line = line.strip()
			if line in ("~/", "~"): 
				self.error_bar("BMPty: Choose a directory other than your home directory, please.")
				pass
			elif line[:8] == "cdda:///":
				if line[8:].isdigit() and int(line[8:]) > 0 and int(line[8:]) < 400:
					self.bmpx.AddUriList([line], self.activeplaylist, self.highliteTrack+1)
			elif line[:7] == "http://":	
				self.bmpx.AddUriList([line], self.activeplaylist, self.highliteTrack+1)
			if line[:6] in ( "zip://", "rar://"):
				self.bmpx.AddUriList([line], self.activeplaylist, self.highliteTrack+1)
			elif line.isdigit(): pass
			else:
				splitit = line.split("/")
				path1=''
				path2 =''
				for r in range(len(splitit)):
					if r == 0:
						path1 += splitit[r]
					elif r == len(splitit)-1:
						#if file[-3:-1]:
						path2 = splitit[-1]
					else:
						path1+= "/"+splitit[r]
					

				sline = os.path.expanduser(line)
				
				if os.path.exists(sline):

					if os.path.isdir(sline):
						#self.error_bar(line+" is a dir, adding to %d" % self.activeplaylist)
						try:
							array = []
							directory = sline
							array = self.add_dir(array, directory)
							#sleep(0.1)
							#self.error_bar("Final array %d" % len(array ))
							#sleep(0.1)
							self.bmpx.AddUriList(array, self.activeplaylist, self.highliteTrack+1)
							self.error_bar("BMPty: Added New Directory to the playlist...")
						except Exception,e:
							self.error_bar("BMPty: Error Adding files: "+str( e )[:20])
							
						
					else:
						s = sline.split(".")
						#self.error_bar(s)
						if s[-1] in supported_formats :
							array = []
							array.append("file://"+sline)
							self.bmpx.AddUriList(array, self.activeplaylist, self.highliteTrack+1)
							self.error_bar("BMPty: Added New File to the playlist...")
						else:
							self.error_bar("BMPty: Format %s isn't supported..." % sline[-3:])
				else:
					#self.error_bar(sline+" doesn't exist")
					#sleep(1)
					direct = os.path.expanduser(path1)
					if os.path.exists(direct):
						if os.path.isdir(direct):
							#self.error_bar("but the directory"+path1+" does exist!, guessing you used a wildcard in: "+path2)
							if direct[:-1] != '/':
								direct += '/'
						else:
							self.error_bar("BMPty: No directory found at path: "+path1[:20])
							return
						if path2 =='*':
							#self.error_bar("guess you want the entire directory: "+path1)
							try:
								array = []
								directory = sline
								array = self.add_dir(array, directory)
								#sleep(0.1)
								#self.error_bar("Final array %d" % len(array ))
								#sleep(0.1)
								self.bmpx.AddUriList(array, self.activeplaylist, self.highliteTrack+1)
								self.error_bar("BMPty: Added New Directory to the playlist...")
							except Exception,e:
								self.error_bar("BMPty: Error Adding files: "+str( e ))
								
						elif '*' in path2:
							dirs = os.listdir(direct)
							#x=  path2.find('*')
							x = path2.replace('*', '')
							array = []
							for path in dirs:
								if x in path:
									if 1:
									#if path[-3:] in supported_formats:
										array.append("file://"+direct+path)
							if array != []:
								self.bmpx.AddUriList(array, self.activeplaylist, self.highliteTrack+1)
								self.error_bar("BMPty: Added file(s) with wildcard: %s" % path2)
					else:
						self.error_bar("BMPty: No directory found at path: "+path1)
						return
							

			
		
		elif key in ("KEY_UP"):#,  "KEY_DOWN", "KEY_PPAGE", "KEY_NPAGE"):
			if self.currentVolume < 100:
				self.bmpx.VolumeSet (self.currentVolume+1)

		elif key in ("KEY_DOWN"):
			if self.currentVolume > 0:
				self.bmpx.VolumeSet (self.currentVolume-1)
				
		elif key == "KEY_PPAGE": # Page UP
			# Scroll down the height of the playlist window
			if self.highliteTrack > 0:
				self.highliteTrack -= self.h-4
				if self.highliteTrack <0:
					self.highliteTrack=0
				self.display_playlist()
			
		elif key == "KEY_NPAGE": # Page DOWN
			# Scroll down the height of the playlist window
			if self.highliteTrack < len(self.playlist_dict[self.activeplaylist]) -1:	
				self.highliteTrack += self.h-4
				if self.highliteTrack > len(self.playlist_dict[self.activeplaylist]) -1:
					self.highliteTrack =  len(self.playlist_dict[self.activeplaylist]) -1
				self.display_playlist()
				
		elif key == "scroll_up":
			# Scroll up the playlist window one item
			if self.highliteTrack > 0: # len(self.playlist_dict[self.current_playlist]
				self.highliteTrack -= 1
				self.display_playlist()
				
		elif key == "scroll_down":
			# Scroll down the playlist window one item
			if self.highliteTrack < len(self.playlist_dict[self.activeplaylist]) -1:
				self.highliteTrack += 1
				self.display_playlist()
				
		elif key in ("e", "E"):
			self.bmpx.TracklistRemove(self.activeplaylist)
			self.error_bar("BMPty: Deleted list: %s" % self.activeplaylist )
			self.activeplaylist = 0
			
		elif key =="new-list":
			line.strip()
			if line == '':
				return
			try:
				self.bmpx.TracklistNew(line)
				self.error_bar("BMPty: Created new list: %s" %line)
			except:
				self.error_bar("BMPty: Couldn't Create list: %s" %line)
		elif key == "rename-list":
			line.strip()
			if line == '':
				return
			try:
				self.bmpx.TracklistRename(self.activeplaylist, line)
				self.error_bar("BMPty: Renamed Current List to: %s" %line)
			except:
				self.error_bar("Couldn't Rename list: %s" %line)
			
		elif key in ("a", "A"):
			# Select/DeSelect All Files in Active playlist
			if self.selectall==True:
				self.selectall=False
				
				for i in range(len(self.playlist_dict[self.activeplaylist])):
					if i   in self.selectedTracks:
						self.selectedTracks.remove(i )
			else:
				self.selectall=True
				for i in range(len(self.playlist_dict[self.activeplaylist])):
					if i  not in self.selectedTracks:
						self.selectedTracks.append(i)
			self.display_playlist()
			
		elif key == "r":
			# Toggle Repeat
			if self.repeat == False:
				self.bmpx.RepeatSet(True)
			else:
				self.bmpx.RepeatSet(False)

		elif key == "s":
			# Toggle Shuffle
			if self.shuffle == False:
				self.bmpx.ShuffleSet(True)
			else:
				self.bmpx.ShuffleSet(False)
				
		elif key == "o":
			# Force a Redraw
			self.build(self.stdscr, line)
			#cself.build_playlists(-1)
			
		elif key == "?":
			# Toggle the help display
			if self.helpshow == False:
				self.helpshow = True
				self.instructions.clear()
				self.instructions.addstr(self.instructionstring[1])
			else:
				self.helpshow = False
				self.instructions.clear()
				self.instructions.addstr(self.instructionstring[0])
			self.instructions.refresh()

		elif key in ( "l", "L"):
			# Cycle thru playlists to the right
			self.switchplaylist("right")
			
		elif key in ( "KEY_F(2)"):
			# Save Config File to disk
			update_config()
			self.error_bar("BMPty: Saved Config")
			sleep(0.5)
			self.error_bar("BMPty")
			
		elif key in ( "t", "T"):
			# Change Track Title Format
			if bmpty_config["display"]["title_format"] == "long":
				bmpty_config["display"]["title_format"] = "short"
			elif bmpty_config["display"]["title_format"] == "short":
				bmpty_config["display"]["title_format"] = "title"
			elif bmpty_config["display"]["title_format"] == "title":
				bmpty_config["display"]["title_format"] = "brackets"
			elif bmpty_config["display"]["title_format"] == "brackets":
				bmpty_config["display"]["title_format"] = "long"
			self.build_playlists(-1)
			
		elif key == "KEY_IC":
			# Mark current Highlighted track
			if self.highliteTrack  in self.selectedTracks:
				self.selectedTracks.remove(self.highliteTrack )
			else:
				self.selectedTracks.append(self.highliteTrack )
			self.display_playlist()
			
		elif key == "KEY_DC": # Delete Key
			# Delete Selected Track(s)
			if self.selectedTracks != []:
				self.bmpx.TracklistRemoveItems(self.activeplaylist, self.selectedTracks, len(self.selectedTracks))
			else:
				self.bmpx.TracklistRemoveItems(self.activeplaylist, [self.highliteTrack], 1)
			self.selectedTracks = []
			
		#elif key == "KEY_F(1)":
		#	self.build(self.stdscr, line)
			
		elif key in ( "z", "Z"):
			# Play previous track
			if self.bmpx.GetCurrentTrack() != 0:
				self.bmpx.PlayPrev()
		elif key in ( "x", "X"):
			# Play Current track
			if self.bmpx.GetCurrentTrack() != -1:
				self.bmpx.PlayCurrent()
			else:
				self.bmpx.PlayNext()
		elif key in ( "c", "C"):
			# If stopped, play current track, otherwise Pause/UnPause 
			if self.statusText == "STOPPED":
				self.bmpx.PlayCurrent()
			else:
				self.bmpx.PlayPause()
		elif key in ( "v", "V"):
			self.bmpx.PlayStop()
		elif key in ( "b", "B"):
			self.bmpx.PlayNext()
			
		elif key == chr(10) or key == "KEY_ENTER":
			# If not in currenttracklist (i.e., the playing tracklist), set it as current
			if self.activeplaylist != self.bmpx.GetCurrentTracklistNumber():
				self.bmpx.CurrentTracklistSet(self.activeplaylist)
			# Now, play the track
			self.bmpx.PlayListTrack(self.activeplaylist, self.highliteTrack)
			
		elif key in ("q", "KEY_F(8)"):
			# Quit BMPty
			curses.nocbreak()
			curses.echo()
			curses.endwin()
			os._exit(1)
			
	def add_dir(self, array, directory):
		
		# Create list of files in directory and subdirectories that match mp3 and ogg extensions
		if os.path.isdir(directory):
			#self.error_bar(directory+" is a subdir, adding to %d" % self.activeplaylist)
			if directory[:-1] != '/':
				directory += '/'
		else:
			#self.error_bar("array: "+str(array))
			return array
		
		dirs = os.listdir(directory)
		for path in dirs:
			if path[-3:] in supported_formats:
				array.append("file://"+directory+path)
				#sleep(0.1)
				#self.error_bar("file://"+directory+path)
			else:
				# Enter possible Subdirectory
				array = self.add_dir(array, directory+path)
		#self.error_bar("array: %d" % len(array))
		return array

	
class editor:
	def __init__(self, win, mainowin, BMPMonitor, escaped, line = ""):
		
		self.win = win
		self.escaped = escaped
		self.h, self.w = BMPMonitor.stdscr.getmaxyx()
		self.BMPMonitor = BMPMonitor
		self.scroll = 0
		self.mainowin = mainowin
		self.line = line
		self.x = len(self.line)
		
		self.escape = False
		self.y = None
		self.inputmode = "normal"
		self.fixpos()

		

	def process(self, c):
		# This is where the key presses are parsed
		
		pos = self.x + self.scroll
		#print c
		#self.win(self.line) # debugging: display keypress
		#
		if c == "KEY_RESIZE":
			self.escaped(c, self.line)
			
		if self.inputmode == "normal":
			self.line = ""
			if c in ('z', 'Z','x','X','c', 'v','V','b'):
				#BMPMonitor.bmpx.PlayPrev()
				self.escaped(c, self.line)
				
			elif c == "KEY_LEFT" or c == chr(2) or c == "KEY_RIGHT" or c == chr(6):
				if self.escape:
					if c == "KEY_LEFT" or c == chr(2):
						c = "list_left"
						self.escaped(c, self.line)
					elif c == "KEY_RIGHT" or c == chr(6):
						c = "list_right"
						self.escaped(c, self.line)
					
				else:
					self.escaped(c, self.line)
			elif c in ("KEY_F(1)", "KEY_F(2)", "?", "a", "A", "KEY_F(8)"):
				self.escaped(c, self.line)

			elif c in ("KEY_PPAGE", "KEY_DC"):
				self.escaped(c, self.line)
			elif c == "KEY_NPAGE":
				self.escaped(c, self.line)
			elif c == "+":
				c = "KEY_UP"
				self.escaped(c, self.line)
			elif c == "-":
				c = "KEY_DOWN"
				self.escaped(c, self.line)
			elif c in (	"e", "E"):
				if self.escape:
					self.escaped(c, self.line)
			elif c in ("n", "N",  "r", "R"):
				if self.escape:
					if c in ("n", "N"):
						self.inputmode = "new-list"
						self.mainowin.addstr( self.h-3, 1, "< Create a New List >")
					elif c in ( "r", "R"):
						self.inputmode = "rename-list"
						self.mainowin.addstr( self.h-3, 1, "< Rename this List >")
					
					#self.escaped(c, self.line)
					self.mainowin.refresh()
					self.win.addstr('\n')
					self.win.refresh()
					return False
					
			elif c in ("KEY_UP", "KEY_DOWN"):
				if self.escape:
					self.escaped(c, self.line)
				else:
					if c == "KEY_UP":
						c = "scroll_up"
						self.escaped(c, self.line)
					elif c == "KEY_DOWN":
						c = "scroll_down"
						self.escaped(c, self.line)
			elif c in ("r", "s", "o", "d", "q", "t", "T"):
				if self.escape:
					self.escaped(c, self.line)

			elif c == "KEY_IC": # Insert
				self.escaped(c, self.line)
			elif c in (	"L", "l"):
				self.escaped(c, self.line)
			elif c in (	"J", "j"):
				self.inputmode = "jump"
				self.mainowin.addstr( self.h-3, 1, "< Jump to track >")
				self.mainowin.refresh()
				self.x = 0
				self.line = ''
				self.win.addstr('\n')
				self.win.refresh()
				return False
			elif c in ("i", "I"):
				self.inputmode = "file"
				self.mainowin.addstr( self.h-3, 1, "<  Add File(s)  >")
				self.mainowin.refresh()
				self.line="~/"
				self.win.addstr('\n~/')
				self.win.refresh()
				
				self.x =2
				return False
			elif c =="KEY_MOUSE":
				self.escaped(c, self.line)
			elif c == chr(10) or c == "KEY_ENTER":
				self.escape = False
				self.escaped(c, self.line)
			elif c == chr(27):
				# ESC or Alt
				self.escape = True
				return False
		else:
			if c == chr(10) or c == "KEY_ENTER":
				c = self.inputmode
				self.escape = False
				self.escaped(c, self.line)
				self.inputmode = "normal"
				self.mainowin.addstr( self.h-3, 1, "-----------------")
				self.mainowin.refresh()
				return True
		
			elif c =="KEY_MOUSE":
				self.escaped(c, self.line)
			elif c == chr(27):
				# ESC or Alt
				self.escape = True
				self.inputmode = "normal"
				self.win.addstr("\nBMPty")
				self.win.refresh()
				self.line = ''
				self.x = 0
				return False
			elif len(c) == 1 and ord(c[0]) >= 32 and ord(c[0]) <127:
				# normal letters 
				self.line = self.line[:pos] + c + self.line[pos:]
				self.x += 1
				
			elif c == "KEY_LEFT" or c == chr(2):
				if self.escape:
					self.escaped(c, self.line)
				else:
					self.x -= 1
			elif c == chr(93) or c == chr(91)  or c == chr(34) or c == chr(35):
				if self.escape:
					self.escaped(c, self.line)
				else:
					self.line = self.line[:pos] + c + self.line[pos:]
					self.x += 1
			elif c == "KEY_RIGHT" or c == chr(6):
			
				if self.escape:
					self.escaped(c, self.line)
				else:
					self.x += 1
					
			elif c == chr(127) or c == "KEY_BACKSPACE" or c == chr(8):
				if pos > 0:
					self.line = self.line[:pos-1] + self.line[pos:]
					self.x -= 1
			elif c == chr(23): # Ctrl-W
				z = self.line.split(' ')
		
				if len(z) >1:
					if z[-1] != ' ' and z[-1] != '':
						self.line = ''
						for s in z:
							if s is not z[-1]:
								self.line = self.line + s +" "
							elif s is z[-1]:
								self.line = self.line
								break
					else:
						self.line = ''
						for s in z:
							if s not in (z[-1], z[-2]):
								self.line = self.line + s +" "
							elif s is z[-2]:
								self.line = self.line
								break
				else:
					self.line = ''
				self.x = len(self.line)
			else: 
				return False
			
			self.fixpos()
		
		# Clear Escape values
		self.escape = False
		return False
			
	def fixpos(self):
		try:
			''' # Debugging
			if len(self.line) >= self.w:
				#self.win.addstr("LINE TOO BIG")
				self.win.addstr("f %d %d %d w%d"  % (len(self.line), self.x, self.scroll, self.w) )
				self.win.refresh()
				sleep(1)	
			'''

			# Make line scroll to end
			while self.scroll + self.x > len(self.line):
				self.x -= 1
				
			while self.x >= self.w:
				self.scroll += 1
				self.x -= 1
				
			if self.x < 0:
				self.scroll += self.x
				self.x = 0
			#self.win.addstr("t %d %d %d w%d"  % (len(self.line), self.x, self.scroll, self.w) )
			#sleep(0.01)
			if self.inputmode != "normal":
			#	self.win.addstr("\nJump to track: %s" % self.line[self.scroll:self.scroll+self.w-16])
				self.win.addstr("\n%s" % self.line[self.scroll:self.scroll+self.w-1])
			#self.win(self.line[self.x:self.scroll+self.w-1])
		except Exception, e:
			self.win.addstr(e)
		self.win.refresh()
		

	def reset(self):

		self.x = self.scroll = 0
		self.line = ""

		self.win.erase()
		self.win.refresh()
			
class MainApp:
	def __init__(self):



		self.app = BMPMonitor()
		
	def MainLoop(self):

		#signal.signal(signal.SIGINT, signal.SIG_DFL)
		signal.signal(signal.SIGINT, self.die)

		
		#self.app.MutrayWindow.show()
		self.app.build(self.app.stdscr, line)
		
		Mapp.app.capturekeys.start()
		gtk.gdk.threads_enter()
		gtk.main()
		gtk.gdk.threads_leave()
		
	def die(self, w, e):
		# GoodBye, Cruel World! :(
		
		curses.nocbreak()
		curses.echo()
		curses.endwin()
		
		os._exit(1)
		
gobject.threads_init()
#c = BMPMonitor()
Mapp = MainApp()

line = ""

try:
	Mapp.MainLoop()
	#sleep(0.01)

except Exception, e:
	try:
		curses.nocbreak()
		curses.echo()
		curses.endwin()
	except:
		pass
