summaryrefslogtreecommitdiff
path: root/jmpd.py
diff options
context:
space:
mode:
Diffstat (limited to 'jmpd.py')
-rw-r--r--jmpd.py219
1 files changed, 219 insertions, 0 deletions
diff --git a/jmpd.py b/jmpd.py
new file mode 100644
index 0000000..0d36ca0
--- /dev/null
+++ b/jmpd.py
@@ -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)
+