Exemple #1
0
 def populateList(self):
     self.client = MPDClient()
     self.client.connect('localhost', 6600)        
     self.playlistinfo = self.client.playlistinfo()
     self.client.disconnect()
             
     self.playlist = []
     
     #backgroundColor = QColor('#383C4A')
     #foregroundColor = QColor('#C1C1C1')
     
     for i in self.playlistinfo:
         row = ''
         if 'album' in i:
             row = row + i['album'] + ' - '
         if 'title' in i:
             if isinstance(i['title'], str):
                 row = row + i['title']
             else:
                 row = row + i['title'][0]
         if 'artist' in i:
             row = row + ' - ' + i['artist']
         self.playlist.append(row)
         #newRow = QListWidgetItem(row)
         #newRow.setBackground(backgroundColor)
         #newRow.setForeground(foregroundColor)
         #self.lw.addItem(newRow)
     self.visibleLw.addItems(self.playlist)
     self.visibleLw.setCurrentRow(0)
Exemple #2
0
    def __init__(self, **config):
        Notifier.__init__(self, **config)
        self.add_defaults(Client.defaults)

        self.client = MPDClient()
        self.client.host = self.host
        self.client.port = self.port
Exemple #3
0
 def __init__(self, server="localhost",port=6600):
     self.mpc = MPDClient()
     self.server = server
     self.port = port
     BarItem.__init__(self, "MPD")
     self.output['name'] = "NowPlaying"
     self.update()
Exemple #4
0
 def __init__(self, host="localhost", port="6600", password=None):
     super().__init__()
     self._comm = self._args = None
     self._mpd = host, port, password
     self._client = MPDClient()
     self._client.iterate = True
     self._cache = None
Exemple #5
0
class MPD(BarItem):

    def __init__(self, server="localhost",port=6600):
        self.mpc = MPDClient()
        self.server = server
        self.port = port
        BarItem.__init__(self, "MPD")
        self.output['name'] = "NowPlaying"
        self.update()

    def update(self):
        try:
            self.mpc.connect(self.server, self.port)
            status = self.mpc.status()
            if (status['state'] == "play"):
                song = self.mpc.currentsong()
                self.output['full_text'] = '► ' + song['artist'] + ' - ' + song['album'] + ' - ' + song['title']
            elif (status['state'] == "pause"):
                song = self.mpc.currentsong()
                self.output['full_text'] = '" ' + song['artist'] + ' - ' + song['album'] + ' - ' + song['title']
            else:
                self.output['full_text'] = status['state']
            self.mpc.disconnect()
        except:
            self.output['full_text'] = "MPD disconnected"
Exemple #6
0
def main():
    if 1 == len(sys.argv):
        print("You will have to give an argument.", file=sys.stderr)
        return 1
    # If nothing fails.
    return_value = 0
    try:
        # Connect to the MPD server
        client = MPDClient()
        client.connect("localhost", 6600)
        title_string = parser(client, str(sys.argv[1]))

    except:
        # Failure. Probably unable to connect to the MPD server.
        return_value = 1
        title_string = "Could not connect to the MPD server"

    # print( int( client.status()['time'].split(':')[0] ) )

    # If we have to cut dow the string or not
    if LENGTH >= len(title_string):
        # Have to append input, if it is shorter than LENGTH
        len_diff = LENGTH - len(title_string)
        append_before = (" ") * int((len_diff / 2))
        append_after = (" ") * int((len_diff / 2) + 0.5)

        # Prints and flushes the output
        print(append_before + title_string + append_after)
        # print(title_string)
        sys.stdout.flush()

    else:
        # Keep track of where to cut the long title string
        start = int(client.status()["time"].split(":")[0]) % (len(title_string) + len(DIVIDER))
        end = start + LENGTH

        # Appends to the title_string, so that we can roll-over easily
        title_string = title_string + DIVIDER + title_string

        print(title_string[start:end])
        sys.stdout.flush()

    # Closing the connection.
    client.close()
    client.disconnect()

    # Done!
    return return_value
Exemple #7
0
 def disconnect(self):
     # Try to tell MPD we're closing the connection first
     try:
         self._client.noidle()
         self._client.close()
     # If that fails, don't worry, just ignore it and disconnect
     except (MPDError, IOError):
         pass
     try:
         self._client.disconnect()
     # Disconnecting failed, so use a new client object instead
     # This should never happen.  If it does, something is seriously broken,
     # and the client object shouldn't be trusted to be re-used.
     except (MPDError, IOError):
         self._client = MPDClient()
