Example #1
0
    def get_items(self, uri):
        '''Get the items in a playlist specified by uri.

        Returns a list of Ref objects referring to the playlist’s items.

        If a playlist with the given uri doesn’t exist, it returns None.


          Return type:	list of mopidy.models.Ref, or None

        '''
        logger.debug('Playlist: get_items %r', uri)
        _rx = re.compile(r'plex:playlist:(?P<plid>\d+)').match(uri)
        if _rx is None:
            return None

        def wrap_ref(item):
            return Ref.track(uri='plex:track:{}'.format(item.ratingKey),
                             name=item.title)

        return [
            wrap_ref(item)
            for item in self.plex.fetchItems('/playlists/{}/items'.format(
                _rx.group('plid')))
        ]
Example #2
0
    def translate_uri(self, uri):
        '''Convert custom URI scheme to real playable URI.

        MAY be reimplemented by subclass.

        This is very likely the only thing you need to override as a backend
        author. Typically this is where you convert any Mopidy specific URI to a real
        URI and then return it. If you can’t convert the URI just return None.

        Parameters: uri (string) – the URI to translate
        Return type:    string or None if the URI could not be translated'''

        logger.debug("Playback.translate_uri Plex with uri '%s'", uri)

        _rx = re.compile(r'plex:track:(?P<track_id>\d+)').match(uri)
        if _rx is None: # uri unknown
            logger.info('Unkown uri: %s', uri)
            return None
        elem = plexutils.findKey(self.backend.plex, _rx.group('track_id'))
        logger.info('getting file parts for eleme %r', elem)
        try:
            p = list(elem.iterParts())[0].key # hackisly get direct url of first part
            return '%s%s?X-Plex-Token=%s' % (elem.server.baseurl, p, self.backend.plex.token)
        except Exception as e:
            logger.exception(e)
            logger.info('fallback to returning stream for elem %r', elem)
            return elem.getStreamUrl()
Example #3
0
    def lookup(self, uri):
        '''Lookup playlist with given URI in both the set of playlists and in any other playlist source.

        Returns the playlists or None if not found.


          Parameters:	uri (string) – playlist URI
          Return type:	mopidy.models.Playlist or None

        '''
        logger.debug('Playlist: lookup %r', uri)
        _rx = re.compile(r'plex:playlist:(?P<plid>\d+)').match(uri)
        if _rx is None:
            return None
        plexlist = self.plex.fetchItems('/playlists/{:s}'.format(
            _rx.group('plid')))[0]
        PL = Playlist(
            uri=uri,
            name=plexlist.title,
            tracks=[
                wrap_track(_t, self.backend.plex_uri)
                for _t in plexlist.items()
            ],
            last_modified=None,  # TODO: find this value
        )
        return PL
Example #4
0
    def as_list(self):
        '''Get a list of the currently available playlists.

        Returns a list of `mopidy.models.Ref` objects referring to the playlists.
        In other words, no information about the playlists’ content is given.'''
        logger.debug('Playlist: as_list')
        audiolists = [l for l in self.plex.playlists() if l.playlistType == 'audio']
        return [Ref(uri='plex:playlist:{}'.format(playlist.ratingKey), 
                    name=playlist.title)
                for playlist in audiolists]
Example #5
0
    def save(self, playlist):
        '''Save the given playlist.

        The playlist must have an uri attribute set. To create a new playlist with an URI, use create().

        Returns the saved playlist or None on failure.

          Parameters:	playlist (mopidy.models.Playlist) – the playlist to save
          Return type:	mopidy.models.Playlist or None
        '''
        logger.debug('Playlist: save %r', playlist)
Example #6
0
 def __init__(self, config, audio):
     super(PlexBackend, self).__init__(audio=audio)
     self.config = config
     self.session = get_requests_session(proxy_config=config['proxy'],
                                         user_agent='%s/%s' % (mopidy_plex.Extension.dist_name,
                                                               mopidy_plex.__version__)
                                        )
     self.account = MyPlexAccount.signin(config['plex']['username'], config['plex']['password'])
     self.plex = self.account.resource(config['plex']['server']).connect()
     self.music = [s for s in self.plex.library.sections() if s.TYPE == MusicSection.TYPE][0]
     logger.debug('Found music section on plex server %s: %s', self.plex, self.music)
     self.uri_schemes = ['plex', ]
     self.library = PlexLibraryProvider(backend=self)
     self.playback = PlexPlaybackProvider(audio=audio, backend=self)
     self.playlists = PlexPlaylistsProvider(backend=self)
