def settag(self): # if len(self.tagger.tags): # loggy.log( str(self.tagger.tags)) loggy.log(str(len(self.totag))+' of '+str(self.totaltotag)+' remaining') mime = mimetypes.guess_type(self.tagger.filename)[0] # take mime out into function? if not mime: loggy.warn('Mime type error in settag - no mime info') elif mime.startswith("audio"): type = 'audio' elif mime.startswith("video"): type = 'video' else: loggy.warn('Mime type error in settag - mime info incorrect') self.tagger.tags['uri'] = self.tagger.filename if len(type)>0: #try: row = [] for key in self.keys: if key in self.tagger.tags: row.append(self.tagger.tags[key]) else: row.append('') row.append(type) #(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(self.tagger.filename) row = row + [1,2,3,4,5] print row self.insert_row('media', row) #self.insert_row(type, [self.tagger.filename, self.tagger.tags['artist'], self.tagger.tags['title']]) #except: #loggy.log('OOOOOOOOOOOOOOOOOOOOOOOOOOOO')#TODO: - deal with errors properly self.gettag()
def settag(self): loggy.log(str(len(self.totag)) + " of " + str(self.totaltotag) + " remaining") mime = mimetypes.guess_type(self.tagger.uri)[0] # take mime out into function? if not mime: loggy.warn("Mime type error in settag - no mime info") elif mime.startswith("audio"): type = "audio" elif mime.startswith("video"): type = "video" else: loggy.warn("Mime type error in settag - mime info incorrect") self.tagger.tags["uri"] = self.tagger.uri self.tagger.tags["mime"] = type # print self.tagger.uri[7:] # (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(self.tagger.uri[7:]) # filetemp = Gio.file_new_for_uri(self.tagger.uri) #file_new_for_uri # temp.query_info('*',flags=gio.FILE_QUERY_INFO_NONE, cancellable=None) # info = filetemp.query_info('standard::mtime') self.tagger.tags["mtime"] = int(os.path.getmtime(self.tagger.uri[7:])) if len(type) > 0: # try: row = [] for key in self.keys: if key in self.tagger.tags: row.append(self.tagger.tags[key]) else: row.append(None) print(str(row)) self.insert_media(row) self.gettag()
def load_id(self, songid): #self.sb.player.load_uri(self.sb.sbdb.get_id_db_info(id)['uri']) try: self.sb.player.load_uri(self.sb.sbdb.get_id_db_info(songid)['uri']) except TypeError: loggy.warn('could not get next playlist item, skipping') self.get_next()
def load_uri(self, uri, callback): self.__init__()#TODO work out how to load file without recreating pipeline self.tags = {} self.uri = uri self.error = None self.callback = callback loggy.warn( "Tagger loading " + uri) self.playbin.set_property("uri", uri) self.player.set_state(Gst.State.PLAYING)
def on_play_state_change(self, player): #TODO: - make player only emit one signal for each event #state = self.sb.player.getstate() loggy.debug('gui.on_play_state_change ' + self.sb.player.state) if (self.sb.player.state == 'play'): for playbutton in self.widgets['play_buttons']: playbutton.set_label(Gtk.STOCK_MEDIA_PAUSE) elif (self.sb.player.state == 'pause' or self.sb.player.state == 'stop'): for playbutton in self.widgets['play_buttons']: playbutton.set_label(Gtk.STOCK_MEDIA_PLAY) else: loggy.warn('gui.on_play_state_change got unknown state: ' + self.sb.player.state)
def on_message(self, bus, message): if message.type == gst.MESSAGE_EOS: #TODO: reorder for speed , or take signals out individually... self.get_next() elif message.type == gst.MESSAGE_ERROR: self.reset() err, debug = message.parse_error() loggy.log( "Player GST_MESSAGE_ERROR: " + str(err) + str(debug)) self.get_next() elif message.type == gst.MESSAGE_STATE_CHANGED: self.update_play_state() elif message.type == gst.MESSAGE_STREAM_STATUS: self.update_position() elif message.type == gst.MESSAGE_NEW_CLOCK: None elif message.type == gst.MESSAGE_ASYNC_DONE: self.emit('async-done') for comm in self.on_update_tags: comm() loggy.log('Player Async Done') elif message.type == gst.MESSAGE_TAG: # thanks to http://www.jezra.net/blog/use_python_and_gstreamer_to_get_the_tags_of_an_audio_file taglist = message.parse_tag() for key in taglist.keys(): self.tags[key] = taglist[key] # if key == 'image': # img = open('temp', 'w') # img.write(taglist[key]) # img.close() # else: # True #loggy.log('Player GST tag:' + key + ' : ' + str(taglist[key]) ) #gst_tag_list_free()? elif message.type == gst.MESSAGE_DURATION: format = gst.Format(gst.FORMAT_TIME) self.dur = self.player.query_duration(format)[0] self.dursec = int(self.dur / gst.SECOND) elif message.type == gst.MESSAGE_ELEMENT: if message.structure is None: return message_name = message.structure.get_name() if message_name == "prepare-xwindow-id": imagesink = message.src loggy.warn('Player prepare-xwindow-id got') imagesink.set_property("force-aspect-ratio", True) #gtk.gdk.threads_enter() if self.vidout.has_key('xid'): imagesink.set_xwindow_id(self.vidout['xid']) #imagesink.set_xwindow_id(self.VID.window.xid) #gtk.gdk.threads_leave() elif message_name == "have-xwindow-id": None else: loggy.log( "Player GST message unhandled:" + str(message.type)) else: loggy.warn('Player - unknown messge' + str(message.type))
def startserver(self, host, port): self.host = host self.port = port self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.sock.bind((self.host, self.port)) #TODO: check port empty first except: loggy.warn('mpdserver failed to start on host %s port %s' % (self.host, self.port)) return False self.sock.listen(1) loggy.log('mpdserver Interface Running on ' + host + ':' + str(port) ) GObject.io_add_watch(self.sock, GObject.IO_IN, self.listener)
def add_uri(self, uri, pos=None): loggy.debug('playlist.add_uri '+str(uri)+str(pos)) songid = self.sb.sbdb.get_uri_db_info(uri) if songid: songid = songid['songid'] if pos is not None: self.add_songid(songid, pos) else: self.add_songid(songid) return songid else: loggy.warn('could not add uri {0} to playlist - not in db') return False
def read_playlist_from_giofile(self, giofile): name = giofile.get_path() (success, contents, tag) = giofile.load_contents() contents = contents.decode().splitlines() #print(contents) if contents.pop(0).startswith('#EXTM3U'): #playlist found, wipe/create playlist with that name self.playlists[name] = [] for line in contents: if line.startswith('/'): self.playlists[name].append('file://'+line) elif (line.startswith('#')): None else: loggy.warn('Could not analyse line in playlist '+name+' :'+line) loggy.log('Found '+str(len(self.playlists[name]))+' items in m3u playlist '+name) self.playlist=self.playlists[name] self.sb.player.emit('new-playlist',name)
def read_playlist_dir(self): self.plfolder = Gio.File.new_for_path(path=self.sb.config.config['playlistfolder']) query = self.plfolder.query_file_type(Gio.FileQueryInfoFlags.NONE, None) if (query != Gio.FileType.DIRECTORY): loggy.warn('Playlist folder is not a directory:' + self.sb.config.config['playlistfolder']) return childrenenumerator = self.plfolder.enumerate_children('standard::display-name,time::modified', Gio.FileQueryInfoFlags.NONE, None)#fills childrenenumerator with fileinfos of child files of directory with information on display name and modified (only). Follows symlinks. See https://developer.gnome.org/pygobject/2.18/gio-constants.html#gio-file-attribute-constants. Content type does not seem to be particularly useful in this context while True: fl = childrenenumerator.next_file() if fl: if fl.get_display_name().lower().endswith('.m3u'): #loggy.log('found playlist'+ fl.get_display_name()) self.read_playlist_from_giofile(self.plfolder.get_child_for_display_name(fl.get_display_name()), ) else: loggy.log('Done reading playlist folder') break self.plmonitor = self.plfolder.monitor_directory(Gio.FileMonitorFlags.NONE, None) if self.plmonitor == None: loggy.warn('unable to monitor playlist directory') self.plmonitor.connect('changed', self.playlist_monitor_changed)
def __init__(self, soundblizzard): #load defaults first then config file then command line args self.config = { 'configfile' : os.path.expanduser('~/.config/soundblizzard/soundblizzard.conf'), 'libraryfolders' : [os.path.expanduser('~/Music')], #TODO: support multiple folders 'playlistfolder' : '~/.config/playlists', 'databasefile' : os.path.expanduser('~/.config/soundblizzard/soundblizzard.db'), 'mpdhost' : 'localhost', 'mpdport' : 6600, 'dbupdatetime' : loggy.currenttime() } if (not(os.path.isdir(os.path.dirname(self.config['configfile'])))): os.makedirs(os.path.dirname(self.config['configfile'])) or loggy.warn ('could not create config dir') # if (not (os.path.isfile('~/.config/soundblizzard/soundblizzard.conf'))) fd = None try: fd = open(self.config['configfile'], 'r')#tries to open config file except: loggy.warn('Could not open config file '+ self.config['configfile']) try: self.config.update(json.load(fd)) #adds config file to dictionary and overrides with config file except: loggy.warn('Could not read config file '+ self.config['configfile']) #Handle command line arguments #Splits command line args into dict, if key starts with -- then takes this as an argument and prints these # if key is help prints defaults #TODO: improve command line argument recognition a = sys.argv[1:] if len(a) % 2: a.append('') b = {a[i]: a[i+1] for i in range(0, len(a), 2)} c ={} for key in b: if key.startswith('--help'): loggy.warn ('Soundblizzard media player\nTo amend config settings please use --key \'value\' on the command line. \n Current values:') print json.dumps(self.config, sort_keys=True, indent=2) loggy.die('help delivered') elif key.startswith('--'): c[key[2:]] = b[key] self.config.update(c) loggy.log('Configuration:' +str(self.config))
def on_message(self, bus, message): if message.type == gst.MESSAGE_EOS: #TODO: reorder for speed , or take signals out individually... self.emit('eos')#called when end of stream reached elif message.type == gst.MESSAGE_ERROR: self.reset() err, debug = message.parse_error() loggy.warn( "Player GST_MESSAGE_ERROR: " + str(err) + str(debug)) self.emit('eos') elif message.type == gst.MESSAGE_STATE_CHANGED: if message.src == self.player: self.updatestate() elif message.type == gst.MESSAGE_STREAM_STATUS: #loggy.log('ss') appears to be related to buffering status #self.update_position() None elif message.type == gst.MESSAGE_NEW_CLOCK: None elif message.type == gst.MESSAGE_ASYNC_DONE: self.emit('async-done') loggy.log('Player Async Done') elif message.type == gst.MESSAGE_TAG: # thanks to http://www.jezra.net/blog/use_python_and_gstreamer_to_get_the_tags_of_an_audio_file taglist = message.parse_tag() for key in taglist.keys(): self.tags[key] = taglist[key] #gst_tag_list_free()? elif message.type == gst.MESSAGE_DURATION: self.updatedur() elif message.type == gst.MESSAGE_QOS: loggy.log('QOS') elif message.type == gst.MESSAGE_ELEMENT: if message.structure is None: return message_name = message.structure.get_name() if message_name == "prepare-xwindow-id": imagesink = message.src loggy.warn('Player prepare-xwindow-id got') imagesink.set_property("force-aspect-ratio", True) #gtk.gdk.threads_enter() if self.vidout.has_key('xid'): imagesink.set_xwindow_id(self.vidout['xid']) #imagesink.set_xwindow_id(self.VID.window.xid) #gtk.gdk.threads_leave() elif message_name == "have-xwindow-id": loggy.log('have xwindow id') else: loggy.log( "Player GST message unhandled:" + str(message.type)) else: loggy.warn('Player - unknown messge' + str(message.type))
def on_message(self, bus, message): if message.type == Gst.MessageType.EOS: #TODO: reorder for speed , or take signals out individually... see http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/video-player-1.0 self.emit('eos')#called when end of stream reached elif message.type == Gst.MessageType.ERROR: self.reset() err, debug = message.parse_error() loggy.warn( "Player GST_MESSAGE_ERROR: " + str(err) + str(debug)) self.emit('eos') elif message.type == Gst.MessageType.STATE_CHANGED: if message.src == self.player: self.updatestate() elif message.type == Gst.MessageType.STREAM_STATUS: #loggy.log('ss') appears to be related to buffering status #self.update_position() None elif message.type == Gst.MessageType.NEW_CLOCK: None elif message.type == Gst.MessageType.ASYNC_DONE: self.emit('async-done') loggy.log('Player Async Done') elif message.type == Gst.MessageType.TAG: # thanks to http://www.jezra.net/blog/use_python_and_gstreamer_to_get_the_tags_of_an_audio_file taglist = message.parse_tag() #gst_tag_list_free()? for key in dbtags.keys(): self.tags[key] = taglist.get_value_index(key, 0) elif message.type == Gst.MessageType.DURATION_CHANGED: self.updatedur()#could query message? elif message.type == Gst.MessageType.QOS: loggy.log('QOS') elif message.type == Gst.MessageType.ELEMENT: if message.structure is None: return message_name = message.get_structure().get_name() if message_name == "prepare-window-handle": loggy.warn('Player prepare-window-handle got') message.src.set_property("force-aspect-ratio", True) #gtk.gdk.threads_enter() if self.vidout.has_key('xid'): message.src.set_window_handle(self.vidout['xid']) #imagesink.set_xwindow_id(self.VID.window.xid) #gtk.gdk.threads_leave() elif message_name == "have-xwindow-id": loggy.log('have xwindow id') else: loggy.log( "Player GST message unhandled:" + str(message.type)) elif (message.type == Gst.MessageType.STREAM_START or message.type == Gst.MessageType.RESET_TIME): None else: loggy.warn('Player - unknown message' + str(message.type))
def on_message(self, bus, message): #Gst.MESSAGE_TAG:thanks to http://www.jezra.net/blog/use_python_and_gstreamer_to_get_the_tags_of_an_audio_file #msgtype = (Gst.message_type_get_name(message.type)) #print('message') 'TODO implement as dict rather than if elif for speed if ((message.type == Gst.MessageType.STREAM_STATUS) or (message.type == Gst.MessageType.STATE_CHANGED) or (message.type == Gst.MessageType.STREAM_START)): True elif (message.type == Gst.MessageType.TAG): print('tag MESSAGE') print (self.player.query_duration(Gst.Format.TIME)) taglist = message.parse_tag() #other ways of accessing list are taglist.to_string() or taglist.foreach() or taglist.get_string('artist') for key in dbtags.keys(): self.tags[key] = taglist.get_value_index(key, 0) elif (message.type == Gst.MessageType.ASYNC_DONE): #Gst.MESSAGE_ASYNC_DONE: query = Gst.Query.new_duration(Gst.Format.TIME) print(self.playbin.query(query)) print (self.player.query_duration(Gst.Format.TIME)) #print (self.player.get_state(1)) self.tags['duration'] = int ((self.playbin.query_duration(Gst.Format.TIME)[1]) / Gst.SECOND) #print str(self.player.query_duration(Gst.Format.TIME)) self.tags['uri'] = self.uri #self.tags['date'] = self.tags['date'].year loggy.log('Tagger got ' + str(self.tags)) #self.player.set_state(Gst.State.NULL) #TODO: replace mime types with Gstreamer alternative from Gst.extend self.callback() elif (message.type == Gst.MessageType.DURATION_CHANGED): #Gst.MESSAGE_DURATION: ?does this ever happen self.tags['duration'] = int ((int(self.playbin.query_duration(Gst.Format.TIME)[1]) / Gst.SECOND)) loggy.warn('got duration huzzah!') #TODO not working at present elif (message.type == Gst.MessageType.ERROR): #Gst.MESSAGE_ERROR: err, debug = message.parse_error() loggy.warn( "Player GST_MESSAGE_ERROR: " + str(err) + str(debug)) #TODO: sort out unicode self.error = str(debug) if self.error: self.player.set_state(Gst.State.NULL) self.__init__() self.callback() else: loggy.warn( "Player GST message unhandled:" + str(message.type))
try: import pygst, gobject, loggy, config pygst.require("0.10") import gst except: loggy.warn('player - Could not find required libraries: pygst, gst, gobject, loggy, config') class player(gobject.GObject): ''' Player - gst player ''' __gproperties__ = { 'vol' : (gobject.TYPE_INT, 'volume', 'Current volume of gstreamer pipeline', 0, 100, 50, gobject.PARAM_READWRITE) } __gsignals__ = { 'async-done' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 'hemisecond' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()) } # def do_get_property(self, property): # if property.name == 'vol': # return self.vol # else: # raise AttributeError, 'unknown property %s' % property.name def do_set_property(self, property, value): loggy.log('player.do_set_property') if property.name == 'vol': self.vol = value
try: import ConfigParser, os, loggy except: loggy.warn('config - Could not find required libraries: ConfigParser') class config( ConfigParser.SafeConfigParser ): #TODO: use linux format, not ini (could not find suitable python module def load(self): self.file = os.path.expanduser('~') + "/.spambox/spambox.ini" self.read(self.file) def defaults(self): try: self.add_section('Main') except: None self.set('Main', 'dbfile', os.path.expanduser('~') + "/.spambox/spambox.sqlite") self.set('Main', 'imagefile', os.path.expanduser('~') + "/.spambox/image") self.set('Main', 'playlistsfolder', os.path.expanduser('~') + "/Music/Playlists") self.set('Main', 'libraryfolders', os.path.expanduser('~') + "/Music " + os.path.expanduser('~') + "/Videos ") self.set('Main', 'mediatags', ' '.join(['uri', 'artist', 'title', 'album', 'date', 'genre', 'duration', 'rating'])) def __del__(self): with open(self.file, 'wb') as configfile: self.write(configfile) if __name__ == "__main__": conf = config() conf.load() conf.defaults()
def save_config(self): #import json configfd = open(self.config['configfile'], 'w') or loggy.warn('Could not open config file for writing') json.dump(self.config, configfd, sort_keys=True, indent=2) #or loggy.warn ('Could not write config file') configfd.close()
def handler(self, conn, *args): '''Asynchronous connection handler. Processes each line from the socket.''' buff = conn.recv(65536) #TODO: handle if more on conn to recieve than 4096 if not len(buff): loggy.log( "mpdserver Connection closed - no input." ) return False elif len(buff)>60000: loggy.warn('mpdserver Connection buff full, data may be lost' . buff) #loggy.log('MPD Server got:' +buff) while '\n' in buff: (line, buff) = buff.split("\n", 1) output = '' if not len(line): loggy.log( "mpdserver Connection closed - no input." ) return False else: arg = line.strip().split(' ', 1) #strips whitespace from right and left, then splits first word off as command command = arg[0].lower() # prevents case sensitivity #TODO: reimplement using a dict? if (len(arg)>1): # if there are arguments to the command args = arg[1].strip() else: args = '' #Tries to recognise command #Playback control func = None loggy.debug('mpdserver got {0} {1}'.format(command, args)) # Makes sure command is not internal function if command in self.list_of_commands: #loggy.warn('mpdserver attempt to access internals {0}'.format(command)) #Searches for command in current class try: func = getattr(self, command) except Exception as detail: output = 'ACK 50@1 {{{0}}} Command not recognised\n'.format (command) loggy.warn('mpdserver: {0}'.format(output)) self.queueing = False self.ok_queueing = False else: #Executes command try: output = func(args) except Exception as detail: output = 'ACK 50@1 {{{0}}} {1} {2} {3}\n'.format(command, detail, str(type(detail)), traceback.format_exc().replace('\n', '|')) loggy.warn('mpdserver: {0}'.format(output)) self.queueing = False self.ok_queueing = False else: # not in list_of_commands output = 'ACK 50@1 {{{0}}} Command not in command list\n'.format (command) loggy.debug('mpdserver {0} not in command list'.format(command)) #Handles output - with respect to list queueing if not output: output = 'ACK 1@1 {{{0}}} Command returned no output - not implemented yet\n'.format(command) loggy.warn('mpdserver: {0}'.format(output)) elif output.startswith('ACK'): self.queueing = False self.ok_queueing = False output = self.queue + output self.queue = '' if self.ok_queueing: #if output[-3:-1] == 'OK': #output = output[:-3] + 'list_OK\n' output = output.replace("OK", "list_OK") self.queue += output output = '' elif self.queueing: self.queue += output output = '' #send output if (output != None): loggy.debug( 'MPD Server sending: {0}'.format( output) ) conn.send(output) return True
try: import loggy, os, sqlite3, mimetypes, tagger, except: loggy.warn('sbdb - Could not find required libraries: loggy, os, sqlite3, mimetypes, tagger, gobject, config') class sbdb(object): keys = ('uri', 'artist', 'title', 'album', 'date', 'genre', 'duration', 'rating') # + mimetype , atime, mtime, ctime, dtime def __init__(self, soundblizzard): self.config = soundblizzard.config self.config.load() self.dbpath = self.config.get('Main', 'dbfile') loggy.log("Database: Loading database from " + self.dbpath) self.conn = sqlite3.connect(self.dbpath) self.curs = self.conn.cursor() self.conn.row_factory = sqlite3.Row self.keys = ('uri', 'artist', 'title', 'album', 'date', 'genre', 'duration', 'rating') # + mimetype , atime, mtime, ctime, dtime self.addkeys = ('mimetype', 'atime', 'mtime', 'ctime', 'dtime', 'size') self.totkeys = self.keys + self.addkeys self.conn.commit() #self.conn.close() def sqlexec(self, string): loggy.log('Database sqlexec:' + string) self.curs.execute(string) # vulnerable to sql injection attacks - should assemble strings within execute #self.conn.commit() def create_table(self, name, fields): self.sqlexec('create table if not exists "%s" ( "%s" )' % (name, '" , "'.join(fields))) def recreate_table(self, name, fields): self.sqlexec('drop table if exists "%s" ' % name) self.sqlexec('create table "%s" ("%s")' % (name, '" , "'.join(fields))) def insert_row(self, table, data): data = [str(item) for item in data]
def handler(self, conn, *args): '''Asynchronous connection handler. Processes each line from the socket.''' buffer = conn.recv(4096) #TODO: handle if more on conn to recieve than 4096 if not len(buffer): loggy.log( "MPD Connection closed - no input." ) return False elif len(buffer)>4000: loggy.warn('MPD Connection buffer full, data may be lost' . buffer) loggy.log('MPD Server got:' +buffer) while '\n' in buffer: (line, buffer) = buffer.split("\n", 1) output = '' if not len(line): loggy.log( "MPD Connection closed - no input." ) return False else: arg = line.rstrip().lstrip().split(' ', 1) #strips whitespace from right and left, then splits first word off as command command = arg[0].lower() # prevents case sensitivity #TODO: reimplement using a dict? if (len(arg)>1): # if there are arguments to the command args = arg[1].lower().lstrip() else: args = False #Tries to recognise command #Playback control if command == 'play': self.player.play() output = 'OK\n' elif command == 'next': output = 'OK\n' #TODO: elif command == 'pause': self.player.pause() output = 'OK\n' elif command == 'playid': output = 'OK\n' #TODO: elif command == 'previous': output = 'OK\n'#TODO: elif command == 'seek': #TODO: handle songpos if args.isdigit() and self.player.setpos(int(args)) : output = 'OK\n' else: loggy.log('mpdserver - could not understand seek to ' + args) output = 'ACK could not understand arguments\n' elif command == 'seekid': #TODO: output = 'OK\n' elif command == 'stop': self.player.stop() output = 'OK\n' #Status elif command == 'clearerror':#TODO: implement print 'Recognised command clearerror' output = 'OK' elif command == 'currentsong': output += 'file: %s\n' % (self.player.filename) output += 'Time: %i\n' % (self.player.dursec) output += 'Artist: %s\n' % (self.player.tags['artist']) output += 'AlbumArtist: %s\n' % (self.player.tags['album-artist']) output += 'Title: %s\n' % (self.player.tags['title']) output += 'Album: %s\n' % (self.player.tags['artist']) output += 'Track: %s\n' % ((str(self.player.tags['track-number'])+'/'+str(self.player.tags['track-count']))) output += 'Date: %s\n' % (str(self.player.tags['date'].year)) output += 'Genre: %s\n' % (self.player.tags['genre']) output += 'Pos: %i\n' % (1) output += 'Id: %i\n' % (1) output += 'OK\n' elif command == 'idle': output = 'changed: database update stored_playlist playlist player mixer output options sticker subscription message\nOK\n'#TODO: handle properly elif command == 'status': output += 'volume: %i\n' % (self.player.getvol()) output += 'repeat: %i\n' % (0) output += 'random: %i\n' % (0) output += 'single: %i\n' % (0) output += 'consume: %i\n' % (0) output += 'playlist: %i\n' % (1) output += 'playlistlength: %i\n' % (1) output += 'xfade: %i\n' % (0) output += 'state: %s\n' % (self.player.getstate()) output += 'song: %i\n' % (1) output += 'songid: %i\n' % (1) output += 'Time: %s\n' % (self.player.getpos()) output += 'bitrate: %i\n' % (1) output += 'audio: %s\n' % ('x') output += 'nextsong: %i\n' % (1) output += 'nextsongid: %i\n' % (1) output += 'OK\n' elif command == 'stats': print 'Recognised status command' output = 'artists: %i\nalbums: %i\nsongs: %i\nuptime: %i\nplaytime: %i\ndb_playtime: %i\ndb_update: %i\nOK\n' % (1,1,1,1,1,1,1) #Playback Options elif command == 'consume': print 'Recognised consume command' if args == '0': output = 'OK\n' print 'set consume 0' elif args == '1': output = 'OK\n' print 'set consume 1' else: output = 'ACK [2@0] {consume} usage consume 0 or consume 1\n' elif command == 'crossfade': output = 'OK\n' elif command == 'mixrampdb': output = 'OK\n' elif command == 'mixrampdelay': output = 'OK\n' elif command == 'random': output = 'OK\n' elif command == 'repeat': output = 'OK\n' elif command == 'setvol': vol = args.strip('"') if vol.isdigit() and int(vol) <=100 and int(vol) >=0 and self.player.setvol(vol): output = 'OK\n' else: loggy.log('mpdserver - could not understand setvol to ' + args) output = 'ACK could not understand arguments\n' elif command == 'single': output = 'OK\n' elif command == 'replay_gain_mode': output = 'OK\n' elif command == 'replay_gain_status': output = 'OK\n' #Current Playlist elif command == 'add': output = 'OK\n' elif command == 'addid': output = 'OK\n' elif command == 'clear': output = 'OK\n' elif command == 'delete': output = 'OK\n' elif command == 'deleteid': output = 'OK\n' elif command == 'move': output = 'OK\n' elif command == 'moveid': output = 'OK\n' elif command == 'playlist': output = 'OK\n' elif command == 'playlistfind': output = 'OK\n' elif command == 'playlistid': output = 'OK\n' elif command == 'playlistinfo': output = 'OK\n' elif command == 'playlistsearch': output = 'OK\n' elif command == 'plchanges': self.trackdetails('file:///home/sam/Music/09 - Girl Talk - Make Me Wanna.mp3') output = 'OK\n' elif command == 'plchangesposid': output = 'OK\n' elif command == 'shuffle': output = 'OK\n' elif command == 'swap': output = 'OK\n' elif command == 'swapid': output = 'OK\n' #Stored playlists elif command == 'listplaylist': output = 'OK\n' elif command == 'listplaylistinfo': output = 'OK\n' elif command == 'listplaylists': output = 'OK\n' elif command == 'load': output = 'OK\n' elif command == 'playlistadd': output = 'OK\n' elif command == 'playlistclear': output = 'OK\n' elif command == 'playlistdelete': output = 'OK\n' elif command == 'playlistmove': output = 'OK\n' elif command == 'rename': output = 'OK\n' elif command == 'rm': output = 'OK\n' elif command == 'save': output = 'OK\n' #Music db elif command == 'count': output = 'OK\n' elif command == 'find': output = 'OK\n' elif command == 'findadd': output = 'OK\n' elif command == 'list': output = 'OK\n' elif command == 'listall': output = 'OK\n' elif command == 'listallinfo': output = 'OK\n' elif command == 'lsinfo': output = 'OK\n' elif command == 'search': output = 'OK\n' elif command == 'update': output = 'OK\n' elif command == 'rescan': output = 'OK\n' elif command == '': output = 'OK\n' #Command queueing elif command == 'command_list_begin': print 'starting queueing commands' loggy.warn('command_list_begin used on mpd client') self.queueing = True elif command == 'command_list_end': print 'ended queueing commands' self.queueing = False self.ok_queueing = False output = self.queue + 'OK\n' self.queue = '' elif command == 'command_list_ok_begin': print 'starting queueing commands' self.ok_queueing = True loggy.warn('command_list_ok_begin used on mpd client') #Connection elif command == 'close': conn.send('OK\n') conn.close() loggy.log('MPD Connection closed by client') return False elif command == 'ping': output = 'OK\n' elif command == 'kill': conn.send('OK\n') conn.close() loggy.die('MPD Client Killed spambox, weep!') #Output elif command == 'disableoutput': output = 'OK\n' elif command == 'enableoutput': output = 'OK\n' elif command == 'outputs': output = 'OK\n' #Error handler else: loggy.log(''.join(['MPD Interface - Unrecognised Command (Perhaps a newer client version?) :', command,':'])) output += 'ACK Unrecognised Command\n' self.queueing = False self.ok_queueing = False #TODO: reflection, stickers, client to client #Respond to client if self.ok_queueing: #if output[-3:-1] == 'OK': #output = output[:-3] + 'list_OK\n' output.replace("OK", "list_OK") self.queue += output output = '' elif self.queueing: self.queue += output output = '' loggy.log( 'MPD Server sending:' + output ) conn.send(output) #TODO: if error return True
''' Created on 20 Mar 2011 @author: sam ''' try: import socket, gobject, loggy, player except: loggy.warn('Could not find required libraries: socket gobject loggy player') class mpdserver(object): ''' MPD Server Class - creates MPD Server connection Settings - self.port = tcp_port self.host = tcp_host ''' def __init__(self, gst_obj): ''' ''' self.queue = '' self.queueing = False self.ok_queueing = False self.player = gst_obj def startserver(self, host, port): self.host = host self.port = port self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((self.host, self.port)) #TODO: check port empty first self.sock.listen(1) loggy.log('MPD Server Interface Running on ' + host + ':' + str(port) )
try: import loggy, player, gobject except: loggy.warn("Could not find required libraries: loggy, player, gobject") class playlist(object): def __init__(self, player): self.player = player self.playlist = [] self.random = False self.repeat = True self.player.bus.connect("message::eos", self.get_next) self.load_playlist("ben") self.get_next() def load_playlist(self, filename): self.playlist = [ "file:///data/Music/Alien Ant Farm/ANThology/01 Courage.mp3", "file:///data/Music/Armand Van Helden/NYC Beat/02 - NYC Beat (Original).mp3", "file:///data/Music/Various Artists/Reloaded 4/13. Flavor Of The Weak.mp3", ] self.position = -1 self.get_next() def get_next(self): if self.random: True else: self.position += 1 if self.position >= (len(self.playlist)):
try: import pygst pygst.require("0.10") import gst import gobject import loggy import datetime except: loggy.warn('Could not find required libraries: pygst, gst, gobject, datetime') class gstr(object): ''' Player - gst player ''' def __init__(self): self.player = gst.element_factory_make("playbin", "player") #self.vis = gst.element_factory_make("goom", "vis") self.bus = self.player.get_bus() self.bus.add_signal_watch() self.bus.enable_sync_message_emission() self.bus.connect("message", self.on_message) self.bus.connect("sync-message::element", self.on_sync_message) self.reset def load_file(self, filename): self.reset() loggy.log( "Player loading " + filename ) self.player.set_property("uri", "file://" + filename) #self.player.set_state(gst.STATE_PLAYING) self.player.set_state(gst.STATE_PAUSED) #self.player.set_property("vis-plugin", self.vis) def reset(self):
def __init__(self, sb): GObject.GObject.__init__(self) self.sb = soundblizzard.soundblizzard # fakes for tab completion self.sb = sb # self.config = soundblizzard.config.config #provides direct access to config dictionary if not (os.path.isdir(os.path.dirname(self.sb.config.config["databasefile"]))): loggy.warn("Creating directories for requested database file") os.makedirs(os.path.dirname(self.sb.config.config["databasefile"])) or loggy.warn( "...could not create config dir" ) self.dbpath = self.sb.config.config["databasefile"] loggy.log("Database: Loading database from " + self.dbpath) if loggy.debug: sqlite3.enable_callback_tracebacks(True) self.conn = sqlite3.connect(self.dbpath) or loggy.warn("Could not connect to database") self.conn.row_factory = sqlite3.Row self.curs = self.conn.cursor() self.curs.row_factory = sqlite3.Row self.keys = ( "artist", "title", "album", "date", "genre", "duration", "rating", "album-artist", "track-count", "track-number", "mimetype", #'atime', "mtime", #'ctime', #'dtime', #'size', "uri", "songid", ) # songid must be last as it's the primary key self.blanktags = { "artist": "", "title": "", "album": "", "date": 0, "genre": "", "duration": 0, "rating": 0, "album-artist": "", "track-count": 1, "track-number": 1, "mimetype": "", #'atime':0, "mtime": 0, #'ctime':0, #'dtime':0, #'size':0, "uri": "", "songid": None, } # self.keys = self.blanktags.keys()[0:10]#('uri', 'artist', 'title', 'album', 'date', 'genre', 'duration', 'rating','album-artist', 'track-count', 'track-number') # + mimetype , atime, mtime, ctime, dtime #TODO:autogenerate from blank dict # self.addkeys = self.blanktags.keys()[10:] #('mimetype', 'atime', 'mtime', 'ctime', 'dtime', 'size') # self.totkeys = self.keys + self.addkeys +('songid',) # self.blanktags = {} # creates blank key set so no type errors when key looked up does not exist # for key in self.totkeys: # self.blanktags[key] = None # TODO: move gubbins to config # self.conn.commit() # TODO: check database is okay, contains tables and necessary fields etc. try: self.curs.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='media'") self.curs.execute("SELECT * from 'media'") except sqlite3.OperationalError: loggy.log("Database: no media table, recreating") self.recreate_media_table()
def on_sync_message(self): loggy.warn('Player got sync message, unhandled')
#!/usr/bin/env python #try: try: import gi, loggy, player gi.require_version('Gst', '1.0') from gi.repository import GObject, Gst, Gtk, GdkPixbuf, GdkX11, GstVideo except: loggy.warn('Gui could not import required libraries') # import soundblizzard # import player, loggy, gst, cairo, aspectimage # from gi.repository import Gtk # from gi.repository import GdkPixbuf # from gi.repository import GdkX11 # from gi.repository import GObject #TODO: look at kiwi for pygtk lists etc. #pyGtk.require("2.0") #except: # print "gui - Required libraries not found - pyGtk, Gtk, player, loggy, gst, sbdb! Please install\n" #TODO: while gtk.gtk_events_pending(): gtk.gtk_main_iteration() - does this work? class GTKGui(object): def __init__(self, sb): loggy.log('Gui loading...') #self.play_buttons = [] #self.progress_bars = [] #self.position_labels = [] self.volume_scales =[] #self.info_labels = [] self.album_arts = [] self.main_trees = [] self.slave_windows = [] self.main_tree_modes = {}
#!/usr/bin/python try: import gi, loggy #gi.require_version('Gst', '1.0') from gi.repository import GObject, Gst except: loggy.warn('Tagger 3 could not import required libraries') GObject.threads_init() Gst.init(None) dbtags = {'artist':'', 'title':'', 'album':'', 'date':0, 'genre':'', 'duration':0, 'rating':0, 'album-artist':'', 'track-count':1, 'track-number':1, #'mimetype':'', #'atime':0, #'mtime':0, #'ctime':0, #'dtime':0, #'size':0, #'uri':'', #'songid':None }