Exemple #8
0
#!/usr/bin/env python2

from musicpd import MPDClient
import os

fifo_name = os.getenv("XDG_RUNTIME_DIR", "/tmp") + "/powerstatus10k/fifos/mpd"
mpd_host = os.getenv("MPD_HOST", "127.0.0.1")
mpd_port = os.getenv("MPD_PORT", "6600")

client = MPDClient()
client.connect(mpd_host, mpd_port)

while True:
    client.send_idle()
    client.fetch_idle()

    status = client.status()
    state = status["state"] if "state" in status else "stop"

    song = client.currentsong()
    artist = song["artist"] if "artist" in song else "Unknown Artist"
    title = song["title"] if "title" in song else "Unknown Title"

    # Do this here to avoid problems on a deleted FIFO during runtime.
    if not os.path.exists(fifo_name):
        os.mkfifo(fifo_name)

    with open(fifo_name, "w") as fifo:
        fifo.write(f"{state}:{artist}:{title}")
Exemple #9
0
class OrpheusLibrarySearch(QWidget):
    
    def __init__(self):
        super().__init__()
        self.initUI()
        self.populateList()
        
    def initUI(self):
        #palette = QPalette()
        #palette.setColor(QPalette.Background, QColor('#383C4A'))        
        #palette.setColor(QPalette.WindowText, QColor('#C1C1C1'))        
        #self.setPalette(palette)
        
        self.setMaximumSize(492, 653)
        self.setMinimumSize(492, 653)
        
        le = QLineEdit(self)
        le.textChanged[str].connect(self.onChanged)
        le.returnPressed.connect(self.onActivation)
        le.setClearButtonEnabled(True)
        le.setPlaceholderText('Start typing to search...')
        self.lw = QListWidget()
        self.visibleLw = QListWidget()
        #palette.setColor(QPalette.Base, QColor('#383C4A'))                        
        #self.visibleLw.setPalette(palette)        
        self.visibleLw.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.visibleLw.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)        
        self.visibleLw.itemActivated.connect(self.onActivation)
        self.scrollBar = QScrollBar()
        self.visibleLw.verticalScrollBar().valueChanged.connect(self.scrollBar.setValue)
        self.scrollBar.valueChanged.connect(self.visibleLw.verticalScrollBar().setValue)
        vbox = QVBoxLayout()
        vbox.setSpacing(3)
        #vbox.setContentsMargins(3, 3, 3, 3)
        vbox.setContentsMargins(0, 4, 0, 0)        
        vbox.addWidget(le)       
        hbox = QHBoxLayout()
        hbox.setSpacing(0)
        #hbox.setContentsMargins(0, 0, 0, 0)                
        hbox.addWidget(self.visibleLw)
        hbox.addWidget(self.scrollBar)
        vbox.addLayout(hbox)
        self.setLayout(vbox)
        
        self.setWindowTitle('Music Library')
        
        icon = QIcon.fromTheme('musique')
        self.setWindowIcon(icon)
        
    def populateList(self):
        self.client = MPDClient()
        self.client.connect('localhost', 6600)        
        self.playlistinfo = self.client.playlistinfo()
        self.client.disconnect()
                
        self.playlist = []
        
        #backgroundColor = QColor('#383C4A')
        #foregroundColor = QColor('#C1C1C1')
        
        for i in self.playlistinfo:
            row = ''
            if 'album' in i:
                row = row + i['album'] + ' - '
            if 'title' in i:
                if isinstance(i['title'], str):
                    row = row + i['title']
                else:
                    row = row + i['title'][0]
            if 'artist' in i:
                row = row + ' - ' + i['artist']
            self.playlist.append(row)
            #newRow = QListWidgetItem(row)
            #newRow.setBackground(backgroundColor)
            #newRow.setForeground(foregroundColor)
            #self.lw.addItem(newRow)
        self.visibleLw.addItems(self.playlist)
        self.visibleLw.setCurrentRow(0)
        
    def get_matches(self, pattern):
        self.visibleLw.clear()
        pattern = '.*' + pattern.replace(' ', '.*').lower()
        regexp = re.compile(pattern)
        for i in self.playlist:
            if regexp.match(i.lower()):
                self.visibleLw.addItem(i)                
                
    def formatScrollBar(self):            
        self.scrollBar.setMaximum(self.visibleLw.verticalScrollBar().maximum())                    
        self.scrollBar.setPageStep(self.visibleLw.verticalScrollBar().pageStep())
        
    def onChanged(self, text):
        self.get_matches(text)
        self.visibleLw.setCurrentRow(0)
        self.scrollBar.setMaximum(self.visibleLw.verticalScrollBar().maximum())        
        if self.visibleLw.verticalScrollBar().maximum() == 0:
            self.scrollBar.setVisible(False)
        else:
            self.scrollBar.setVisible(True)

    def onActivation(self):
        selected_song = self.visibleLw.currentItem().text()
        for i in range(0, len(self.playlist)):
            if selected_song == self.playlist[i]:
                self.client.connect('localhost', 6600)
                self.client.play(i)
                self.client.disconnect()       
        
    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Down:
            self.visibleLw.setFocus()
        elif e.key() == Qt.Key_Escape:
            self.close()
