def __init__(self, sticker_file=os.path.expanduser('~/.mpd/sticker.sql'), musiclib=os.path.expanduser('~/Music/')): self.__current_cover = None self.__current_song = {} self.mpdcli = MPDClient() self.mpdcli.timeout = 600 self.mpdcli.connect('localhost', 6600) self.__set_notify_client('mpdrator') self.sticker_db = None self.musiclib = musiclib self.updated = False self.default_rating = 4 self.db_queue = queue.Queue() self.pipefn = '/tmp/mpdrator' if os.path.exists(self.pipefn): os.unlink(self.pipefn) os.mkfifo(self.pipefn) self.sticker_file = sticker_file self.sticker_db = sqlite3.connect(sticker_file) if self.sticker_file else None self.show() print('Init finished')
class mpdrator: def __init__(self, sticker_file=os.path.expanduser('~/.mpd/sticker.sql'), musiclib=os.path.expanduser('~/Music/')): self.__current_cover = None self.__current_song = {} self.mpdcli = MPDClient() self.mpdcli.timeout = 600 self.mpdcli.connect('localhost', 6600) self.__set_notify_client('mpdrator') self.sticker_db = None self.musiclib = musiclib self.updated = False self.default_rating = 4 self.db_queue = queue.Queue() self.pipefn = '/tmp/mpdrator' if os.path.exists(self.pipefn): os.unlink(self.pipefn) os.mkfifo(self.pipefn) self.sticker_file = sticker_file self.sticker_db = sqlite3.connect(sticker_file) if self.sticker_file else None self.show() print('Init finished') def run(self): try: daemon_thread = threading.Thread(target=self.__listen) supervisor_thread = threading.Thread(target=self.__superviser) daemon_thread.start() supervisor_thread.start() daemon_thread.join() supervisor_thread.join() finally: os.unlink(self.pipefn) @staticmethod def starify(rating, black_star=u'\u2605', half_star=u'\u272E', white_star=u'\u2606'): if mpdrator.is_valid_ranking(rating): return black_star * int(int(rating) / 2) + \ (int(rating) % 2 != 0 and half_star or "") + \ white_star * (5 - int(rating) // 2 - int(rating) % 2) else: # raise ArithmeticError("I cant starify a not number like type") return 'Bad Rating Value (%s )' % (str(rating), ) def search(self, query, query_type="any", on="library"): places = { "library" : self.mpdcli.search, "playlist" : self.mpdcli.playlistsearch } yield from places[on](query_type, query) def __set_priority(self, song_pos, prio, song_end=None): args = song_pos, song_end if song_end else song_pos, self.mpdcli.prio(*args) def get_song(self, q): if str(q).isnumeric(): return self._search_song_by_id(q) else: return self._search_song(q) def set_priority(self, *args): if len(args) < 2: raise Exception('Not enough parameters') prio = args.pop(0) # specified start and end if len(args) == 2: start = self.search(args[0], on='library') end = self.search(args[1], on='library') elif len(args) == 1: start = self.search(args[0], on='library') else: raise Exception('Unsopported paramater number') @staticmethod def is_valid_ranking(rating): return str(rating).isnumeric() and 0 <= int(rating) <= 10 def __set_notify_client(self, name="mpdrator"): Notify.uninit() Notify.init("mpdrator") noti = Notify.Notification.new('Hey you', 'Go to hell') noti.show() self.notifier = noti def show(self): self.notifier.show() @property def current_song(self): if not self.__current_song or not self.updated: self.__current_song = self.mpdcli.currentsong() self.__current_song['albumart'] = self.cover self.__current_song['rating'] = self.rating() title = self.__current_song.get('title') rating = self.__current_song.get('rating') artist = self.__current_song.get('artist') album = self.__current_song.get('album') self.updated = True return self.__current_song @property def cover(self): if not self.__current_cover: self.__current_cover = self.__get_cover() return self.__current_cover def play(self): self.mpdcli.play() def pause(self): self.mpdcli.pause() def rating(self): if self.__dbr: with self.__dbr as db: cur = db.cursor() cur.execute("SELECT uri, value FROM sticker WHERE `uri` = ?", (self.__current_song.get('file'),)) song = cur.fetchone() return song[1] if song else None else: return None def set_rating(self, rating=None, song=None): if not rating: rating = self.default_rating if not song: song = self.__current_song.get('file') if type(rating) != int: print('Bad valud :"{0}" ({1}) '.format(rating, type(rating))) return False # print('Rating : {0} Song : {1}'.format(rating, song)) title = self.__current_song.get('title') artist = self.__current_song.get('artist') album = self.__current_song.get('album') stars = "[" + self.starify(rating) + "]" self.__update_notification("{0}\t{1}".format(title, stars), "{0} \n{1}".format(artist, album)) if not rating or not song: print('What da fuq, man?') return False if self.__dbw: with self.__dbw as db: cur = db.cursor() cur.execute("SELECT uri, value FROM sticker WHERE `uri` = ?", (self.__current_song.get('file'),)) exists = cur.fetchone() if exists: cur.execute("UPDATE sticker SET value = ? WHERE `uri` = ?", (rating, song)) else: cur.execute("INSERT INTO `sticker` (type, uri, name, value) VALUES ('song', ?, 'rating', ?)", (song, rating)) self.updated = False return True def idle(self): self.mpdcli.idle('player') if self.current_song.get('file') != self.mpdcli.currentsong().get('file'): self.__current_cover = None self.__current_song = None return True def __get_cover(self): coverfile= '{musiclib}/{currentsongpath}'.format(musiclib=self.musiclib, currentsongpath=self.__current_song.get('file')) coverfile += '/{name}.{ext}' cover = None for name,ext in [ (name, ext) for name in ["cover", "folder"] for ext in [ "jpg", "png"] ] : cover = "{0}/{1}/{2}.{3}".format(self.musiclib, os.path.dirname(self.__current_song.get('file', '')), name, ext) if os.path.isfile(cover): # print("Cover found! {0}".format(cover)) break return cover def __update_notification(self, title, body): self.notifier.update(title, body, icon = self.cover) self.show() def __superviser(self): self.__dbr = sqlite3.connect(self.sticker_file) while self.idle(): currentsong = self.current_song title = currentsong.get('title') artist = currentsong.get('artist') album = currentsong.get('album') cover = self.cover if self.__dbr: with self.__dbr as db: cur = db.cursor() cur.execute("SELECT uri, value FROM sticker WHERE `uri` = ?", (self.current_song.get('file'),)) song = cur.fetchone() else: song = None try: rating = "[" + self.starify(int(song[1])) + "]" except: rating = "" self.__update_notification("{0}\t{1}".format(title, rating), "{0} \n{1}".format(artist, album)) def __get_fifo_input(self): with open(self.pipefn, 'r') as pipe: # print('reading..') line = pipe.read()[:-1] # print('readed') # while not line or line == "\n" or line == " ": # line = pipe.readline()[:-1] pipe.flush() # for w in line.split(): return line # return line if line != 'exit' else False def __listen(self): self.__dbw = sqlite3.connect(self.sticker_file) if self.sticker_file else None actions = { 'display' : lambda args: self.show(), 'set_rating' : lambda args: str(args[0]).isnumeric() and self.set_rating(int(args[0])) and self.show() } line = self.__get_fifo_input() while line: print('triggering', line) items = line.split() actions.get(items[0], lambda: print('No valid action'))(items[1:]) line = self.__get_fifo_input() def __db(self): self.sticker_db = sqlite3.connect(sticker_file) if self.sticker_file else None while True: self.db_queue.get()