Ejemplo n.º 1
0
    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')
Ejemplo n.º 2
0
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()