Exemple #10
0
def get_client():
    client = MPDClient()
    client.connect(app.config['MPD_ADDRESS'], app.config['MPD_PORT'])
    return client
Exemple #11
0
class KissMPD():
    def handle_idle(func):
        def inner(self, *args, **kwargs):
            self.__lock.acquire()
            self.__client.noidle()
            res = func(self, *args, **kwargs)
            self.__client.send_idle()
            self.__lock.release()
            return res

        return inner

    def __init__(self, fp):
        self.__fp = fp
        self.__client = MPDClient()
        self.__lock = threading.Lock()
        self.__idle_client = MPDClient()

    def connect(self):
        self.__client.connect('localhost', 6600)
        self.__idle_client.connect('localhost', 6600)
        status = self.__client.status()
        self.__state = status['state']
        self.__volume = int(status['volume'])
        try:
            self.__songid = status['songid']
        except:
            self.__songid = None
        self.__client.send_idle()
        self.__idle_client.send_idle()

    def disconnect(self):
        self.__client.disconnect()
        self.__idle_client.disconnect()

    def process(self):
        canRead = select([self.__idle_client], [], [], 0)[0]
        if canRead:
            changes = self.__idle_client.fetch_idle()
            self.__idle_client.send_idle()  # continue idling
            change = self.update_status()
            return change
        return None

    @handle_idle
    def refresh(self):
        self.display_current_song()

    def display_current_song(self):
        if (self.__songid):
            song = self.__client.currentsong()
            try:
                text = song['artist'] + ' - ' + song['title']
            except:
                text = song['file'].split('/')[-1]

            self.__fp.set_scrolling_text(3, 1, text + '           ')
            try:
                time = divmod(int(song['time']), 60)
                self.__fp.set_track_clock('0{0[0]:02}{0[1]:02}'.format(time))
            except:
                self.__fp.set_track_clock(None)
        else:
            self.__fp.clear()

    def display_volume(self):
        self.__fp.set_flash_text(8, 'Volume: ' + str(self.__volume))

    def display_state(self):
        if (self.__state != 'play'):
            self.__fp.clear()
            self.__fp.set_text('{0:^12}'.format(self.__state))
        else:
            self.display_current_song()

    @handle_idle
    def update_status(self):
        status = self.__client.status()

        try:
            songid = status['songid']
        except:
            songid = None

        if (songid != self.__songid):
            self.__songid = songid
            self.display_current_song()

        if (int(status['volume']) != self.__volume):
            self.__volume = int(status['volume'])
            self.display_volume()

        state = status['state']
        if (state != self.__state):
            self.__state = state
            self.display_state()
            return state

        return None

    @handle_idle
    def volume_down(self):
        self.__volume = self.__volume - 1
        if (self.__volume < 0):
            self.__volume = 0
        self.__client.setvol(self.__volume)
        self.display_volume()

    @handle_idle
    def volume_up(self):
        self.__volume = self.__volume + 1
        if (self.__volume > 100):
            self.__volume = 100
        self.__client.setvol(self.__volume)
        self.display_volume()

    @handle_idle
    def play(self, toggle=False):
        if (self.__state == 'play'):
            if toggle:
                self.__client.pause()
        else:
            self.__client.play()

    def play_pause(self):
        self.play(True)

    @handle_idle
    def pause(self):
        self.__client.pause(1)

    @handle_idle
    def previous(self):
        self.__client.previous()

    @handle_idle
    def next(self):
        self.__client.next()

    @handle_idle
    def stop(self):
        self.__client.stop()

    def handle_inputevent(self, ie):
        key2function = {
            'volume_down': self.volume_down,
            'volume_up': self.volume_up,
            'stop': self.stop,
            'play': self.play_pause,
            'next_track': self.next,
            'previous_track': self.previous,
            'right': self.next,
            'left': self.previous,
            'down': self.volume_down,
            'up': self.volume_up,
            'ok': self.play_pause,
            'mute': self.play_pause,
        }
        try:
            function = key2function[ie.key]
        except:
            function = None
        if not function:
            return False

        if (ie.type == InputEventType.hold):
            if (function == self.volume_down) or (function == self.volume_up):
                function()
        elif (ie.type == InputEventType.pressed):
            function()
        return True