Example #7
0
    def search(self, query=None, uris=None, exact=False):
        '''Search the library for tracks where field contains values.

        Parameters:
        query (dict) – one or more queries to search for - the dict's keys being:
              {
                  'any': *, # this is what we get without explicit modifiers
                  'albumartist': *,
                  'date': *,
                  'track_name': *,
                  'track_number': *,
              }


        uris (list of string or None) – zero or more URI roots to limit the search to
        exact (bool) – if the search should use exact matching

        Returns mopidy.models.SearchResult, which has these properties
            uri (string) – search result URI
            tracks (list of Track elements) – matching tracks
            artists (list of Artist elements) – matching artists
            albums (list of Album elements) – matching albums
        '''

        logger.debug("Searching Plex for track '%s'", query)
        if query is None:
            logger.debug('Ignored search without query')
            return SearchResult(uri='plex:search')

        if 'uri' in query and False:  # TODO add uri limiting
            pass
        else:
            search_query = ' '.join(query.values()[0])

        search_uri = 'plex:search:%s' % urllib.quote(
            search_query.encode('utf-8'))
        logger.debug("Searching Plex with query '%s'", search_query)

        artists = []
        tracks = []
        albums = []
        for hit in self.plex.search(search_query):
            if isinstance(hit, plexaudio.Artist):
                artists.append(wrap_artist(hit, self.backend.plex_uri))
            elif isinstance(hit, plexaudio.Track):
                tracks.append(wrap_track(hit, self.backend.plex_uri))
            elif isinstance(hit, plexaudio.Album):
                albums.append(
                    wrap_album(hit, self.backend.plex_uri,
                               self.backend.resolve_uri))

        logger.debug("Got results: %s, %s, %s", artists, tracks, albums)

        return SearchResult(uri=search_uri,
                            tracks=tracks,
                            artists=artists,
                            albums=albums)
Example #8
0
    def get_items(self, uri):
        '''Get the items in a playlist specified by uri.

        Returns a list of Ref objects referring to the playlist’s items.

        If a playlist with the given uri doesn’t exist, it returns None.


          Return type:	list of mopidy.models.Ref, or None

        '''
        logger.debug('Playlist: get_items %r', uri)
        _rx = re.compile(r'plex:playlist:(?P<plid>\d+)').match(uri)
        if _rx is None:
            return None

        def wrap_ref(item):
            return Ref.track(uri='plex:track:{}'.format(item.ratingKey), name=item.title)

        return [wrap_ref(item) for item in
                listItems(self.plex, '/playlists/{}/items'.format(_rx.group('plid')))]
Example #9
0
    def lookup(self, uri):
        '''Lookup playlist with given URI in both the set of playlists and in any other playlist source.

        Returns the playlists or None if not found.


          Parameters:	uri (string) – playlist URI
          Return type:	mopidy.models.Playlist or None

        '''
        logger.debug('Playlist: lookup %r', uri)
        _rx = re.compile(r'plex:playlist:(?P<plid>\d+)').match(uri)
        if _rx is None:
            return None
        plexlist = listItems(self.plex, '/playlists/{:s}'.format(_rx.group('plid')))[0]
        PL = Playlist(uri=uri,
                      name=plexlist.title,
                      tracks=[wrap_track(_t, self.backend.plex_uri) for _t in plexlist.items()],
                      last_modified=None, # TODO: find this value
                     )
        return PL
Example #10
0
    def search(self, query=None, uris=None, exact=False):
        '''Search the library for tracks where field contains values.

        Parameters:
        query (dict) – one or more queries to search for - the dict's keys being:
              {
                  'any': *, # this is what we get without explicit modifiers
                  'albumartist': *,
                  'date': *,
                  'track_name': *,
                  'track_number': *,
              }


        uris (list of string or None) – zero or more URI roots to limit the search to
        exact (bool) – if the search should use exact matching

        Returns mopidy.models.SearchResult, which has these properties
            uri (string) – search result URI
            tracks (list of Track elements) – matching tracks
            artists (list of Artist elements) – matching artists
            albums (list of Album elements) – matching albums
        '''

        logger.info("Searching Plex for track '%s'", query)
        if query is None:
            logger.debug('Ignored search without query')
            return SearchResult(uri='plex:search')


        if 'uri' in query and False: # TODO add uri limiting
            pass
        else:
            search_query = ' '.join(query.values()[0])

        search_uri = 'plex:search:%s' % urllib.quote(search_query.encode('utf-8'))
        logger.info("Searching Plex with query '%s'", search_query)

        artists = []
        tracks = []
        albums = []
        for hit in self.plex.searchAudio(search_query):
            logger.debug('Got plex hit from query "%s": %s', search_query, hit)
            if isinstance(hit, plexaudio.Artist):
                artists.append(wrap_artist(hit, self.backend.plex_uri))
            elif isinstance(hit, plexaudio.Track):
                tracks.append(wrap_track(hit, self.backend.plex_uri))
            elif isinstance(hit, plexaudio.Album):
                albums.append(wrap_album(hit, self.backend.plex_uri, self.backend.resolve_uri))


        logger.debug("Got results: %s, %s, %s", artists, tracks, albums)

        return SearchResult(
            uri=search_uri,
            tracks=tracks,
            artists=artists,
            albums=albums
        )
