#!/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, strftime import threading, getopt, pwd version = "0.3.7" 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 Use a different config file -v, --version Display version and quit -r, --charset 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", "dock_playlists": "on" }, \ "bmpx":{"auto-launch":"no", "daemonize": "no"} } supported_formats = ["mp3", "ogg", "flac", "mpc", "m4a", "aac", "zip"] # , "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", "auto-launch", "daemonize"] : 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) if d == 0: c, keys = keys[0], keys[1:] try: self.BMPMonitor.edit.process(c) 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 = None self.selectedTracks =[] self.playlist_dict = {} self.highliteTrack =0 self.playlists = [] self.seeking = False self.activeplaylist = None self.statusstatic = " 0:00" self.current_pos = 0 self.selectall=False self.mixermode = False self.showsort = False self.helpshow = False self.from_a = 0 self.currentChannel = 0 self.continue_build = 0 self.current_tracklist = 0 self.sortnumber = 0 # Layout self.main_h = None self.main_w = None self.playlist_w = None self.playlist_h = None self.equalizer = {0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9: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.create_dbus_interface() self.bmpx.SendStatus() self.connected = True except: self.connected = False # Start Curses #self.stdscr = curses.initscr() # Start Keygrabber self.capturekeys = capturekeys(self) self.stdscr.nodelay(1) self.stdscr.keypad(1) curses.start_color() curses.noecho() 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_WHITE ) 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_WHITE ) 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.currentBitrate = 0 self.shuffle = None self.repeat = None self.currentVolume = 0 if self.connected == True: self.integrate_signals() self.bus.add_signal_receiver(self.bmpx_startup, 'StartupComplete', "org.beepmediaplayer.BMPx", "", "") self.bus.add_signal_receiver(self.bmpx_shutdown, "ShutdownComplete", "org.beepmediaplayer.BMPx", "", "") if self.connected == True: self.sync_status() self.instructionstring = [ \ "-Items-"\ "\n Play: Enter"\ "\n Select: Insert"\ "\n Select All: A"\ "\n Delete: Del"\ "\n Move to: Alt-M"\ "\n Copy to: Alt-P"\ "\n Jump to: J",\ \ "-Lists-"\ "\n Format: Alt-T"\ "\n New: Alt-N"\ "\n Rename: Alt-R"\ "\n Delete: Alt-E"\ "\n Add Files: I"\ "\n\nRefresh: Alt-O"\ "\nSeek: Left Right",\ \ "-Switch list-\n Alt-Left Alt-Right"\ "\nToggle Eq: Alt-U"\ "\nSave: F5"\ "\nStart BMPx F6"\ "\nAuto-Launch F7"\ "\nDaemonize F8"\ "\nQuit: F10",\ \ "-Playlists-"\ "\n Alt-U",\ \ "-Volume-"\ "\n Up / Down"\ "\n PgUp / PgDn"\ "\n Home / End",\ \ "-All Bands-"\ "\n Max M"\ "\n Flatten F"\ "\n Min N"\ ] def create_dbus_interface(self): self.bmpx_obj = self.bus.get_object('org.beepmediaplayer.BMPx', '/org/beepmediaplayer/BMPx/BmpSystemControl') self.bmpx = dbus.Interface(self.bmpx_obj, 'org.beepmediaplayer.BMPx') def sync_status(self): self.bmpx.SendStatus() self.shuffle = self.bmpx.ShuffleGet() self.repeat = self.bmpx.RepeatGet() self.currentVolume = int( self.bmpx.VolumeGet() ) def integrate_signals(self): self.bmpx.connect_to_signal('SetPlaystatus', self.bmpx_set_playstatus) try: 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_deleted) self.bmpx.connect_to_signal('ListRenamed', self.bmpx_playlist_renamed) self.bmpx.connect_to_signal('SetRepeat', self.setrepeat) self.bmpx.connect_to_signal('SetShuffle', self.setshuffle) self.bmpx.connect_to_signal('SetEq', self.seteq) except Exception, e: self.error_bar("ERROR: integrate_signals: " +str(e)) def seteq(self, channel, v): self.equalizer[channel] = v if self.mixermode == True: self.display_mixer() #self.error_bar(str(ch) +":"+ str(s)) def launch_bmpx(self): if bmpty_config["bmpx"]["daemonize"] == "yes": self.error_bar("Launching BMPx as a daemonized service...") os.system("bmpx --daemon") else: self.error_bar("Launching BMPx...") os.system("bmpx &") def bmpx_startup(self): self.error_bar("Reconnecting to BMPx") try: try: self.create_dbus_interface() except: self.error_bar("ERROR: BMPty Cannot Access BMPx via D-Bus") self.connected = False return self.integrate_signals() self.sync_status() self.connected = True line = '' self.build(self.stdscr, line, "all") self.error_bar("BMPty connected to BMPx") except: self.error_bar("BMPty: Connection error: "+str(e)) def bmpx_shutdown(self): self.launch_options() self.connected = False self.build_playlists(-1) #if 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.escape_title(), self.statusText.capitalize())) #self.decode_language(self.titlestring) else: return def escape_title(self): string = self.decode_language(self.titlestring) string = string.replace("`", "'") return string def bmpx_playlist_added(self, playlist_num): temp_list = reversed( self.playlist_dict.keys() ) for lists in temp_list: if lists >= playlist_num: self.playlist_dict[lists+1] =self.playlist_dict[lists] self.playlist_dict[playlist_num] = [] if self.activeplaylist >= playlist_num: self.activeplaylist += 1 self.display_playlist() self.draw_playlist_label() def bmpx_playlist_deleted(self, playlist_num): temp_list = self.playlist_dict.keys() for lists in temp_list: if lists > playlist_num: self.playlist_dict[lists-1] =self.playlist_dict[lists] del self.playlist_dict[-1] self.display_playlist() self.draw_playlist_label() def bmpx_playlist_renamed(self, playlist_num): #self.error_bar(playlist_num) #temp_list = reversed(self.playlist_dict.keys() ) temp_list = self.playlist_dict.keys() new_items = self.bmpx.GetTracklists() self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() self.currentTrack= self.bmpx.GetCurrentTrack() for x in new_items: if x not in self.playlists: #new_name = x new_pos = new_items.index(x) #s ="%s %d renamed to %s %d" % (self.playlists[playlist_num], playlist_num, new_name, new_pos) #self.error_bar(s) #self.playlists = self.bmpx.GetTracklists() current = self.playlist_dict[playlist_num] self.activeplaylist = new_pos if new_pos < playlist_num: for lists in reversed(temp_list): if lists > playlist_num or lists < new_pos: pass elif lists < playlist_num and lists >= new_pos: self.playlist_dict[lists+1] =self.playlist_dict[lists] elif new_pos > playlist_num: for lists in temp_list: if lists < playlist_num or lists > new_pos: pass elif lists > playlist_num and lists <= new_pos: self.playlist_dict[lists-1] =self.playlist_dict[lists] else: self.display_playlist() self.draw_playlist_label() return self.playlist_dict[new_pos] = current self.display_playlist() self.draw_playlist_label() def bmpx_playlist_item_sorted(self, playlist_num): self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() 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)) 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): if track_nums == -1: self.playlist_dict[playlist_num] = [] else: tracks = reversed(tracks) 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.currentTrack= self.bmpx.GetCurrentTrack() #self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() if self.titlestring != self.lasttitle: #self.error_bar("changing title %s" % strftime("%H:%M:%S") ) self.set_title() self.lasttitle = self.titlestring try: self.onlinetitle.addstr("\n"+self.decode_language(self.titlestring)[:self.w-self.sidebar_w-7]) self.onlinetitle.refresh() self.titletime.addstr("\n"+self.statusstatic) self.titletime.refresh() except Exception, e: self.error_bar( "ERROR: track change" + str(e)) try: self.bitwin.erase() self.bitwin.addstr(" BitRate: %s"[-self.sidebar_w+1:] % str(self.currentBitrate)) self.bitwin.refresh() except Exception, e: self.error_bar("ERROR: modifying BitRatebox: " + str(e)) #if self.activeplaylist == self.current_tracklist: 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.erase() self.volwin.addstr(" - + Volume: %s%%" % str(self.currentVolume)) self.volwin.refresh() def bmpx_set_stream_pos(self, stream_pos): #return if stream_pos == self.current_pos: return self.current_pos = stream_pos minutes = int(stream_pos) / int(60) seconds = stream_pos % 60; minutes_length = int(self.length) / int(60) seconds_length = int(self.length) % int(60) self.statusnew ='%2d:%2.2d' % (minutes, seconds) self.statusstatic = '%2d:%2.2d' % ( minutes_length, seconds_length) if self.status != self.statusnew: self.status = self.statusnew try: self.onlinetime.addstr("\n"+self.status) self.onlinetime.refresh() except Exception, e: self.error_bar( "ERROR: Online Time" + str(e)) sleep(0.01) def display_statusbox(self): try: self.onlinestatus.erase() if self.connected == True: if self.statusText == 'PAUSED': self.onlinestatus.addstr(" %s:" %self.statusText) elif self.statusText == 'PLAYING': self.onlinestatus.addstr(" %s:" %self.statusText) elif self.statusText == 'STOPPED': self.onlinestatus.addstr(" %s:" %self.statusText) else: self.onlinestatus.addstr(" OFFLINE:") 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-self.sidebar_w-7]) self.onlinetitle.refresh() return 1 def run(self): self.capturekeys.start() def create_title(self): try: self.update_info() self.set_title() if self.connected == True: self.highliteTrack=self.bmpx.GetCurrentTrack() else: self.highliteTrack = 0 self.onlinetitle = curses.newwin(1, self.w-self.sidebar_w-5, 0, 0) self.onlinetitle.bkgdset(" ", curses.A_REVERSE | curses.A_BOLD) self.onlinetitle.idlok(1) self.onlinetitle.scrollok(1) self.onlinetitle.erase() if self.connected == True: try: self.onlinetitle.addstr("\n"+self.decode_language(self.titlestring)[:self.w-self.sidebar_w-7]) except Exception,e: self.error_bar("title problem %s" % str(e)) else: self.onlinetitle.addstr("\n [0] No track") self.onlinetitle.refresh() self.titletime = curses.newwin(1, 6, 0, self.w-self.sidebar_w-6) self.titletime.bkgdset(" ", curses.A_REVERSE | curses.A_BOLD) self.titletime.idlok(1) self.titletime.scrollok(1) self.titletime.erase() self.titletime.addstr("\n"+self.statusstatic) self.titletime.refresh() except Exception, e: self.error_bar("ERROR: title " + str(e)[:60]) def launch_options(self): self.editwin.addstr("\nBMPty disconnected from BMPx: |F5 Save|F6 Start BMPx|") if bmpty_config["bmpx"]["auto-launch"] == "yes": self.editwin.addstr("F7 Auto", curses.A_REVERSE | self.colors["greenbg"] ) else: self.editwin.addstr("F7 Auto") self.editwin.addstr("|") if bmpty_config["bmpx"]["daemonize"] == "yes": self.editwin.addstr("F8 Daemon", curses.A_REVERSE | self.colors["greenbg"] ) else: self.editwin.addstr("F8 Daemon" ) self.editwin.addstr("|F10 Quit|") self.editwin.refresh() 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.erase() if self.connected == True: self.editwin.addstr("\nBMPty ;)", curses.A_REVERSE | self.colors["redwhite"]) self.editwin.refresh() else: if bmpty_config["bmpx"]["auto-launch"] == "yes": self.launch_bmpx() else: self.launch_options() def create_mainwindow(self): try: #bmpty_config["display"]["dock_playlists"] = False if bmpty_config["display"]["dock_playlists"] == False: self.main_h = self.h-2 self.main_w = self.w-15 self.sidebar_t = 4 self.sidebar_w = 15 self.sidebar_h = self.h-8 else: self.main_h = self.h-2 self.main_w = self.w-20 self.sidebar_t = 4 self.sidebar_w = 20 self.sidebar_h = self.h-8 self.mainowin = curses.newwin(self.main_h, self.main_w, 1, 0) self.mainowin.idlok(1) self.mainowin.erase() self.mainowin.border() self.mainowin.refresh() self.playlist_h = self.main_h-2 self.playlist_w = self.main_w-2 self.playlistwin = self.mainowin.subwin(self.playlist_h, self.playlist_w, 2, 1) self.playlistwin.scrollok(1) self.playlistwin.idlok(1) except Exception,e : self.error_bar("ERROR: Creating MainWindow: "+ str( e)[:60]) def display_instructions(self): if self.helpshow == True: self.instructionswin.redrawwin() self.instructionswin.border() self.instructionswin.addstr(0,1, "< Help >", curses.A_BOLD | self.colors["cyan"]) self.instructionswin.refresh() self.instructions.idlok(1) self.instructions.scrollok(1) self.instructions.erase() self.instructions2.scrollok(1) self.instructions2.erase() self.instructions3.scrollok(1) self.instructions3.erase() if self.mixermode == True: self.instructions.addstr(self.instructionstring[3]) self.instructions2.addstr(self.instructionstring[4]) self.instructions3.addstr(self.instructionstring[5]) elif self.mixermode == False: self.instructions.addstr(self.instructionstring[0]) self.instructions2.addstr(self.instructionstring[1]) self.instructions3.addstr(self.instructionstring[2]) self.instructions.refresh() self.instructions2.refresh() def create_instructions(self): try: self.instrheight = self.h-12-2 #self.instrwidth = self.w-self.sidebar_w-10 if self.w > 63 +5: self.instrwidth = 63 else: self.instrwidth = self.w-5 self.instructionswin= curses.newwin(self.instrheight, self.instrwidth, 11, 5) self.instructionswin.erase() self.instructionswin.border() self.instructionswin.addstr(0,1, "< Help >", curses.A_BOLD | self.colors["cyan"]) self.instructions= self.instructionswin.subwin(self.instrheight-2, 20, 12, 6) self.instructions2= self.instructionswin.subwin(self.instrheight-2, self.instrwidth-22,12, 26) self.instructions3= self.instructionswin.subwin(self.instrheight-2, 20,12, 46) self.helpshow = False 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.erase() 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, self.sidebar_w, 1, self.w-self.sidebar_w) self.volwin.bkgdset(" ", curses.A_UNDERLINE|curses.A_BOLD| self.colors["bluebg"]) self.volwin.idlok(1) self.volwin.scrollok(0) self.volwin.erase() self.volwin.addstr(" - + Volume: %s%%"[-self.sidebar_w+1:] % 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, self.sidebar_w, 2, self.w-self.sidebar_w) self.bitwin.bkgdset(" ", curses.A_UNDERLINE|curses.A_BOLD| self.colors["bluebg"]) self.bitwin.idlok(1) self.bitwin.scrollok(0) self.bitwin.erase() self.bitwin.addstr(" BitRate: %s"[-self.sidebar_w+1:] % str(self.currentBitrate)) self.bitwin.refresh() except Exception, e: self.error_bar("ERROR: BitRatebox: " + str(e)) def create_eqbox(self): try: self.eqboxwin = curses.newwin(1, 3, 3, self.w-self.sidebar_w+1) self.eqboxwin.bkgdset(" ") self.eqboxwin.idlok(1) self.eqboxwin.scrollok(0) self.eqboxwin.erase() if self.mixermode == True: self.eqboxwin.addstr("EQ", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"]) else: self.eqboxwin.addstr("EQ", self.colors["redwhite"] | curses.A_REVERSE) self.eqboxwin.refresh() except Exception, e: self.error_bar("ERROR: EQbox: " + 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.erase() 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.erase() 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() except Exception, e: self.error_bar("ERROR: Shufflebox: " + str(e)) def create_helpbox(self): try: self.helpboxwin = curses.newwin(1, 5, self.h-3, self.w-self.sidebar_w) #self.helpboxwin.bkgdset(" ", curses.A_BOLD| self.colors["cyan"]) #self.shuffwin = curses.newwin(1, 8, 3, self.w-15) self.shuffwin.bkgdset(" ") self.helpboxwin.idlok(1) self.helpboxwin.scrollok(1) self.helpboxwin.erase() if self.helpshow == True: self.helpboxwin.addstr("Help", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"]) else: self.helpboxwin.addstr("Help", self.colors["redwhite"] | curses.A_REVERSE) self.helpboxwin.refresh() except Exception, e: self.error_bar("ERROR: Shufflebox: " + str(e)) def create_statusbox(self): try: self.onlinestatus = curses.newwin(1, 14, 0, self.w-self.sidebar_w) 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.erase() self.display_statusbox() except Exception, e: self.error_bar("ERROR: Statusbox: " + str(e)) def build(self, stdscr, line = "", refresh= ""): self.stdscr = stdscr self.stdscr.erase() self.stdscr.refresh() self.h, self.w = self.stdscr.getmaxyx() self.continue_build = 1 try: try: self.currentTrack= self.bmpx.GetCurrentTrack() self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() except: pass self.create_errorbar() self.create_mainwindow() self.create_title() self.update_info() self.set_title() if refresh == "all": self.build_playlists(-1) else: self.display_playlist() self.create_timebox() self.create_volumebox() self.create_bitratebox() self.create_eqbox() self.create_statusbox() self.create_shufflebox() self.create_repeatbox() self.create_instructions() self.draw_playlist_label() self.create_helpbox() self.playwin = curses.newwin(2, 15, self.h-3, self.w-15) self.playwin.bkgdset(" ", curses.A_BOLD| self.colors["cyan"]) self.playwin.idlok(1) self.playwin.scrollok(1) self.playwin.erase() 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)) self.continue_build = 0 def error_bar(self, string): self.editwin.addstr("\n"+self.decode_language(str(string))) self.editwin.refresh() def build_playlists(self, value): try: if self.connected == True: 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() else: self.playlists=[] self.playlist_dict = {} self.playlist_dict[0] = [] self.activeplaylist = 0 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: if self.connected == True: thelist = self.bmpx.GetTracklist(x) else: thelist = [] except: self.error_bar("Problem with list: %d" % x) if thelist == []: #self.playlist_dict[x] = [] x +=1 # increase playlist number for empty playlists continue 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): try: if TRACK[-3:] in supported_formats or TRACK[:4] in ("cdda", "http"): if self.connected == True: metadata = self.bmpx.GetMetadataForUri(TRACK) else: metadata = {'comment': '', 'count': 0, 'rating': 0, 'track-number': 0, 'artist': '', 'title': '', 'genre': '', 'mtime': 0, 'location': '', 'time': 0, 'date': 0, 'samplerate': 0, 'album': '', 'bitrate': 0} try: if metadata['title'] != '': title_s = cgi.escape(metadata['title']).strip() title_s = title_s.replace("&", "&").replace("%20", " ") else: filename = TRACK.split("/") noext = filename[-1].split(".") s = '' for x in noext: if x is not noext[-1]: s += x title_s = s.replace("&", "&").replace("%20", " ") 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("&", "&") except: artist_s = "" try: album_s = cgi.escape(metadata['album']).strip() album_s = album_s.replace("&", "&") except: album_s = "" try: length = int(metadata['time']) except: length=0 try: track_nums = metadata['track-number'] 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 = length/60 seconds = length - (60 * minutes) time = '%2d:%2.2d' % (minutes, seconds) return titlestring, time except Exception, e: self.error_bar("ERROR: getmetadata: " + str(e)) return "Error", " 0:00" def update_info(self): if self.connected == True: self.currentTrack = self.bmpx.GetCurrentTrack() self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() width =1 if self.playlist_dict != {}: if self.current_tracklist in range(len(self.playlist_dict)): #self.error_bar(str(len(self.playlists[self.bmpx.GetCurrentTracklistNumber()]))) width = len(str(len(self.playlist_dict[self.current_tracklist]))) else: self.currentTrack =0 width = 1 if self.connected == True: try: self.uri = self.bmpx.GetCurrentUri() except: self.uri ="" else: self.uri ="" if self.uri == "": return TRACK = self.uri if self.uri[-3:] in supported_formats or self.uri[:4] in ("cdda", "http", "file"): if self.connected == True: metadata = self.bmpx.GetMetadataForUri(TRACK) else: metadata = {'comment': '', 'count': 0, 'rating': 0, 'track-number': 0, 'artist': '', 'title': '', 'genre': '', 'mtime': 0, 'location': '', 'time': 0, 'date': 0, 'samplerate': 0, 'album': '', 'bitrate': 0} try: if metadata['title'] != '': title_s = cgi.escape(metadata['title']).strip() title_s = title_s.replace("&", "&").replace("%20", " ") else: filename = TRACK.split("/") noext = filename[-1].split(".") s = '' for x in noext: if x is not noext[-1]: s += x title_s = s.replace("&", "&").replace("%20", " ") 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("&", "&") except: artist_s = "" try: album_s = cgi.escape(metadata['album']).strip() album_s = album_s.replace("&", "&") except: album_s = "" try: length = int(metadata['time']) except: length=0 try: track_nums = metadata['track-number'] except: track_nums = 0 try: self.currentBitrate = 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 = '%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 = " 0:00" titlestring = self.format_title_string(artist_s, album_s, track_nums, title_s) ta = str(self.currentTrack) # add 1 for zero correction while len(ta) ") self.sortwin.refresh() self.sortwinscroll = self.sortwin.subwin(6, 17, 5, 6) self.sortwinscroll.erase() self.sortwinscroll.scrollok(1) self.sortwinscroll.refresh() self.showsort = True self.draw_sort() def draw_sort(self): self.sortwinscroll.erase() zed = ["Location", "\nTitle", "\nArtist", "\nAlbum", "\nGenre", "\nComment"] for z in zed: if self.sortnumber == zed.index(z): self.sortwinscroll.addstr(z, self.colors["cyan"]) else: self.sortwinscroll.addstr(z) self.sortwinscroll.refresh() def draw_playlist_label(self): self.mainowin.border() if self.connected == True: self.playlists = self.bmpx.GetTracklists() #self.draw_playlist_label() try: if bmpty_config["display"]["dock_playlists"] == False: pos = 1 for playlists in self.playlists: if pos > self.playlist_w-10: 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 else: pos = 1 playlists = self.playlists[self.activeplaylist] self.mainowin.addstr( 0, pos, "< ") pos += 2 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, " >") self.playlistsidebar= curses.newwin(self.sidebar_h, self.sidebar_w, self.sidebar_t, self.main_w) self.playlistsidebar.idlok(1) #self.playlistsidebar.scrollok(1) self.playlistsidebar.border() self.playlistsidebar.addstr( 0, 0, " ", curses.ACS_TTEE) self.playlistsidebar.addstr( self.sidebar_h-1, 0, " ", curses.ACS_BTEE) self.mainowin.addstr( self.sidebar_t+self.sidebar_h-2, self.w-self.sidebar_w-1, " ", curses.ACS_LTEE) self.mainowin.addstr( self.sidebar_t-1, self.w-self.sidebar_w-1, " ", curses.ACS_LTEE) self.playlistsidebar.addstr( 0, 1, "< Playlists >", curses.A_BOLD) self.playlistsidebar.addstr( self.sidebar_h-1, 1, "--") self.playlistsidebar.refresh() self.playlistscroll_w = self.sidebar_w-2 self.playlistscroll = self.playlistsidebar.subwin(self.sidebar_h-2, self.w-self.main_w-2, self.sidebar_t+1, self.main_w+1) height = self.sidebar_h-2 from_a = self.activeplaylist-height/2 # middle playlength =len(self.playlists) if from_a < 0: to = self.activeplaylist+(height-height/2)-from_a from_a = 0 else: to = self.activeplaylist+(height-height/2) #self.error_bar("%s::%s::%s::%s" % (from_a, to, playlength, height) ) #sleep(0.5) if playlength-1 < height: from_a =0 if to >= playlength : from_a = abs(to - playlength - from_a) if playlength-1 < height: from_a =0 self.listz = self.playlists[from_a:] else: self.listz = self.playlists[from_a:to] #self.error_bar(self.playlists) a = from_a self.playlistscroll.scrollok(0) for i in self.listz: if self.listz.index(i) == self.listz[-1]: string = i[:self.playlistscroll_w-1]+" "*(self.playlistscroll_w- len(i)-1) else: string = i[:self.playlistscroll_w]+" "*(self.playlistscroll_w- len(i)) try: if self.playlists.index(i) == self.activeplaylist: self.playlistscroll.addstr(string, self.colors["cyan"]| curses.A_REVERSE | curses.A_BOLD) else: self.playlistscroll.addstr(string) except Exception, e: #self.error_bar("pls %s" % str(e)) pass a += 1 self.playlistscroll.refresh() except Exception,e: self.error_bar("Error: playlist title:" + str(e)) self.mainowin.addstr( self.main_h-1, self.main_w-24, "< Playlist %d of %d >" % (self.activeplaylist+1, len(self.playlists) ) ) else: self.playlists = [] self.mainowin.refresh() def display_playlist(self): # Draw Current Playlist Title in bold, others normally # Draw playlist if self.playlist_dict[self.activeplaylist] == []: self.playlistwin.erase() #self.playlistwin.bkgdset(" ") self.playlistwin.addstr(" This playlist is Empty") else: playlength = len(self.playlist_dict[self.activeplaylist]) if self.highliteTrack > playlength -1: self.highliteTrack = playlength -1 try: height = self.playlist_h 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) if self.to >= playlength: self.from_a = abs(self.to - playlength - self.from_a) self.to = playlength if playlength < height: self.from_a =0 #debug scrolling #self.error_bar(str(self.from_a)+"::"+str(self.to) ) #self.mainowin.refresh() #sleep(1) if self.connected == True: pass #self.currentTrack= self.bmpx.GetCurrentTrack() #self.current_tracklist = self.bmpx.GetCurrentTracklistNumber() else: self.currentTrack= None self.current_tracklist = 0 self.playlistwin.erase() self.playlistwin.bkgdset(" ") #self.playlistwin.addstr("\n")#+" "*self.main_h*self.main_w) #self.error_bar("%d:%d" % (self.current_tracklist, self.activeplaylist) ) width = len(str(len(self.playlist_dict[self.activeplaylist]))) t = 0 templist = self.playlist_dict[self.activeplaylist][self.from_a:self.to] for string, time in templist: # Don't scroll on last line if [string, time] == templist[-1]: self.playlistwin.scrollok(0) else: self.playlistwin.scrollok(1) self.display_item(t+self.from_a, string, time, width) t +=1 except Exception, e: self.error_bar("Display playlist :" + str(e)) self.playlistwin.refresh() if self.mixermode == True: self.display_mixer() if self.helpshow == True: self.display_instructions() if self.showsort == True: self.create_sort() def display_item(self, t, string, time, width): ta = str( t + 1 ) while len(ta) self.playlist_w: #z = " " z = '' pass else: # Otherwise, add spaces to fill the empty void z = " " * (self.playlist_w-6 - len(self.decode_language(string))-len(tra) ) # Force string to fit, add spaces, and time string = self.decode_language(string) string = string[:self.playlist_w-6-len(tra)] +z#+time if self.currentTrack== None: self.currentTrack = self.bmpx.GetCurrentTrack() if t == self.currentTrack and self.current_tracklist == self.activeplaylist: try: if self.selectedTracks != []: if t in self.selectedTracks: if t == self.highliteTrack: self.playlistwin.addstr( string, curses.A_REVERSE | curses.A_BOLD | self.colors["red"]) raise Exception, "" self.playlistwin.addstr( string, curses.A_REVERSE | curses.A_BOLD | self.colors["yellow"]) raise Exception, "" if t == self.highliteTrack: self.playlistwin.addstr( string,curses.A_BOLD | self.colors["cyan"] | curses.A_REVERSE ) else: self.playlistwin.addstr( 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.playlistwin.addstr( string, curses.A_BOLD | self.colors["yellowhite"]) raise Exception, "" self.playlistwin.addstr( string, curses.A_REVERSE | self.colors["yellow"]) except Exception,e: #self.error_bar("ERROR: Selected: "+e) pass elif t == self.highliteTrack: try: self.playlistwin.addstr( string, curses.A_REVERSE ) except Exception, e: pass else: try: self.playlistwin.addstr( string) except Exception, e: #self.error_bar("Display track: "+ str(e)) pass try: while len(time) < 6: time = " " + time self.playlistwin.addstr( time[:-2].replace(":","")) self.playlistwin.addstr( ":", curses.A_BOLD | self.colors["black"] ) self.playlistwin.addstr( time[-2:]) except Exception, e: #self.error_bar("Display track: "+ str(e)) pass def addfiles(self, line): try: line = line.strip() if line in ("~/", "~"): self.error_bar("BMPty: Choose a directory other than your home directory, please.") return 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) #self.playlistwin.scrollok(1) #self.playlistwin.erase() #z =[] #for s in array[147:]: # z.append(s) #self.playlistwin.addstr(s) #for r in z: #self.playlistwin.addstr(r) #self.playlistwin.refresh() try: #["file:///home/daelstorm/dd/The Best Of/07 - After all (Feat. Jaƫl).mp3"] self.bmpx.AddUriList(array, self.activeplaylist, self.highliteTrack) self.error_bar("BMPty: Added New Directory to the playlist...") except Exception,e: self.error_bar("Error AddUriList: "+str( e )) except Exception,e: self.error_bar("BMPty: Error Adding files: "+str( e )) 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) 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) 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) except Exception, e: self.error_bar("BMPty: error adding files: "+str(e)) 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: try: # UGLY HACK # this basically makes BMPty toss unicoded filenames path = path.encode("utf-8") array.append("file://"+directory+path) except: pass #self.error_bar("file://"+directory+path) else: # Enter possible Subdirectory array = self.add_dir(array, directory+path) return array def move_items(self, mode, list_o_items, destination): destination -= 1 list_o_locations = [] for track in list_o_items: e = self.bmpx.GetMetadataForListItem(self.activeplaylist, track) list_o_locations.append(e['location']) #self.error_bar() if mode == "move-items": self.bmpx.TracklistRemoveItems(self.activeplaylist, list_o_items, len(list_o_items)) if destination == self.activeplaylist: place = self.highliteTrack for track in list_o_items: if track < self.highliteTrack: place -=1 self.bmpx.AddUriList(list_o_locations, destination, place) else: self.bmpx.AddUriList(list_o_locations, destination, -1) self.error_bar("Moved items to playlist: "+ self.playlists[destination]) else: if destination == self.activeplaylist: self.bmpx.AddUriList(list_o_locations, destination, -1) self.error_bar("Copied items to playlist: "+ self.playlists[destination]) self.selectedTracks = [] def gethertz(self, channel): if channel == 0: hertz = "30Hz" elif channel == 1: hertz = "60Hz" elif channel == 2: hertz = "125Hz" elif channel == 3: hertz = "250Hz" elif channel == 4: hertz = "500Hz" elif channel == 5: hertz = "1Khz" elif channel == 6: hertz = "2KHz" elif channel == 7: hertz = "4KHz" elif channel == 8: hertz = "8KHz" elif channel == 9: hertz = "16KHz" return hertz def display_mixer(self): try: #eq = self.bmpx.EqGet(7) #self.playlistwin.clear() eqwin= curses.newwin(7, 65, 4, 5) eqwin.bkgdset(" ", curses.A_BOLD) eqwin.idlok(1) eqwin.border() eqwin.addstr( 0, 1, "< Equalizer >") pos = 2 for channel, vol in self.equalizer.items(): if channel == self.currentChannel: eqwin.addstr(2, pos, str(vol), self.colors["yellow"]) eqwin.addstr(" ") eqwin.addstr(4, pos, self.gethertz(channel), self.colors["yellow"]) else: eqwin.addstr(2, pos, str(vol)+" ") eqwin.addstr(4, pos, self.gethertz(channel), self.colors["cyan"]) pos += 6 eqwin.refresh() except: self.error_bar("Error displaying mixer") def toggle_help(self): if self.helpshow == False: self.helpshow = True #self.display_instructions(self.instructionstring[1]) self.display_instructions() else: self.helpshow = False self.instructionswin.erase() self.instructionswin.refresh() self.refresh_windows() if self.mixermode == True: self.display_mixer() self.helpboxwin.erase() if self.helpshow == True: self.helpboxwin.addstr("Help", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"]) else: self.helpboxwin.addstr("Help", self.colors["redwhite"] | curses.A_REVERSE) self.helpboxwin.refresh() def refresh_windows(self): self.mainowin.redrawwin() self.mainowin.refresh() self.playlistsidebar.redrawwin() self.playlistsidebar.refresh() self.playlistscroll.redrawwin() self.playlistscroll.refresh() def mixer(self): if self.mixermode == True: self.mixermode = False self.helpshow = False self.helpboxwin.erase() self.helpboxwin.addstr("Help", self.colors["redwhite"] | curses.A_REVERSE) self.helpboxwin.refresh() self.refresh_windows() #self.playlistwin.redrawwin() #self.playlistwin.refresh() #self.display_instructions() self.display_playlist() #self.display_instructions(self.instructionstring[0]) else: self.mixermode = True #self.display_instructions() self.display_mixer() if self.helpshow == True: self.display_instructions() self.eqboxwin.scrollok(0) self.eqboxwin.erase() if self.mixermode == True: self.eqboxwin.addstr("EQ", curses.A_REVERSE| curses.A_BOLD| self.colors["cyan"]) else: self.eqboxwin.addstr("EQ", self.colors["redwhite"] | curses.A_REVERSE) self.eqboxwin.refresh() def update_config(self): # Save Config File to disk try: update_config() self.error_bar("BMPty: Saved Config") sleep(0.5) self.error_bar("BMPty ;)") except: self.error_bar("ERROR saving Config..") def delete_playlist(self): name = self.playlists[self.activeplaylist] self.bmpx.TracklistRemove(self.activeplaylist) self.error_bar("BMPty: Deleted list: %s" % name ) 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 elif direction == "left": if self.activeplaylist - 1 in range(len(self.playlists)): self.activeplaylist -= 1 else: self.activeplaylist = len(self.playlists)-1 else: self.activeplaylist = direction # 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.draw_playlist_label() 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) while self.continue_build == 1: sleep(0.1) self.build(self.stdscr, line, "screen") # refresh only the screen, do not rebuild the playlists (much faster) if self.connected == False: if key in ( "KEY_F(5)", "KEY_F(6)", "KEY_F(7)", "KEY_F(8)", "KEY_F(10)"): if key in ("KEY_F(5)"): self.update_config() elif key in ("KEY_F(6)"): self.launch_bmpx() elif key in ("KEY_F(7)"): if bmpty_config["bmpx"]["auto-launch"] == "yes": bmpty_config["bmpx"]["auto-launch"] = "no" else: bmpty_config["bmpx"]["auto-launch"] = "yes" self.launch_options() elif key in ("KEY_F(8)"): if bmpty_config["bmpx"]["daemonize"] == "yes": bmpty_config["bmpx"]["daemonize"] = "no" return else: bmpty_config["bmpx"]["daemonize"] = "yes" self.launch_options() self.launch_bmpx() elif key in ("KEY_F(10)"): # Quit BMPty self.shutdown() return # If disconnected from BMPx, ignore all commands from keyboard or mouse # except the above. if 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 if self.mixermode == False: # IF NOT USING the MIXER if y == 0: if x >= 0 and x < self.w-self.sidebar_w: # 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 >=2 and y<= self.h-2 and x < self.w-self.sidebar_w: y = y -2 if event in (64, 256): # (un)mark tracks selected 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: # Highlight track on click self.highliteTrack = len(self.playlist_dict[self.activeplaylist]) -1 if event in (8, 16384): # Play track on doubleclick or rightclick self.bmpx.PlayListTrack(self.activeplaylist, self.highliteTrack) self.display_playlist() elif y >self.h-2 and x >= self.w-self.sidebar_w-23 and x < self.w-self.sidebar_w: # Switch to next playlist self.switchplaylist("right") if y in (0, 1, 2) and x >= self.w-self.sidebar_w: if x >= self.w-self.sidebar_w and x < self.w-self.sidebar_w+2: if self.currentVolume > 0: if self.currentVolume == 1: self.bmpx.VolumeSet (0) else: self.bmpx.VolumeSet (self.currentVolume-2) elif x >= self.w-self.sidebar_w+2 and x < self.w-self.sidebar_w+5: if self.currentVolume < 100: if self.currentVolume == 99: self.bmpx.VolumeSet (100) else: self.bmpx.VolumeSet (self.currentVolume+2) elif y in (3, 4) and x >= self.w-self.sidebar_w: if x >= self.w-self.sidebar_w and x < self.w-self.sidebar_w+5: # Toggle Mixer self.mixer() elif x >= self.w-15 and x < self.w-7: # Toggle Shuffle 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 > self.sidebar_t and y < self.sidebar_t + self.sidebar_h-1 and x >= self.w-self.sidebar_w: self.error_bar(y) y -=5 if y in range(len(self.listz)): s = self.listz[y] y =self.playlists.index( s ) if y in self.playlist_dict.keys(): self.switchplaylist(y) #self.h-3 - y elif y == self.sidebar_t + self.sidebar_h-1: if x >= self.w-self.sidebar_w+13: self.delete_playlist() elif x < self.w-self.sidebar_w+7 and x >= self.w-self.sidebar_w+1: self.edit.inputmode = "new-list" self.mainowin.addstr( self.h-3, 1, "< Create a New List >") self.mainowin.refresh() self.error_bar("\n") elif x < self.w-self.sidebar_w+12 and x >= self.w-self.sidebar_w+8: self.edit.inputmode = "rename-list" self.mainowin.addstr( self.h-3, 1, "< Rename this List >") self.mainowin.refresh() self.error_bar("\n") elif y >=self.h-2 and x >= self.w -self.sidebar_w: if x >= self.w-self.sidebar_w and x < self.w-self.sidebar_w+5: self.toggle_help() elif 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() if self.mixermode == True: if key in( "KEY_LEFT", "CC", chr(2)): if self.currentChannel > 0: self.currentChannel -= 1 self.display_mixer() elif key in("KEY_RIGHT", chr(6) ): if self.currentChannel < 9: self.currentChannel += 1 self.display_mixer() elif key in ("KEY_UP"): if self.equalizer[self.currentChannel] < 100: self.bmpx.EqSet(self.currentChannel, self.equalizer[self.currentChannel]+1) elif key in ("KEY_DOWN"): if self.equalizer[self.currentChannel] > -100: self.bmpx.EqSet(self.currentChannel, self.equalizer[self.currentChannel]-1) elif key == "KEY_PPAGE": # Page UP if self.equalizer[self.currentChannel] < 100: if self.equalizer[self.currentChannel] < 90: self.bmpx.EqSet(self.currentChannel, self.equalizer[self.currentChannel]+10) else: self.bmpx.EqSet(self.currentChannel, 100) elif key == "KEY_NPAGE": # Page DOWN if self.equalizer[self.currentChannel] > -100: if self.equalizer[self.currentChannel] > -90: self.bmpx.EqSet(self.currentChannel, self.equalizer[self.currentChannel]-10) else: self.bmpx.EqSet(self.currentChannel, -100) elif key == "KEY_HOME": # HOME if self.equalizer[self.currentChannel] < 100: self.bmpx.EqSet(self.currentChannel, 100) elif key == "KEY_END": # END if self.equalizer[self.currentChannel] > -100: self.bmpx.EqSet(self.currentChannel, -100) elif key == 0: self.bmpx.EqSet(self.currentChannel, 0) elif key in ("m", "M"): for i, v in self.equalizer.items(): if v != 100: self.bmpx.EqSet(i, 100) elif key in ("f", "F"): for i, v in self.equalizer.items(): if v != 0: self.bmpx.EqSet(i, 0) elif key in ("n", "N"): for i, v in self.equalizer.items(): if v != -100: self.bmpx.EqSet(i, -100) elif self.mixermode == False: if key in( "KEY_LEFT", "CC", chr(2)): if self.current_pos != 0 and self.length != 0: pass elif self.length == 0: return else: #percent=0 return if self.current_pos != 0: if self.current_pos-5 > 0: self.bmpx.Seek(self.current_pos-5) else: self.bmpx.Seek(0) elif key in("KEY_RIGHT", chr(6) ): if self.current_pos != 0 and self.length != 0: pass elif self.length == 0: return else: #percent=0 return if self.current_pos + 5 < self.length: self.bmpx.Seek(self.current_pos+5) else: self.bmpx.Seek(self.length) 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) t = 0 for string, time in self.playlist_dict[self.activeplaylist]: if line == t+1: self.error_bar("Jumped to: %s" % string) self.highliteTrack =t self.display_playlist() sleep(0.4) self.error_bar("BMPty ;)") return t += 1 self.error_bar("Nothing Matches: %d " % line) else: line_ignorecase = re.compile('.*' + line + '.*', re.DOTALL | re.I) t = 0 for string, time in self.playlist_dict[self.activeplaylist]: if re.match( line_ignorecase,string): self.error_bar("Jumped to: %s" % string) self.highliteTrack = self.playlist_dict[self.activeplaylist].index([string, time]) #self.highliteTrack = t self.display_playlist() sleep(0.4) self.error_bar("BMPty ;)") return self.error_bar("Nothing Matches: %s" % line) elif key == "file": # Parse line for path/files and request them to be added to # current playlist self.addfiles(line) 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 if self.mixermode == False: self.helpshow = False # 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 if self.mixermode == False: self.helpshow = False # 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 == "KEY_HOME": # HOME if self.mixermode == False: self.helpshow = False # Scroll to the top of the playlist window #if self.highliteTrack < len(self.playlist_dict[self.activeplaylist]) -1: # self.highliteTrack += self.h-4 if self.highliteTrack != 0: self.highliteTrack = 0 self.display_playlist() elif key == "KEY_END": # END if self.mixermode == False: self.helpshow = False # Scroll to the bottom of the playlist window if self.highliteTrack != len(self.playlist_dict[self.activeplaylist]) -1: self.highliteTrack = len(self.playlist_dict[self.activeplaylist]) -1 self.display_playlist() elif key == "sort_up": if self.sortnumber >0: self.sortnumber -= 1 self.draw_sort() elif key == "sort_down": if self.sortnumber < 5: self.sortnumber += 1 self.draw_sort() elif key == "scroll_up": if self.mixermode == False: if self.helpshow == True: self.toggle_help() # Scroll up the playlist window one item if self.highliteTrack > 0: self.highliteTrack -= 1 self.display_playlist() elif key == "scroll_down": if self.mixermode == False: if self.helpshow == True: self.toggle_help() # 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.delete_playlist() elif key in ("move-items", "copy-items"): if self.selectedTracks == []: list_o_items = [self.highliteTrack] else: list_o_items = self.selectedTracks if line.isdigit(): if int(line) > 0 and int(line) <= len(self.playlists): self.move_items(key, list_o_items, int(line)) else: self.error_bar("No playlist number matches: %s" % line) elif line == "": self.move_items(key, list_o_items, self.activeplaylist+1 ) else: line_ignorecase = re.compile('.*' + line + '.*', re.DOTALL | re.I) a = 0 for lists in self.playlists: if re.match( line_ignorecase, lists): #self.error_bar(line+" is in "+ lists +str ( self.playlists.index(lists) ) ) self.move_items(key, list_o_items, self.playlists.index(lists) ) a = 1 if a == 0: self.error_bar("No playlist matches string: %s" % line) 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 == "o": # Force a Redraw self.build(self.stdscr, line, "screen") #cself.build_playlists(-1) elif key in ( "l", "L"): # Cycle thru playlists to the right self.switchplaylist("right") 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 == chr(10) or key == "KEY_ENTER": # If not in currenttracklist (i.e., the playing tracklist), set it as current if self.showsort == True: self.bmpx.TracklistSort(self.activeplaylist, self.sortnumber) self.sortnumber = 0 self.showsort = False self.playlistwin.redrawwin() self.playlistwin.refresh() return 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 ("W", "w"): if self.showsort == False: self.create_sort() else: self.showsort = False self.playlistwin.redrawwin() self.playlistwin.refresh() # End Playlist-only keys if 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 == "?": # Toggle the help display self.toggle_help() elif key in ("u", "U"): self.mixer() elif key == "KEY_F(5)": self.update_config() elif key in ("KEY_F(7)"): if bmpty_config["bmpx"]["auto-launch"] == "yes": bmpty_config["bmpx"]["auto-launch"] = "no" self.error_bar("BMPx Auto-Launching Disabled") else: bmpty_config["bmpx"]["auto-launch"] = "yes" self.error_bar("BMPx Auto-Launching Enabled") sleep(1) self.update_config() elif key in ("KEY_F(8)"): if bmpty_config["bmpx"]["daemonize"] == "yes": bmpty_config["bmpx"]["daemonize"] = "no" self.error_bar("BMPx Daemon Launching Disabled") else: bmpty_config["bmpx"]["daemonize"] = "yes" self.error_bar("BMPx Daemon Launching Enabled") sleep(1) self.update_config() 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 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 in ("KEY_F(10)"): # Quit BMPty self.shutdown() elif key in ("q"): # Kill BMPx self.bmpx.Quit() def shutdown(self): # Quit BMPty curses.nocbreak() curses.echo() curses.endwin() if bmpty_config["display"]["terminal_title"] == "yes": if os.path.expandvars("$SHELL") in ("/bin/bash", "/bin/sh"): os.system("echo -ne \"\033]0;`pwd`\007\" ") #self.decode_language(self.titlestring) os._exit(1) 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.addstr('\n'+c) #self.win.refresh() #self.win(self.line) # debugging: display keypress # if c == "KEY_RESIZE": self.escaped(c, self.line) if self.BMPMonitor.connected == False: if c in ( "KEY_F(5)", "KEY_F(6)", "KEY_F(7)", "KEY_F(8)", "KEY_F(10)"): self.escaped(c, self.line) return True if self.inputmode == "normal": self.color_red() self.win.refresh() self.line = "" if c in ('z', 'Z','x','X','c', 'v','V','b'): self.escaped(c, self.line) #elif c == "^?": # if self.BMPMonitor. 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(5)", "KEY_F(6)", "KEY_F(7)", "?", "a", "A", "KEY_F(8)", "KEY_F(10)"): self.escaped(c, self.line) elif c in ("KEY_PPAGE", "KEY_DC", "KEY_NPAGE", "KEY_HOME", "KEY_END"): self.escaped(c, self.line) elif c == "w": 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 ( "u", "U"): if self.escape: self.escaped(c, self.line) elif c in ("p", "P", "m", "M", "f", "F", "n", "N", "r", "R", 0): if self.BMPMonitor.mixermode == True: if c in ("m", "M", "f", "F", "n", "N", 0): self.escaped(c, self.line) return True if self.escape: if c in ("p", "P"): self.inputmode = "copy-items" self.mainowin.addstr( self.h-3, 1, "< Copy to Playlist.. >") self.color_blue() self.win.addstr('\n') elif c in ("m", "M"): self.inputmode = "move-items" self.mainowin.addstr( self.h-3, 1, "< Move to Playlist.. >") self.color_blue() self.win.addstr('\n') elif c in ("n", "N"): self.inputmode = "new-list" self.mainowin.addstr( self.h-3, 1, "< Create a New List >") self.color_blue() self.win.addstr('\n') elif c in ( "r", "R"): self.inputmode = "rename-list" self.mainowin.addstr( self.h-3, 1, "< Rename this List >") playlist = self.BMPMonitor.playlists[self.BMPMonitor.activeplaylist] self.line = playlist self.color_blue() self.win.addstr("\n"+playlist) self.x = len(playlist) else: return True #self.escaped(c, self.line) self.mainowin.refresh() 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": if self.BMPMonitor.mixermode == False: c = "scroll_up" if self.BMPMonitor.showsort ==True: c = "sort_up" self.escaped(c, self.line) elif c == "KEY_DOWN": if self.BMPMonitor.mixermode == False: c = "scroll_down" if self.BMPMonitor.showsort ==True: c = "sort_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.color_blue() 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.color_blue() 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.inputmode = "normal" self.color_red() self.win.refresh() self.mainowin.addstr( self.h-3, 1, " "*35, curses.ACS_HLINE) self.mainowin.refresh() self.escaped(c, self.line) self.x = 0 return True elif c in ("KEY_MOUSE", "KEY_F(6)"): self.escaped(c, self.line) elif c == chr(27): # ESC self.escape = True self.inputmode = "normal" self.color_red() self.mainowin.addstr( self.h-3, 1, " "*35, curses.ACS_HLINE) self.mainowin.refresh() self.win.addstr("\nBMPty :(") self.win.refresh() self.line = '' self.x = 0 return True 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 color_blue(self): self.win.attron(self.BMPMonitor.colors["cyan"]) self.win.bkgdset(" ", curses.A_REVERSE | self.BMPMonitor.colors["cyan"]) def color_red(self): self.win.attron(self.BMPMonitor.colors["redwhite"]) self.win.bkgdset(" ", curses.A_REVERSE | self.BMPMonitor.colors["redwhite"]) 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, "all") Mapp.app.capturekeys.start() gtk.gdk.threads_enter() gtk.main() gtk.gdk.threads_leave() def die(self, w, e): # GoodBye, Cruel World! :( self.app.shutdown() 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