Exemple #12
0
 def __init__(self, fp):
     self.__fp = fp
     self.__client = MPDClient()
     self.__lock = threading.Lock()
     self.__idle_client = MPDClient()
Exemple #13
0
def main():
    # If nothing fails.
    return_value = 0
    try:
        # Connect to the MPD server
        client = MPDClient()
        client.connect("localhost", 6600)
        
        # Runs the script until a new songs comes on
        currentTrack = client.status()['songid']

        # If there is no argument, we will use  "artist - title"
        if 1 == len(sys.argv):
            title_string = parser(client, "%artist% - %title%")
        else:
            title_string = parser(client, str(sys.argv[1]))
        
    except:
        # Failure. Probably unable to connect to the MPD server.
        return_value = 1
        title_string = "Could not connect to the MPD server"
        
    # If we have to cut dow the string or not
    if LENGTH >= len(title_string):
        # Have to append input, if it is shorter than LENGTH
        len_diff      = LENGTH - len(title_string)
        append_before = (' ') * int((len_diff/2))
        append_after  = (' ') * int((len_diff/2) + 0.5)

        # Prints and flushes the output
        print(append_before + title_string + append_after)
        sys.stdout.flush()
        
        # Now we only have to wait.
        #while client.status()['songid'] == currentTrack:
            #time.sleep(WAIT_TIME)
    else:
        # Appends to the title_string, so that we can roll-over easily
        title_string = title_string + DIVIDER + title_string[0:LENGTH]

        # Keep track of where to cut the long title string
        start = 0
        end   = LENGTH
        
        try:
            # While this song is playing
            while currentTrack == client.status()['songid']:
                # Print and flush
                print( title_string[start:end] )
                sys.stdout.flush()
                # Wait a little bit
                time.sleep(WAIT_TIME)
                # Step through the string
                start +=1
                end   +=1
                # We have are one lap through, so resert the steps
                if title_string[start:end] == title_string[0:LENGTH]:
                    start = 0
                    end   = LENGTH
        except:
            # Something failed.
            return_value = 1

    # Closing the connection.    
    client.close()
    client.disconnect()

    # Done!
    return return_value
Exemple #14
0
 def getOpenClient():
     client = MPDClient()
     client.connect('localhost', 6600)
     return client
Exemple #15
0
class Client(Notifier):
    """
    The host and port are 127.0.0.1 and 6600 by default but can be set by passing these
    when initiating the client.

    The notification timeout can be changed by setting Client.timeout to milliseconds
    (int) or -1, which then uses the notification server's default timeout.
    """
    defaults = [
        ('summary', 'Music', 'Notification summary.'),
        ('host', '127.0.0.1', 'IP address of MPD server.'),
        ('port', '6600', 'Port of MPD server.'),
    ]

    def __init__(self, **config):
        Notifier.__init__(self, **config)
        self.add_defaults(Client.defaults)

        self.client = MPDClient()
        self.client.host = self.host
        self.client.port = self.port

    @_client_func
    def toggle(self):
        if self.client.status()['state'] == 'play':
            self.client.pause()
        else:
            self.client.play()
        return bodies.get(self.client.status()['state'])

    @_client_func
    def next(self):
        self.client.next()
        current = self.client.currentsong()
        return f"{current['artist']} - {current['title']}"

    @_client_func
    def previous(self):
        self.client.previous()
        current = self.client.currentsong()
        return f"{current['artist']} - {current['title']}"

    @_client_func
    def stop(self):
        self.client.stop()
        return 'Stopped'