Example #11
0
 def __init__(self, config, audio):
     super(PlexBackend, self).__init__(audio=audio)
     self.config = config
     self.session = get_requests_session(
         proxy_config=config['proxy'],
         user_agent='%s/%s' %
         (mopidy_plex.Extension.dist_name, mopidy_plex.__version__))
     self.account = MyPlexAccount.signin(config['plex']['username'],
                                         config['plex']['password'])
     self.plex = self.account.resource(config['plex']['server']).connect()
     self.music = [
         s for s in self.plex.library.sections()
         if s.TYPE == MusicSection.TYPE
     ][0]
     logger.debug('Found music section on plex server %s: %s', self.plex,
                  self.music)
     self.uri_schemes = [
         'plex',
     ]
     self.library = PlexLibraryProvider(backend=self)
     self.playback = PlexPlaybackProvider(audio=audio, backend=self)
     self.playlists = PlexPlaylistsProvider(backend=self)
Example #12
0
 def __init__(self, config, audio):
     super(PlexBackend, self).__init__(audio=audio)
     self.config = config
     self.session = get_requests_session(
         proxy_config=config['proxy'],
         user_agent='%s/%s' %
         (mopidy_plex.Extension.dist_name, mopidy_plex.__version__))
     baseurl = (config['plex']['server'])
     token = (config['plex']['token'])
     self.plex = PlexServer(baseurl, token)
     self.music = [
         s for s in self.plex.library.sections()
         if s.TYPE == MusicSection.TYPE
     ][0]
     logger.debug('Found music section on plex server %s: %s', self.plex,
                  self.music)
     self.library_id = config['plex']['library_id']
     self.uri_schemes = [
         'plex',
     ]
     self.library = PlexLibraryProvider(backend=self)
     self.playback = PlexPlaybackProvider(audio=audio, backend=self)
Example #13
0
    def __init__(self, config, audio):
        super(PlexBackend, self).__init__(audio=audio)
        self.config = config
        self.session = get_requests_session(
            proxy_config=config['proxy'],
            user_agent='%s/%s' %
            (mopidy_plex.Extension.dist_name, mopidy_plex.__version__))
        type = config['plex']['type']
        library = (config['plex']['library'])
        self.plex = None
        self.music = None
        if type == 'myplex':
            server = (config['plex']['server'])
            user = (config['plex']['username'])
            password = (config['plex']['password'])
            account = self.myplex_login(user, password)
            logger.info('Connecting to plex server: %s', server)
            self.plex = account.resource(server).connect(ssl=False)
            self.music = self.plex.library.section(library)
        elif type == 'direct':
            baseurl = (config['plex']['server'])
            token = (config['plex']['token'])
            self.plex = PlexServer(baseurl, token)
            self.music = self.plex.library.section(library)
        else:
            logger.error('Invalid value for plex backend type: %s', type)

        logger.info('Connected to plex server')
        logger.debug('Found music section on plex server %s: %s', self.plex,
                     self.music)
        self.library_id = self.music.key
        self.uri_schemes = [
            'plex',
        ]
        self.library = PlexLibraryProvider(backend=self)
        self.playback = PlexPlaybackProvider(audio=audio, backend=self)
        self.playlists = PlexPlaylistsProvider(backend=self)
Example #14
0
    def create(self, name):
        '''Create a new empty playlist with the given name.

        Returns a new playlist with the given name and an URI.'''
        logger.debug('Playlist: create %r', name)
