diff options
Diffstat (limited to 'jmpd.py')
-rw-r--r-- | jmpd.py | 219 |
1 files changed, 219 insertions, 0 deletions
@@ -0,0 +1,219 @@ +import socket +from thread import start_new_thread +from traceback import print_exc +import codecs +import os + +from mutagen.easyid3 import EasyID3 + +from clSettings import Settings + +VERSION='0.1' +MUSIC_DIRECTORY="music_directory" +ENCODING="UTF-8" + +class server: + ssocket=None + _sockets=[] + + def __init__(self): + self._jmpd=jmpd() + self._sockets=[] + + def start(self, port, type=socket.SOCK_STREAM): + try: + self.ssocket=socket.socket(socket.AF_INET, type) + self._start_server(port) + except: + print_exc() + return + + def _start_server(self, port): + self.ssocket.bind(('localhost', port)) + self.ssocket.listen(5) + self.ssocket.settimeout(None) + + print("Started jmpd v%s" % (VERSION)) + while True: + csock,caddr=self.ssocket.accept() + self._sockets.append(csock) + #start_new_thread(self.handle, (csock, caddr)) + self.handle(csock, caddr) + + def _read(self, file): + line="" + while line=="": + line=file.readline() + return line.strip() + def _write(self, file, line): + file.write("%s\n" % (line)) + + def handle(self, csocket, caddr): + print("Incoming connection from %s" % (str(caddr))) + file=csocket.makefile('rw', 0) + self._write(file, 'hello jmpd %s'%(VERSION)) + + try: + while True: + line=self._read(file) + print line + except: + print_exc() + + def closeAll(self): + for socket in self._sockets: + socket.close() + +def _getName(line): + return line[0:line.find(': ')] +def _getValue(line): + return line[line.find(': ')+2:] + +tags=['title', 'artist', 'album', 'tracknumber', 'genre'] +class jmpd: + _lib=None # library + _settings=None + + def __init__(self): + self._lib=[] + self._settings=Settings("mpdconf") + self.readLib() + + def writeLib(self): + all_tags=tags + encoding=ENCODING + tags.append('filename') + + fout=codecs.open(self._settings.get("db_file"), mode='w', encoding=encoding) + fout.write("# jmpd\n") + fout.write("begin info\n") + fout.write("encoding: %s\n" % (encoding)) + fout.write("jmpd: %s\n" % (VERSION)) + fout.write("end info\n") + fout.write("\n") + + fout.write("begin library\n") + cur_path="" + for entry in self._lib: + if entry['path']!=cur_path: + fout.write("set path: %s\n" % entry['path']) + cur_path=entry['path'] + + fout.write("begin file\n") + for tag in all_tags: + if tag in entry: + fout.write("%s: %s\n" % (tag, entry[tag])) + fout.write("end file\n") + + fout.write("end library\n") + fout.close() + + def readLib(self): + """Restore the library from file""" + db_file=self._settings.get("db_file") + encoding=ENCODING + if os.path.exists(db_file)==False: + self._lib=[] + return + + # we first open the file in ASCII-mode, and read on till the real encoding + # then we reopen it in that encoding + fin=open(db_file, 'r') + fin.close() + fin=codecs.open(db_file, mode='r', encoding=encoding) + + self._readLine(fin) # begin info + encoding=_getValue(self._readLine(fin)) + version=_getValue(self._readLine(fin)) + if version!=VERSION: + raise Exception("Invalid database file") + self._readNext(fin, 'end info') + + self._readNext(fin, 'begin library') + cur_path="" + while True: + line=self._readLine(fin) + if line=="end library": + break + if _getName(line)=="set path: ": + cur_path=_getValue(line) + elif line=="begin file": + self._readFile(fin, cur_path, encoding) + + fin.close() + + def _readFile(self, fin, cur_path, encoding): + """Read the data for a file""" + entry={'filepath': cur_path} + line="" + while line!="end file": + line=self._readLine(fin) + if line.find(': ')>0: + entry[_getName(line)]=_getValue(line) + + self._lib.append(entry) + def _readEnd(self, fin, section): + """Read the next line containing an end section""" + line="" + while line!="end %s"%(section): + line=self._readLine(fin) + return line + def _readBegin(self, fin, section): + """Read the next line containing a begin section""" + line="" + while line!="begin %s"%(section): + line=self._readLine(fin) + return line + + def _readNext(self, fin, find): + line="" + while line!=find: + line=self._readLine(fin) + return line + def _readLine(self, fin): + """Reads the next line having characters and not being a commented line""" + ret="\n" + try: + while ret=="\n" or ret[0]=='#': + ret=fin.readline() + except: + pass + if len(ret)==0: + raise Exception("EOF") + return ret.strip() + + + def update(self): + """Look for songs in the music_directory""" + self._lib=[] + for dir in self._settings.get(MUSIC_DIRECTORY).split(":"): + self._update_rec(dir) + + self.writeLib() + + def _update_rec(self, path): + subdirs=[] + for filename in os.listdir(path): + filepath="%s/%s"%(path,filename) + if os.path.isdir(filepath): + subdirs.append(filepath) + if filename[-4:]==".mp3": + audio=EasyID3(filepath) + entry = {'path': path.decode(ENCODING) + , 'filename': filename.decode(ENCODING) + } + for tag in tags: + try: + value=str(audio[tag]) + entry[tag]=value[3:-2] + except: + entry[tag]='' + self._lib.append(entry) + + for subdir in subdirs: + self._update_rec(subdir) + +from test import port +s=server() +s.start(port) + |