Exemple #16
0
class PlayerClient(Player):
    """MPD Client
    From python-musicpd:
        _fetch_nothing  …
        _fetch_item     single str
        _fetch_object   single dict
        _fetch_list     list of str
        _fetch_playlist list of str
        _fetch_changes  list of dict
        _fetch_database list of dict
        _fetch_songs    list of dict, especially tracks
        _fetch_plugins,
    TODO: handle exception in command not going through _client_wrapper() (ie.
          remove…)
    """
    database = None  # sima database (history, blacklist)

    def __init__(self, host="localhost", port="6600", password=None):
        super().__init__()
        self._comm = self._args = None
        self._mpd = host, port, password
        self._client = MPDClient()
        self._client.iterate = True
        self._cache = None

    def __getattr__(self, attr):
        command = attr
        wrapper = self._execute
        return lambda *args: wrapper(command, args)

    def _execute(self, command, args):
        self._write_command(command, args)
        return self._client_wrapper()

    def _write_command(self, command, args=None):
        self._comm = command
        self._args = list()
        for arg in args:
            self._args.append(arg)

    def _client_wrapper(self):
        func = self._client.__getattr__(self._comm)
        try:
            ans = func(*self._args)
        # WARNING: MPDError is an ancestor class of # CommandError
        except CommandError as err:
            raise PlayerCommandError('MPD command error: %s' % err)
        except (MPDError, IOError) as err:
            raise PlayerError(err)
        return self._track_format(ans)

    def _track_format(self, ans):
        """
        unicode_obj = ["idle", "listplaylist", "list", "sticker list",
                "commands", "notcommands", "tagtypes", "urlhandlers",]
        """
        # TODO: ain't working for "sticker find" and "sticker list"
        tracks_listing = ["playlistfind", "playlistid", "playlistinfo",
                          "playlistsearch", "plchanges", "listplaylistinfo", "find",
                          "search", "sticker find",]
        track_obj = ['currentsong']
        if self._comm in tracks_listing + track_obj:
            if isinstance(ans, list):
                return [Track(**track) for track in ans]
            elif isinstance(ans, dict):
                return Track(**ans)
        return ans

    def __skipped_track(self, old_curr):
        if (self.state == 'stop'
                or not hasattr(old_curr, 'id')
                or not hasattr(self.current, 'id')):
            return False
        return self.current.id != old_curr.id  # pylint: disable=no-member

    def _flush_cache(self):
        """
        Both flushes and instantiates _cache
        """
        if isinstance(self._cache, dict):
            self.log.info('Player: Flushing cache!')
        else:
            self.log.info('Player: Initialising cache!')
        self._cache = {'artists': frozenset(),
                       'nombid_artists': frozenset(),}
        self._cache['artists'] = frozenset(self._execute('list', ['artist']))
        if Artist.use_mbid:
            self._cache['nombid_artists'] = frozenset(self._execute('list', ['artist', 'musicbrainz_artistid', '']))

    @blacklist(track=True)
    def find_track(self, artist, title=None):
        tracks = set()
        if artist.mbid:
            if title:
                tracks |= set(self.find('musicbrainz_artistid', artist.mbid,
                                        'title', title))
            else:
                tracks |= set(self.find('musicbrainz_artistid', artist.mbid))
        else:
            for name in artist.names:
                if title:
                    tracks |= set(self.find('artist', name, 'title', title))
                else:
                    tracks |= set(self.find('artist', name))
        return list(tracks)

    @bl_artist
    def search_artist(self, artist):
        """
        Search artists based on a fuzzy search in the media library
            >>> art = Artist(name='the beatles', mbid=<UUID4>) # mbid optional
            >>> bea = player.search_artist(art)
            >>> print(bea.names)
            >>> ['The Beatles', 'Beatles', 'the beatles']

        Returns an Artist object
        """
        found = False
        if artist.mbid:
            # look for exact search w/ musicbrainz_artistid
            exact_m = self._execute('list', ['artist', 'musicbrainz_artistid', artist.mbid])
            if exact_m:
                _ = [artist.add_alias(name) for name in exact_m]
                found = True
        else:
            artist = Artist(name=artist.name)
        # then complete with fuzzy search on artist with no musicbrainz_artistid
        if artist.mbid:
            # we already performed a lookup on artists with mbid set
            # search through remaining artists
            artists = self._cache.get('nombid_artists')
        else:
            artists = self._cache.get('artists')
        match = get_close_matches(artist.name, artists, 50, 0.73)
        if not match and not found:
            return
        if len(match) > 1:
            self.log.debug('found close match for "%s": %s', artist, '/'.join(match))
        # Does not perform fuzzy matching on short and single word strings
        # Only lowercased comparison
        if ' ' not in artist.name and len(artist.name) < 8:
            for fuzz_art in match:
                # Regular lowered string comparison
                if artist.name.lower() == fuzz_art.lower():
                    artist.add_alias(fuzz_art)
                    return artist
        fzartist = SimaStr(artist.name)
        for fuzz_art in match:
            # Regular lowered string comparison
            if artist.name.lower() == fuzz_art.lower():
                found = True
                artist.add_alias(fuzz_art)
                if artist.name != fuzz_art:
                    self.log.debug('"%s" matches "%s".', fuzz_art, artist)
                continue
            # SimaStr string __eq__ (not regular string comparison here)
            if fzartist == fuzz_art:
                found = True
                artist.add_alias(fuzz_art)
                self.log.info('"%s" quite probably matches "%s" (SimaStr)',
                              fuzz_art, artist)
        if found:
            if artist.aliases:
                self.log.debug('Found: %s', '/'.join(list(artist.names)[:4]))
            return artist

    def fuzzy_find_track(self, artist, title):
        # Retrieve all tracks from artist
        all_tracks = self.find_track(artist, title)
        # Get all titles (filter missing titles set to 'None')
        all_artist_titles = frozenset([tr.title for tr in all_tracks
                                       if tr.title is not None])
        match = get_close_matches(title, all_artist_titles, 50, 0.78)
        if not match:
            return []
        for title_ in match:
            leven = levenshtein_ratio(title.lower(), title_.lower())
            if leven == 1:
                pass
            elif leven >= 0.79:  # PARAM
                self.log.debug('title: "%s" should match "%s" (lr=%1.3f)',
                               title_, title, leven)
            else:
                self.log.debug('title: "%s" does not match "%s" (lr=%1.3f)',
                               title_, title, leven)
                return []
            return self.find('artist', artist, 'title', title_)

    def find_album(self, artist, album):
        """
        Special wrapper around album search:
        Album lookup is made through AlbumArtist/Album instead of Artist/Album
        """
        alb_art_search = self.find('albumartist', artist, 'album', album)
        if alb_art_search:
            return alb_art_search
        return self.find('artist', artist, 'album', album)

    @blacklist(album=True)
    def search_albums(self, artist):
        """
        Fetch all albums for "AlbumArtist"  == artist
        Filter albums returned for "artist" == artist since MPD returns any
               album containing at least a single track for artist
        """
        albums = []
        for name in artist.names:
            if len(artist.names) > 1:
                self.log.debug('Searching album for aliase: "%s"', name)
            kwalbart = {'albumartist':name, 'artist':name}
            for album in self.list('album', 'albumartist', artist):
                if album and album not in albums:
                    albums.append(Album(name=album, **kwalbart))
            for album in self.list('album', 'artist', artist):
                album_trks = [trk for trk in self.find('album', album)]
                if 'Various Artists' in [tr.albumartist for tr in album_trks]:
                    self.log.debug('Discarding %s ("Various Artists" set)', album)
                    continue
                arts = set([trk.artist for trk in album_trks])
                if len(set(arts)) < 2:  # TODO: better heuristic, use a ratio instead
                    if album not in albums:
                        albums.append(Album(name=album, **kwalbart))
                elif album and album not in albums:
                    self.log.debug('"{0}" probably not an album of "{1}"'.format(
                        album, artist) + '({0})'.format('/'.join(arts)))
        return albums

    def monitor(self):
        curr = self.current
        try:
            self.send_idle('database', 'playlist', 'player', 'options')
            select([self._client], [], [], 60)
            ret = self.fetch_idle()
            if self.__skipped_track(curr):
                ret.append('skipped')
            if 'database' in ret:
                self._flush_cache()
            return ret
        except (MPDError, IOError) as err:
            raise PlayerError("Couldn't init idle: %s" % err)

    def clean(self):
        """Clean blocking event (idle) and pending commands
        """
        if 'idle' in self._client._pending:
            self._client.noidle()
        elif self._client._pending:
            self.log.warning('pending commands: %s', self._client._pending)

    def remove(self, position=0):
        self.delete(position)

    def add(self, track):
        """Overriding MPD's add method to accept add signature with a Track
        object"""
        self._execute('add', [track.file])

    @property
    def artists(self):
        return self._cache.get('artists')

    @property
    def state(self):
        return str(self.status().get('state'))

    @property
    def current(self):
        return self.currentsong()

    @property
    def queue(self):
        plst = self.playlist
        plst.reverse()
        return [trk for trk in plst if int(trk.pos) > int(self.current.pos)]

    @property
    def playlist(self):
        """
        Override deprecated MPD playlist command
        """
        return self.playlistinfo()

    def connect(self):
        host, port, password = self._mpd
        self.disconnect()
        try:
            self._client.connect(host, port)

        # Catch socket errors
        except IOError as err:
            raise PlayerError('Could not connect to "%s:%s": %s' %
                              (host, port, err.strerror))

        # Catch all other possible errors
        # ConnectionError and ProtocolError are always fatal.  Others may not
        # be, but we don't know how to handle them here, so treat them as if
        # they are instead of ignoring them.
        except MPDError as err:
            raise PlayerError('Could not connect to "%s:%s": %s' %
                              (host, port, err))

        if password:
            try:
                self._client.password(password)
            except (MPDError, IOError) as err:
                raise PlayerError("Could not connect to '%s': %s", (host, err))
        # Controls we have sufficient rights
        needed_cmds = ['status', 'stats', 'add', 'find', \
                       'search', 'currentsong', 'ping']

        available_cmd = self._client.commands()
        for nddcmd in needed_cmds:
            if nddcmd not in available_cmd:
                self.disconnect()
                raise PlayerError('Could connect to "%s", '
                                  'but command "%s" not available' %
                                  (host, nddcmd))

        #  Controls use of MusicBrainzIdentifier
        if Artist.use_mbid:
            if 'MUSICBRAINZ_ARTISTID' not in self._client.tagtypes():
                self.log.warning('Use of MusicBrainzIdentifier is set but MPD is '
                                 'not providing related metadata')
                self.log.info(self._client.tagtypes())
                self.log.warning('Disabling MusicBrainzIdentifier')
                Artist.use_mbid = False
            else:
                self.log.trace('Available metadata: %s', self._client.tagtypes())  # pylint: disable=no-member
        else:
            self.log.warning('Use of MusicBrainzIdentifier disabled!')
            self.log.info('Consider using MusicBrainzIdentifier for your music library')
        self._flush_cache()

    def disconnect(self):
        # Try to tell MPD we're closing the connection first
        try:
            self._client.noidle()
            self._client.close()
        # If that fails, don't worry, just ignore it and disconnect
        except (MPDError, IOError):
            pass
        try:
            self._client.disconnect()
        # Disconnecting failed, so use a new client object instead
        # This should never happen.  If it does, something is seriously broken,
        # and the client object shouldn't be trusted to be re-used.
        except (MPDError, IOError):
            self._client = MPDClient()