Example #15
0
    def browse(self, uri):
        logger.debug('browse: %s', str(uri))
        if not uri:
            return []
        if uri == self.root_directory.uri:
            return self._root
        parts = uri.split(':')

        sections = self.plex.library.sections()
        artists = [sec for sec in sections if sec.type == 'artist']
        # albums
        if uri == 'plex:album':
            logger.debug('self._browse_albums()')
            albums = list()
            for a in artists:
                try:
                    albums += a.albums()
                except Exception as e:
                    logger.warning(
                        'Failed to process albums for {}: {}'.format(a, e))
            # logger.info('Albums: {}'.format([a.title for a in albums]))
            logger.debug('{} albums found'.format(len(albums)))
            return [self._item_ref(item, 'album') for item in albums]

        # a single album
        # uri == 'plex:album:album_id'
        if len(parts) == 3 and parts[1] == 'album':
            logger.debug('self._browse_album(uri)')
            album_id = parts[2]
            key = '/library/metadata/{}/children'.format(album_id)
            return [
                self._item_ref(item, 'track')
                for item in self.plex.fetchItems(key)
            ]

        # artists
        if uri == 'plex:artist':
            logger.debug('self._browse_artists()')
            return [self._item_ref(item, 'artist') for item in artists]

        # a single artist
        # uri == 'plex:artist:artist_id'
        if len(parts) == 3 and parts[1] == 'artist':
            logger.debug('self._browse_artist(uri)')
            artist_id = parts[2]
            # get albums and tracks
            ret = []
            for item in plexutils.listItems(
                    self.plex,
                    '/library/metadata/{}/children'.format(artist_id)):
                ret.append(self._item_ref(item, 'album'))
            for item in plexutils.listItems(
                    self.plex,
                    '/library/metadata/{}/allLeaves'.format(artist_id)):
                ret.append(self._item_ref(item, 'track'))
            return ret

        # all tracks of a single artist
        # uri == 'plex:artist:artist_id:all'
        if len(parts) == 4 and parts[1] == 'artist' and parts[3] == 'all':
            logger.debug('self._browse_artist_all_tracks(uri)')
            artist_id = parts[2]
            return [
                self._item_ref(item, 'track') for item in plexutils.listItems(
                    self.plex, '/library/metadata/{}/allLeaves'.format(
                        artist_id))
            ]

        logger.debug('Unknown uri for browse request: %s', uri)

        return []
Example #16
0
 def delete(self, uri):
     '''Delete playlist identified by the URI.'''
     logger.debug('Playlist: delete %r', uri)
Example #17
0
    def browse(self, uri):
        logger.debug('browse: %s', str(uri))
        if not uri:
            return []
        if uri == self.root_directory.uri:
            return self._root
        parts = uri.split(':')

        # albums
        if uri == 'plex:album':
            logger.debug('self._browse_albums()')
            return [self._item_ref(item, 'album') for item in
                    plexutils.listItems(self.plex, '/library/sections/4/albums')]

        # a single album
        # uri == 'plex:album:album_id'
        if len(parts) == 3 and parts[1] == 'album':
            logger.debug('self._browse_album(uri)')
            album_id = parts[2]
            return [self._item_ref(item, 'track') for item in
                    plexutils.listItems(self.plex,
                                         '/library/metadata/{}/children'.format(album_id))]

        # artists
        if uri == 'plex:artist':
            logger.debug('self._browse_artists()')
            return [self._item_ref(item, 'artist') for item in
                    plexutils.listItems(self.plex, '/library/sections/4/all')]

        # a single artist
        # uri == 'plex:artist:artist_id'
        if len(parts) == 3 and parts[1] == 'artist':
            logger.debug('self._browse_artist(uri)')
            artist_id = parts[2]
            # get albums and tracks
            ret = []
            for item in plexutils.listItems(self.plex,
                                             '/library/metadata/{}/children'.format(artist_id)):
                ret.append(self._item_ref(item, 'album'))
            for item in plexutils.listItems(self.plex,
                                             '/library/metadata/{}/allLeaves'.format(artist_id)):
                ret.append(self._item_ref(item, 'track'))
            return ret

        # all tracks of a single artist
        # uri == 'plex:artist:artist_id:all'
        if len(parts) == 4 and parts[1] == 'artist' and parts[3] == 'all':
            logger.debug('self._browse_artist_all_tracks(uri)')
            artist_id = parts[2]
            return [self._item_ref(item, 'track') for item in
                    plexutils.listItems(self.plex, '/library/metadata/{}/allLeaves'.format(artist_id))]

        logger.debug('Unknown uri for browse request: %s', uri)

        return []
Example #18
0
 def refresh(self):
     '''Refresh the playlists in playlists.'''
     logger.debug('Refresh')