Exemple #17
0
class KissMPD():
    def handle_idle(func):
        def inner(self, *args, **kwargs):
            self.__lock.acquire()
            self.__client.noidle()
            res = func(self, *args, **kwargs)
            self.__client.send_idle()
            self.__lock.release()
            return res
        return inner

    def __init__(self, fp):
        self.__fp = fp
        self.__client = MPDClient()
        self.__lock = threading.Lock()
        self.__idle_client = MPDClient()

    def connect(self):
        self.__client.connect('localhost', 6600)
        self.__idle_client.connect('localhost', 6600)
        status = self.__client.status()
        self.__state = status['state']
        self.__volume = int(status['volume'])
        try:
            self.__songid = status['songid']
        except:
            self.__songid = None
        self.__client.send_idle()
        self.__idle_client.send_idle()

    def disconnect(self):
        self.__client.disconnect()
        self.__idle_client.disconnect()

    def process(self):
        canRead = select([self.__idle_client], [], [], 0)[0]
        if canRead:
            changes = self.__idle_client.fetch_idle()
            self.__idle_client.send_idle() # continue idling
            change = self.update_status()
            return change
        return None

    @handle_idle
    def refresh(self):
        self.display_current_song()

    def display_current_song(self):
        if(self.__songid):
            song = self.__client.currentsong()
            try:
                text = song['artist'] + ' - ' + song['title']
            except:
                text = song['file'].split('/')[-1]

            self.__fp.set_scrolling_text(3, 1, text)
            try:
                time = divmod(int(song['time']), 60)
                self.__fp.set_track_clock('0{0[0]:02}{0[1]:02}'.format(time))
            except:
                self.__fp.set_track_clock(None)
        else:
            self.__fp.clear()

    def display_volume(self):
        self.__fp.set_flash_text(8, 'Volume: ' + str(self.__volume))

    def display_state(self):
        if(self.__state != 'play'):
            self.__fp.clear()
            self.__fp.set_text('{0:^12}'.format(self.__state))
        else:
            self.display_current_song()

    @handle_idle
    def update_status(self):
        status = self.__client.status()

        try:
            songid = status['songid']
        except:
            songid = None

        if(songid != self.__songid):
            self.__songid = songid
            self.display_current_song()

        if(int(status['volume']) != self.__volume):
            self.__volume = int(status['volume'])
            self.display_volume()

        state = status['state']
        if(state != self.__state):
            self.__state = state
            self.display_state()
            return state

        return None

    @handle_idle
    def volume_down(self):
        self.__volume = self.__volume - 1
        if(self.__volume < 0):
            self.__volume = 0
        self.__client.setvol(self.__volume)
        self.display_volume()

    @handle_idle
    def volume_up(self):
        self.__volume = self.__volume + 1
        if(self.__volume > 100):
            self.__volume = 100
        self.__client.setvol(self.__volume)
        self.display_volume()

    @handle_idle
    def play(self, toggle=False):
        if(self.__state == 'play'):
            if toggle:
                self.__client.pause()
        else:
            self.__client.play()

    def play_pause(self):
        self.play(True)

    @handle_idle
    def pause(self):
        self.__client.pause(1)

    @handle_idle
    def previous(self):
        self.__client.previous()

    @handle_idle
    def next(self):
        self.__client.next()

    @handle_idle
    def stop(self):
        self.__client.stop()

    def handle_inputevent(self, ie):
        key2function = {
            'volume_down'    : self.volume_down,
            'volume_up'      : self.volume_up,
            'stop'           : self.stop,
            'play'           : self.play_pause,
            'next_track'     : self.next,
            'previous_track' : self.previous,
            'right'          : self.next,
            'left'           : self.previous,
            'down'           : self.volume_down,
            'up'             : self.volume_up,
            'ok'             : self.play_pause,
            'mute'           : self.play_pause,
        }
        try:
            function = key2function[ie.key]
        except:
            function = None
        if not function:
            return False

        if(ie.type == InputEventType.hold):
            if(function == self.volume_down) or (function == self.volume_up):
                function()
        elif(ie.type == InputEventType.pressed):
            function()
        return True
Exemple #18
0
 def __init__(self, fp):
     self.__fp = fp
     self.__client = MPDClient()
     self.__lock = threading.Lock()
     self.__idle_client = MPDClient()
Exemple #19
0
 def __init__(self):
     self.client = MPDClient()
     self.port = 6600
     self._connect()
Exemple #20
0
class MPDConnection(object):
    def __init__(self):
        self.client = MPDClient()
        self.port = 6600
        self._connect()

    def _connect(self):
        self.client.connect("localhost", self.port)

    def _is_connected(self):
        try:
            self.client.ping()
            return True
        except ConnectionError:
            return False

    def _ensure_connected(self):
        if self._is_connected() is True:
            return True
        self._connect()
        return True

    def get_tracks_on_playlist(self):
        self._ensure_connected()
        return self.client.playlist()

    def add_to_playlist(self, to_add):
        if isinstance(to_add, str):
            to_add = [to_add]
        for eachone in to_add:
            self.client.add(eachone)

    def ensure_playing(self):
        self._ensure_connected()
        if self.client.status()["state"] != "play":
            self.client.play()
        self.client.repeat(1)

    def __getattr__(self, attrname):
        return getattr(self.client, attrname)