Giter Club home page Giter Club logo

mopidy-pandora's Introduction

Mopidy-Pandora

Latest PyPI version

Test coverage

Mopidy extension for playing music from Pandora.

Maintainer wanted

I no longer have access to the Pandora music service in the region that I live, which has made maintaining this project impossible. Mopidy-Pandora is looking for a new maintainer, preferably someone who is familiar with the codebase, familiar with Python development, and uses the paid Pandora subscription service on a regular basis.

If you're interested, please take a look at the code base and work on submitting a pull request or two to show you understand how everything works together.

Features

  • Support for both Pandora Premium and ad-supported free accounts.
  • Add ratings to tracks (thumbs up, thumbs down, sleep, etc.).
  • Bookmark songs or artists.
  • Browse and add genre stations.
  • Search for song, artist, and genre stations.
  • Play QuickMix stations.
  • Sort stations alphabetically or by date added.
  • Delete stations from the user's Pandora profile.
  • Scrobbling to last.fm using the Mopidy scrobbler.

Usage

Ideally, Mopidy needs dynamic playlists and core extensions to properly support Pandora. In the meantime, Mopidy-Pandora comes bundled with a frontend extension that automatically adds more tracks to the tracklist as needed. Mopidy-Pandora will ensure that there are always just two tracks in the tracklist: the currently playing track and the track that is up next. It is not possible to mix Pandora and non-Pandora tracks for playback at the same time, so any non-Pandora tracks will be removed from the tracklist when playback starts.

Pandora expects users to interact with tracks at the point in time and in the sequence that it serves them up. For this reason, trying to save tracks to playlists or messing with the Mopidy-Pandora generated tracklist is probably not a good idea. And not recommended.

Dependencies

  • Requires a Pandora user account. Users with a Pandora Premium subscription will have access to the higher quality 192 Kbps audio stream. Free accounts will play advertisements.
  • pydora >= 2,<3. The Python Pandora API Client. Pre-requisites: As of 1.11.0 pydora requires cryptography. Depending on your setup, there may be some native dependencies on openssl that you will need to install beforehand. See the cryptography installation docs for details.
  • cachetools >= 1.0.0. Extensible memoizing collections and decorators. The package is available as cachetools on PyPI.
  • Mopidy >= 3.0.0. The music server that Mopidy-Pandora extends.
  • requests >= 2.5.0. Python HTTP Requests for Humansβ„’.

Installation

Install by running:

pip install Mopidy-Pandora

Configuration

Before starting Mopidy, you must add your Pandora username and password to your Mopidy configuration file. The minimum configuration also requires that you provide the details of the JSON API endpoint that you would like to use:

[pandora]
enabled = true
api_host = tuner.pandora.com/services/json/
partner_encryption_key =
partner_decryption_key =
partner_username = android
partner_password =
partner_device = android-generic
username =
password =

The following configuration values are available:

  • pandora/enabled: If the Pandora extension should be enabled or not. Defaults to true.
  • pandora/api_host: Which of the JSON API endpoints to use. Note that the endpoints are different for Pandora Premium and free accounts (details in the link provided).
  • pandora/partner_* related values: The credentials to use for the Pandora API entry point. You must provide these values based on your device preferences.
  • pandora/username: Your Pandora username. You must provide this.
  • pandora/password: Your Pandora password. You must provide this.
  • pandora/preferred_audio_quality: can be one of lowQuality, mediumQuality, or highQuality (default). If the preferred audio quality is not available for the partner device specified, then the next-lowest bitrate stream that Pandora supports for the chosen device will be used. Note that this setting has no effect for partner device types that only provide one audio stream (notably credentials associated with iOS). In such instances, Mopidy-Pandora will always revert to the default stream provided by the Pandora server.
  • pandora/sort_order: defaults to a-z. Use date to display the list of stations in the order that the stations were added.
  • pandora/auto_setup: Specifies if Mopidy-Pandora should automatically configure the Mopidy player for best compatibility with the Pandora radio stream. Defaults to true and turns consume on and repeat, random, and single modes off.
  • pandora/cache_time_to_live: specifies the length of time (in seconds) that station and genre lists should be cached for between automatic refreshes. Using a local cache greatly speeds up browsing the library. It should not be necessary to fiddle with this unless the Mopidy frontend that you are using does not support manually refreshing the library, and you want Mopidy-Pandora to immediately detect changes to your Pandora user profile that are made in other Pandora players. Setting this to 0 will disable caching completely and ensure that the latest lists are always retrieved directly from the Pandora server. Defaults to 86400 (i.e. 24 hours).

It is also possible to apply Pandora ratings and perform other actions on the currently playing track using the standard pause/play/previous/next buttons.

  • pandora/event_support_enabled: setting this to true will enable the event triggers. Event support is disabled by default as this is still an experimental feature, and not something that is provided for in the Mopidy API. It works, but it is not impossible that the wrong events may be triggered for tracks or (in the worst case scenario) that one of your stations may be deleted accidentally. Mileage may vary - use at your own risk.
  • pandora/double_click_interval: successive button clicks that occur within this interval will trigger an event. Defaults to 2.50 seconds.
  • pandora/on_pause_resume_click: click pause and then play while a song is playing to trigger the event. Defaults to thumbs_up.
  • pandora/on_pause_next_click: click pause and then next in quick succession. Calls event and skips to next song. Defaults to thumbs_down.
  • pandora/on_pause_previous_click: click pause and then previous in quick succession. Calls event and restarts the current song. Defaults to sleep.
  • pandora/on_pause_resume_pause_click: click pause, resume, and pause again in quick succession (i.e. triple click). Calls event. Defaults to delete_station.

The full list of supported events are: thumbs_up, thumbs_down, sleep, add_artist_bookmark, add_song_bookmark, and delete_station.

Project resources

Credits

mopidy-pandora's People

Contributors

abates avatar jcass77 avatar jodal avatar rectalogic avatar ron4mac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mopidy-pandora's Issues

Mopidy-pandora stops working after long periods of inactivity

I sometimes leave Mopidy running for days on end on a Pi Musicbox. I've found that if I press pause after listening, and then try to resume playback or select different Pandora stations to listen to a few hours later, mopidy-pandora fails silently.

  • If I push play to resume the current track, the following output appears in the debug log file:

ERROR 2015-05-30 14:47:00,638 [5508:MainThread] mopidy.audio.gst Could not open resource for reading.

  • If I navigate to Browse -> Pandora -> Stations, then the 'Loading data from...' spinning wheel appears, but nothing is loaded and the station list is not displayed.

I suspect that the above is due to the Pandora session expiring at some point, and that we need to find a way to check that it is still active and re-initialise if necessary?

Tracks play for only a few seconds before pausing

I'm troubleshooting an issue where a Pandora track will start playing immediately, but only for about 2 seconds before it playback pauses. Usually it will continue after a long wait. My hunch is that it's a stream buffering issue.

Here's a Mopidy Discuss post about the issue with more information.

No audio output, GStreamer errors (solved)

I'm having essentially the same issue as #50 though re-installing Mopidy from master did not work.

I can browse tracks on Pandora, and when I select one I do get the album artwork showing up under Now Playing. But there's no audio.

Here's my mopidy.log, showing that it looks like it can't decode the stream:

2016-09-09 22:37:33,865 - INFO     Starting new HTTPS connection (1): tuner.pandora.com
2016-09-09 22:37:34,266 - INFO     Starting Mopidy core
2016-09-09 22:37:34,321 - INFO     Starting Mopidy frontends: PandoraFrontend, 
, MpdFrontend, HttpFrontend
2016-09-09 22:37:58,286 - INFO     Starting new HTTP connection (1): tuner.pandora.com
2016-09-09 22:38:07,744 - INFO     Starting new HTTP connection (1): audio-sv5-t1-1-v4v6.pandora.com
2016-09-09 22:38:09,867 - INFO     Resetting dropped connection: audio-sv5-t1-1-v4v6.pandora.com
2016-09-09 22:38:10,401 - INFO     Resetting dropped connection: audio-sv5-t1-1-v4v6.pandora.com
2016-09-09 22:38:10,704 - WARNING  Could not find a MPEG-4 AAC decoder to handle media.
2016-09-09 22:38:10,707 - WARNING  GStreamer warning: gst-stream-error-quark: No decoder available for type 'audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, level=(string)1, base-profile=(string)lc, profile=(string)lc, codec_data=(buffer)139056e5a0, rate=(int)22050, channels=(int)2'. (6)
2016-09-09 22:38:10,710 - ERROR    GStreamer error: gst-core-error-quark: Your GStreamer installation is missing a plug-in. (12)

Aha. I solved this while filing the bug, so I'll just submit and close, and hopefully someone will find this useful in the future.)

It turns out that there are two similarly-numbered versions of GStreamer that can be installed independently, 1.0 and 0.10. You can see which ones you have installed with:

# dpkg --get-selections | grep -v deinstall | grep gst
...
gstreamer0.10-plugins-bad:armhf         install
gstreamer0.10-plugins-base:armhf        install
gstreamer0.10-plugins-good:armhf        install
gstreamer0.10-plugins-ugly:armhf        install
gstreamer0.10-tools             install
gstreamer1.0-alsa:armhf             install
gstreamer1.0-plugins-base:armhf         install
gstreamer1.0-plugins-good:armhf         install
gstreamer1.0-plugins-ugly:armhf         install
...

In this case I had gstreamer0.10-plugins-bad but not gstreamer1.0-plugins-bad.

Add support for processing ad tokens

Mopidy-Pandora just skips over ads at the moment. This is not by design but due to the fact that advertisement tracks require special processing.

It would probably be a good idea to provide support for playing ads in order to align with the standard Pandora clients.

Skipping ads will probably also result in the user's Pandora account being disabled if done consistently.

I've started an implementation to support playing ads in a separate branch at https://github.com/jcass77/mopidy-pandora/tree/enhance/ad_support, but it requires some changes to the underlying pydora library before we can roll it out (mcrute/pydora#26)

Unplayable tracks are not removed from the tracklist

This actually has two root causes:

  1. if the first track is unplayable, then the tracklist may not have been set to consume mode yet so every subsequent unplayable track is not removed from the list. Need to find a way to ensure that 'consume' is enabled before playback starts.
  2. Mopidy uses tracklist ID's when consuming tracks in the tracklist. Because Mopidy-Pandora dynamically changes the tracklist on the fly, and core.PlaybackController.next() is called recursively, the tlid may actually have changed by the time it tries to remove the track. Need to find a way to delay tracklist updates until Mopidy has found a playable track to play.

event_support not completely working

Some of the events (pandora/on_pause_next_click and pandora/on_pause_previous_click) are not triggering. The associated tests pass but the events are never triggered when I'm actually using mopidy-pandora. This appears to be due to a slight difference in the sequence with which events are received between a test environment and production.

I'm working on a fix.

Cannot import name 'compat' from 'mopidy'

Installed Mopidy-Pandora and setup config, upon restart get the following:

Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/mopidy/main.py", line 129, in main
extension.setup(registry)
File "/usr/local/lib/python3.7/dist-packages/mopidy_pandora/init.py", line 88, in setup
from .backend import PandoraBackend
File "/usr/local/lib/python3.7/dist-packages/mopidy_pandora/backend.py", line 14, in
from mopidy_pandora.library import PandoraLibraryProvider
File "/usr/local/lib/python3.7/dist-packages/mopidy_pandora/library.py", line 15, in
from mopidy_pandora.uri import (
File "/usr/local/lib/python3.7/dist-packages/mopidy_pandora/uri.py", line 7, in
from mopidy import compat, models
ImportError: cannot import name 'compat' from 'mopidy' (/usr/lib/python3/dist-packages/mopidy/init.py)

Pandora station in Mopidy playlist

I'd like to use Mopidy-AlarmClock to play a Pandora station at a certain time of day. It only understands Mopidy playlists, so I'd need to define a playlist file that references the Pandora station to play.

Add support to rate tracks in Pandora (love / ban)

One of the major attractions of Pandora is its ability to learn what the listener's preferences are. I find that I miss not being able to refine this further using the thumbs up / down features when listening in Mopidy.

Although not strictly part of the Mopidy API, my question is whether it would be possible to enable these features in the back-end in case any web clients would like to expose this functionality in the UI.

skitched-20150309-171928

I will start working on a pull request if anybody is in support of the idea, and feels that this is worth investigating / pursuing.

Ads are not always registered properly

Pydora sometimes fails to register ads. Stack trace in the log:

DEBUG 2015-12-10 08:37:34,256 [30759:PandoraBackend-14] requests.packages.urllib3.connectionpool
"POST /services/json/?partner_id=42&auth_token=VIOOYNDHJ2MOZSW2QBeDbkfJwMfpazG7ab9kx4AktYYccgZMSdSPJWrQ%3D%3D&user_id=175482532&method=ad.registerAd HTTP/1.1" 200 65
DEBUG 2015-12-10 08:37:34,260 [30759:PandoraBackend-14] pykka
Exception returned from PandoraBackend (urn:uuid:3c22bf76-4511-4004-ade2-9614a100a033) to caller:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 201, in _actor_loop
response = self._handle_receive(message)
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 295, in _handle_receive
return callee(_message['args'], *_message['kwargs'])
File "/Users/jcass/PycharmProjects/Mopidy/mopidy-pandora/mopidy_pandora/playback.py", line 39, in prepare_change
self.backend.prepare_next_track(False)
File "/Users/jcass/PycharmProjects/Mopidy/mopidy-pandora/mopidy_pandora/backend.py", line 60, in prepare_next_track
next_track = self.library.get_next_pandora_track()
File "/Users/jcass/PycharmProjects/Mopidy/mopidy-pandora/mopidy_pandora/library.py", line 138, in get_next_pandora_track
pandora_track = self._station_iter.next()
File "/usr/local/lib/python2.7/site-packages/pydora/utils.py", line 121, in iterate_forever
yield next(output).prepare_playback()
File "/usr/local/lib/python2.7/site-packages/pandora/models/pandora.py", line 227, in prepare_playback
self.register_ad(self.station_id)
File "/usr/local/lib/python2.7/site-packages/pandora/models/pandora.py", line 224, in register_ad
self._api_client.register_ad(station_id, self.tracking_tokens)
File "/usr/local/lib/python2.7/site-packages/pandora/client.py", line 280, in register_ad
adTrackingTokens=tokens)
File "/usr/local/lib/python2.7/site-packages/pandora/client.py", line 104, in call
return self.transport(method, *_kwargs)
File "/usr/local/lib/python2.7/site-packages/pandora/transport.py", line 47, in function
return func(_args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/pandora/transport.py", line 234, in call
return self._parse_response(result)
File "/usr/local/lib/python2.7/site-packages/pandora/transport.py", line 220, in _parse_response
raise PandoraException.from_code(result["code"], result["message"])
ParameterMissing: Parameter Missing
INFO 2015-12-10 08:37:34,270 [30759:PandoraBackend-14] requests.packages.urllib3.connectionpool
Resetting dropped connection: audio-sv3-t1-2-v4v6.pandora.com

This should have been fixed by mcrute/pydora#34.

This error occurred while playing a station that was recently added from the Genres list, so it is possible that Mopidy-Pandora is not supplying the correct station_id.

Add support for browsing bookmarks

Mopidy-Pandora already supports bookmarking songs and artists using the user-configurable doubleclick events.

It should be fairly easy to add another node to the library folder structure that allows users to browse bookmarks and create stations for these on the fly, similar to how genre stations are handled currently.

Wrong double-click event triggered

The history update bug in Mopidy (mopidy/mopidy#1352) sometimes causes Mopidy-Pandora to trigger the wrong event for a track.

At the moment this issue is only present in the v0.2.0 release in the 'develop' branch and it is recommended to disable events by setting the configuration parameter event_support_enabled = false until it has been fixed.

Raise mopidy.exceptions.BackendError

According to the Mopidy docs, backends should raise mopidy.exceptions.BackendError on initialisation errors (e.g. when logging in to the Pandora server failed).

This will cause Mopidy to print the error message and exit, which might be less confusing than just not having the Mopidy-Pandora backend extension listed in the frontend if it did not initialise properly.

HTTP errors cause the Mopidy actor to die

HTTP connection and timeout errors raise exceptions which are not currently handled. This sometimes causes the Mopidy backend to die unexpectedly:

2015-06-26 03:39:56,619 - ERROR Unhandled exception in Core (urn:uuid:dc95f4be-887d-4bcf-a332-2d6cced5309f): Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 200, in _actor_loop response = self._handle_receive(message) File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 294, in _handle_receive return callee(*message['args'], **message['kwargs']) File "/var/lib/git/mopidy/mopidy/listener.py", line 49, in on_event getattr(self, event)(**kwargs) File "/var/lib/git/mopidy/mopidy/core/actor.py", line 87, in reached_end_of_stream self.playback._on_end_of_track() File "/var/lib/git/mopidy/mopidy/core/playback.py", line 217, in _on_end_of_track self._change_track(next_tl_track) File "/var/lib/git/mopidy/mopidy/core/playback.py", line 199, in _change_track self._play(on_error_step=on_error_step) File "/var/lib/git/mopidy/mopidy/core/playback.py", line 313, in _play backend.playback.change_track(tl_track.track).get() and File "/usr/local/lib/python2.7/dist-packages/pykka/future.py", line 299, in get exec('raise exc_info[0], exc_info[1], exc_info[2]') File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 200, in _actor_loop response = self._handle_receive(message) File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 294, in _handle_receive return callee(*message['args'], **message['kwargs']) File "/var/lib/git/mopidy-pandora/mopidy_pandora/actor.py", line 60, in change_track pandora_track = self._next_track(track_uri.station_token) File "/var/lib/git/mopidy-pandora/mopidy_pandora/actor.py", line 50, in _next_track self.tracks = self.backend.api.get_playlist(station_token) File "/var/lib/git/mopidy-pandora/mopidy_pandora/pydora.py", line 10, in with_authentication return f(self, *args, **kwargs) File "/var/lib/git/mopidy-pandora/mopidy_pandora/pydora.py", line 66, in get_playlist for station in self.api.get_playlist(station_token)['items']) File "/var/lib/git/pydora/pandora/__init__.py", line 308, in get_playlist includeTrackLength=True) File "/var/lib/git/pydora/pandora/__init__.py", line 172, in __call__ result = self._make_http_request(url, data) File "/var/lib/git/pydora/pandora/__init__.py", line 130, in _make_http_request return urlopen(req) File "/usr/lib/python2.7/urllib2.py", line 127, in urlopen return _opener.open(url, data, timeout) File "/usr/lib/python2.7/urllib2.py", line 401, in open response = self._open(req, data) File "/usr/lib/python2.7/urllib2.py", line 419, in _open '_open', req) File "/usr/lib/python2.7/urllib2.py", line 379, in _call_chain result = func(*args) File "/usr/lib/python2.7/urllib2.py", line 1219, in https_open return self.do_open(httplib.HTTPSConnection, req) File "/usr/lib/python2.7/urllib2.py", line 1181, in do_open raise URLError(err) URLError: <urlopen error [Errno 110] Connection timed out> 2015-06-26 03:39:56,724 - WARNING Tried to communicate with dead actor. 2015-06-26 03:39:56,729 - WARNING Tried to communicate with dead actor. 2015-06-26 03:39:56,733 - WARNING Tried to communicate with dead actor. 2015-06-26 03:39:56,737 - WARNING Tried to communicate with dead actor. 2015-06-26 03:39:56,740 - WARNING Tried to communicate with dead actor.

Handling of login errors needs to be improved

The backend extension fails silently on login errors when Mopidy starts up. Apart from the stack traces that are logged, the only indication to the user that something is wrong will be that an empty list is returned when they try to browse their stations.

The log contains:

2016-01-29 20:18:22,082 - INFO     TRANSPORT: 
METHOD: auth.partnerLogin
PARAMS: {'user_id': None, 'auth_token': None, 'partner_id': None, 'method': 'auth.partnerLogin'}
DATA: {'username': u'android', 'userAuthToken': None, 'deviceModel': u'android-generic', 'syncTime': None, 'version': '5', 'password': u'AC7IBG09A3DTSYM4R41UJWL07VLN8JI7'}
URL: https://tuner.pandora.com/services/json/
2016-01-29 20:18:22,099 - INFO     Starting new HTTPS connection (9): tuner.pandora.com
2016-01-29 20:18:22,115 - WARNING  Retrying (Retry(total=2, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x381ff90>: Failed to establish a new connection: [Errno -2] Name or service not known',)': /services/json/?method=auth.partnerLogin
2016-01-29 20:18:22,118 - INFO     Starting new HTTPS connection (10): tuner.pandora.com
2016-01-29 20:18:22,135 - WARNING  Retrying (Retry(total=1, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x382a170>: Failed to establish a new connection: [Errno -2] Name or service not known',)': /services/json/?method=auth.partnerLogin
2016-01-29 20:18:22,138 - INFO     Starting new HTTPS connection (11): tuner.pandora.com
2016-01-29 20:18:22,154 - WARNING  Retrying (Retry(total=0, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x382a210>: Failed to establish a new connection: [Errno -2] Name or service not known',)': /services/json/?method=auth.partnerLogin
2016-01-29 20:18:22,156 - INFO     Starting new HTTPS connection (12): tuner.pandora.com
2016-01-29 20:18:22,174 - ERROR    Error logging in to Pandora.
Traceback (most recent call last):
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/backend.py", line 50, in on_start
    self.api.login(self.config['username'], self.config['password'])
  File "/var/lib/git/pydora/pandora/client.py", line 71, in login
    return self._authenticate()
  File "/var/lib/git/pydora/pandora/client.py", line 74, in _authenticate
    self._partner_login()
  File "/var/lib/git/pydora/pandora/client.py", line 62, in _partner_login
    version=self.transport.API_VERSION)
  File "/var/lib/git/pydora/pandora/transport.py", line 50, in function
    return func(*args, **kwargs)
  File "/var/lib/git/pydora/pandora/transport.py", line 240, in __call__
    result = self._make_http_request(url, data, params)
  File "/var/lib/git/pydora/pandora/transport.py", line 185, in _make_http_request
    r = self._http.post(url, data=data, params=params)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 511, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 437, in send
    raise ConnectionError(e, request=request)
ConnectionError: HTTPSConnectionPool(host='tuner.pandora.com', port=443): Max retries exceeded with url: /services/json/?method=auth.partnerLogin (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x382a290>: Failed to establish a new connection: [Errno -2] Name or service not known',))

As a result of this, the parameters to APITransport.__call__() are not set correctly which cause subsequent calls to the Pandora server to fail as well:

TRANSPORT: 
METHOD: station.getGenreStations
PARAMS: {'user_id': None, 'auth_token': None, 'partner_id': None, 'method': 'station.getGenreStations'}
DATA: {'userAuthToken': None, 'syncTime': None}
URL: http://tuner.pandora.com/services/json/
2016-01-30 09:08:06,155 - INFO     Starting new HTTP connection (1): tuner.pandora.com
2016-01-30 09:08:06,159 - INFO     TRANSPORT: 
METHOD: user.getStationList
PARAMS: {'user_id': None, 'auth_token': None, 'partner_id': None, 'method': 'user.getStationList'}
DATA: {'userAuthToken': None, 'syncTime': None, 'includeStationArtUrl': True}
URL: http://tuner.pandora.com/services/json/
2016-01-30 09:08:06,180 - INFO     Starting new HTTP connection (2): tuner.pandora.com
2016-01-30 09:08:06,899 - INFO     TRANSPORT: 
RESULT: {"stat":"fail","message":"An unexpected error occurred","code":0}

2016-01-30 09:08:07,006 - INFO     TRANSPORT: 
RESULT: {"stat":"fail","message":"An unexpected error occurred","code":0}

2016-01-30 09:08:07,011 - ERROR    PandoraBackend backend caused an exception.
Traceback (most recent call last):
  File "/var/lib/git/mopidy/mopidy/core/library.py", line 19, in _backend_error_handling
    yield
  File "/var/lib/git/mopidy/mopidy/core/library.py", line 112, in _browse
    result = backend.library.browse(uri).get()
  File "/usr/local/lib/python2.7/dist-packages/pykka/threading.py", line 52, in get
    compat.reraise(*self._data['exc_info'])
  File "/usr/local/lib/python2.7/dist-packages/pykka/compat.py", line 12, in reraise
    exec('raise tp, value, tb')
  File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 201, in _actor_loop
    response = self._handle_receive(message)
  File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 295, in _handle_receive
    return callee(*message['args'], **message['kwargs'])
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/library.py", line 41, in browse
    return self._browse_stations()
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/library.py", line 140, in _browse_stations
    stations = self.backend.api.get_station_list()
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/client.py", line 57, in get_station_list
    station_list = super(MopidyAPIClient, self).get_station_list()
  File "/var/lib/git/pydora/pandora/client.py", line 125, in get_station_list
    includeStationArtUrl=True))
  File "/var/lib/git/pydora/pandora/client.py", line 107, in __call__
    return self.transport(method, **kwargs)
  File "/var/lib/git/pydora/pandora/transport.py", line 50, in function
    return func(*args, **kwargs)
  File "/var/lib/git/pydora/pandora/transport.py", line 243, in __call__
    return self._parse_response(result)
  File "/var/lib/git/pydora/pandora/transport.py", line 225, in _parse_response
    raise PandoraException.from_code(result["code"], result["message"])
InternalServerError: Internal Server Error

We probably need to make dealing with login errors more explicit.

Got un-handled exception from PandoraBackend

I receive the following error on a fresh Raspberry Pi install:
ERROR Got un-handled exception from PandoraBackend Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/mopidy/commands.py", line 237, in _actor_error_handling yield File "/usr/lib/python2.7/dist-packages/mopidy/commands.py", line 386, in start_backends config=config, audio=audio).proxy() File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 94, in start obj = cls(*args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/backend.py", line 41, in __init__ self.library = PandoraLibraryProvider(backend=self, sort_order=self.config.get('sort_order')) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/library.py", line 36, in __init__ self.pandora_station_cache = LRUCache(maxsize=5, missing=self.get_station_cache_item) TypeError: __init__() got an unexpected keyword argument 'missing'

Play a personal playlist with mopidy-pandora

Hi !
i have recently installed mopidy-pandora (debian10) and successfully; I can play the various radio stations by creating an m3u8 file in the format "pandora: station: token: token" and load the same file with the "mpc load" utility ....
I ask you now if it is possible to do the same but calling a url related to a personal playlist like "pandora: playlist: xxxx: yyyyy"
I have already made several attempts but it does not work.
Can you help me ?
Thank you

Add support for user to set preferred audio quality

Pandora provides more than one audio URL for certain devices (e.g. android-generic), which contain different bitrate encodings.

It should ideally be possible for the user to specify their preferred bitrate, especially in situations where Mopidy is used with high fidelity audio equipment. I've created a fork here to start implementing this functionality:

https://github.com/jcass77/mopidy-pandora.git

Please take a look at the code to see if this is something that you think could work? This code is dependent on the related pydora pull request: mcrute/pydora#2

Thanks for starting the mopidy-pandora plugin!

Is the installer ready for users?

I read the part about how you have to loop a single track playlist, am OK with that.
I tried installing via pip install Mopidy-Pandora but it eventually timed out. Do I need to add any special repositories, or pull directly from github somehow?

Can't get Pandora to play

Whenever I try to play a song through MusicBox, I get this error:

WARNING  Error changing Pandora track: Track(album=Album(name=u'(Company name not specified)'), artists=[Artist(name=u'(Title not specified)')], name=u'Advertisement', uri='pandora:ad:1033918586896730518:1033918586896730518-isa%3A1033918586896730518'), (Track with URI 'pandora:ad:1033918586896730518:1033918586896730518-isa%3A1033918586896730518' is not playable.)
WARNING  Track is not playable: pandora:ad:1033918586896730518:1033918586896730518-isa%3A1033918586896730518

** (<unknown>:2330): WARNING **: Invalid channel positions

** (<unknown>:2330): WARNING **: Invalid channel positions
ERROR    GStreamer error: gst-stream-error-quark: Internal data flow error. (1)

I set up everything in the config file, but I can't seem to get it to play anything. I'm running on the latest version of Mopidy and Mopidy-Pandora.

Thanks.

Reset maximum skip limit

When more than five tracks in a row are unplayable, the 'maximum skip limit' is enforced to avoid the client from exceeding Pandora's internal request thresholds.

This works as expected, but the limit is never reset again once it has been reached, and the only way to resume playback is to restart Mopidy. Log contains:

2016-01-26 06:07:28,518 - WARNING  Maximum track skip limit (5) exceeded.
2016-01-26 06:07:28,521 - WARNING  Track is not playable: pandora:track:788279271243133277:4b93698ca1d1b60a1e496911cad2e191a0645cda5c3ab18ebcc5328266209b4b2fe04a60810b426142cc58b1431e06c45e5d5323ac6195f3

A sensible point at which to reset the counter might be when the user does a manual refresh in the web client, or switches to a different station.

Remove album and artist URI's from Mopidy models

pydora currently sets the artist and album URI fields to point to the relevant sections of the Pandora website (e.g. http://www.pandora.com/hozier/from-eden-ep)

The doesn't make sense in a Mopidy context, where we expect to be able to do a mopidy.backend.LibraryProvider.lookup on the URI and get a list of tracks for the album or artist back. This can lead to unpredictable results in many Mopidy frontend extensions like Mopidy-MusicBox-Webclient.

We should either just clear the URI fields, or enhance mopidy_pandora.PandoraLibraryProvider.lookup to return sensible default values.

Play Pandora Station via CURL Request

I'm looking to be able to start a Pandora station via a simple CURL request. Looks like there are some previsions in the Mopidy API to be able to start playing a specific track with the track URI--I can't quite figure out how I could programmatically start a Pandora station. Would appreciate any guidance.

Add automatic enabling of repeat mode

Since mopidy-pandora assumes repeat mode is enabled in order to function properly, checking and enabling this setting automatically would probably be a good idea.

I'm not quite sure how to do this using the current Mopidy API.

A workaround for linux users might be to call the equivalent of the mpc repeat on command somewhere.

Station object created before using Station.from_json

Installed using pip: Mopidy-Pandora 0.4.0, pydora 1.12.0, Mopidy 2.1 on Debian Stretch on a Raspberry Pi.

In _create_station_for_token, json_result turns out to be a Station object already and does not seem to be a real json object. Setting new_station to be json_result makes it work. How can I help?

Add support for gapless playback

Gapless playback will be a nice feature to add, especially seeing as the high quality Pandora streams can take a while to buffer between track changes.

Mopidy 1.0.5 contains the basic callback mechanism for the implementation, but it still does not handle buffering properly. More info is available at: https://discuss.mopidy.com/t/has-the-gapless-playback-implementation-been-completed-yet/784/2

Perhaps this is something that we can take a look at when gapless playback is delivered in Mopidy 1.x

Station Art not Showing on Browse

Station art images are not appearing when browsing mopidy-pandora stations. I'll work on this and submit a pull request when I have it figured out.

Get 'Invalid Partner Login' With Valid Credentials

I have a Pandora One account (so I am actually paying Pandora monthly) and I am trying to setup mopidy-pandora to use my account, but no matter what I do I always get back 'Invalid Partner Login' and the extension ends up getting disabled.

The full error dump is:

ERROR    2016-01-06 21:30:41,991 [1601:PandoraBackend-7] pykka
  Unhandled exception in PandoraBackend (urn:uuid:931919b5-b51a-47ad-8462-fddb201d966a):
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 192, in _actor_loop
    self.on_start()
  File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/backend.py", line 52, in on_start
    self.api.login(self._config["username"], self._config["password"])
  File "/usr/local/lib/python2.7/dist-packages/pandora/client.py", line 71, in login
    return self._authenticate()
  File "/usr/local/lib/python2.7/dist-packages/pandora/client.py", line 85, in _authenticate
    xplatformAdCapable=True)
  File "/usr/local/lib/python2.7/dist-packages/pandora/transport.py", line 47, in function
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandora/transport.py", line 234, in __call__
    return self._parse_response(result)
  File "/usr/local/lib/python2.7/dist-packages/pandora/transport.py", line 220, in _parse_response
    raise PandoraException.from_code(result["code"], result["message"])
InvalidPartnerLogin: Invalid Partner Login
ERROR    2016-01-06 21:30:42,024 [1601:MainThread] mopidy.commands
  Actor died: PandoraBackend (urn:uuid:931919b5-b51a-47ad-8462-fddb201d966a) stopped before handling the message

My config is as follows:

[pandora]
enabled = true
api_host = tuner.pandora.com/services/json/
partner_encryption_key = 721^26xE22776
partner_decryption_key = 20zE1E47BE57$51
partner_username = iphone
partner_password = P2E4FC0EAD3*878N92B2CDp34I0B1@388137C
partner_device = IP01
preferred_audio_quality = mediumQuality #highQuality
username = myusername
password = mypassword
sort_order = date
auto_setup = true
### EXPERIMENTAL EVENT HANDLING IMPLEMENTATION ###
#event_support_enabled = false
#double_click_interval = 2.00
#on_pause_resume_click = thumbs_up
#on_pause_next_click = thumbs_down
#on_pause_previous_click = sleep

I got the Partner encrypt/decrypt/username/password/device from the link provided in the setup details.

Invalid Auth Token when browsing stations

Browsing stations sometimes does not work after a long period of inactivity. Instead of the list of stations appearing, and empty list is displayed.

This could either be due to:

  • the fact that user.getStationList and station.getGenreStations is run in parallel in different threads and that some sort of race condition occurs
  • there's a server side issue causing 1001: An unexpected error occurred, and the first few requests fail as a result.

The issue is fairly rare and just clicking on the last played track in the tracklist will re-authenticate correctly and fill the caches with the station list information.

It might be necessary to add a threading.Lock() to ensure that only one process re-authenticates at a time, or to catch the 1001-code exceptions with some sort of special retry logic.

Full stack trace below:

2016-01-21 22:02:51,714 - INFO     TRANSPORT: 
METHOD: user.getStationList
PARAMS: {'user_id': u'175482532', 'auth_token': u'VICRE1lhaAOhdqsswBEnhWIfVG0Vgr3hpD2phwZaC3JRwk6HH7GfHL6Q==', 'partner_id': u'42', 'method': 'user.getStationList'}
DATA: {'userAuthToken': u'VICRE1lhaAOhdqsswBEnhWIfVG0Vgr3hpD2phwZaC3JRwk6HH7GfHL6Q==', 'syncTime': 1453406567, 'includeStationArtUrl': True}
URL: http://tuner.pandora.com/services/json/
2016-01-21 22:02:51,719 - INFO     TRANSPORT: 
METHOD: station.getGenreStations
PARAMS: {'user_id': u'175482532', 'auth_token': u'VICRE1lhaAOhdqsswBEnhWIfVG0Vgr3hpD2phwZaC3JRwk6HH7GfHL6Q==', 'partner_id': u'42', 'method': 'station.getGenreStations'}
DATA: {'userAuthToken': u'VICRE1lhaAOhdqsswBEnhWIfVG0Vgr3hpD2phwZaC3JRwk6HH7GfHL6Q==', 'syncTime': 1453406567}
URL: http://tuner.pandora.com/services/json/
2016-01-21 22:02:51,753 - INFO     Resetting dropped connection: tuner.pandora.com
2016-01-21 22:02:51,758 - INFO     Starting new HTTP connection (3): tuner.pandora.com
2016-01-21 22:02:52,514 - INFO     TRANSPORT: 
RESULT: {"stat":"fail","message":"An unexpected error occurred","code":1001}

2016-01-21 22:02:52,518 - INFO     TRANSPORT: 
METHOD: auth.partnerLogin
PARAMS: {'user_id': None, 'auth_token': None, 'partner_id': None, 'method': 'auth.partnerLogin'}
DATA: {'username': u'android', 'userAuthToken': None, 'deviceModel': u'android-generic', 'syncTime': None, 'version': '5', 'password': u'AC7IBG09A3DTSYM4R41UJWL07VLN8JI7'}
URL: https://tuner.pandora.com/services/json/
2016-01-21 22:02:52,544 - INFO     Resetting dropped connection: tuner.pandora.com
2016-01-21 22:02:52,550 - INFO     TRANSPORT: 
RESULT: {"stat":"fail","message":"An unexpected error occurred","code":1001}

2016-01-21 22:02:52,554 - INFO     TRANSPORT: 
METHOD: auth.partnerLogin
PARAMS: {'user_id': None, 'auth_token': None, 'partner_id': None, 'method': 'auth.partnerLogin'}
DATA: {'username': u'android', 'userAuthToken': None, 'deviceModel': u'android-generic', 'syncTime': None, 'version': '5', 'password': u'AC7IBG09A3DTSYM4R41UJWL07VLN8JI7'}
URL: https://tuner.pandora.com/services/json/
2016-01-21 22:02:52,594 - INFO     Starting new HTTPS connection (4): tuner.pandora.com
2016-01-21 22:02:54,863 - INFO     TRANSPORT: 
RESULT: {"stat":"ok","result":{"stationSkipLimit":6,"partnerId":"42","partnerAuthToken":"VAI+vKUfyXtPc0fIJakAaeb15HA63B1nFA","syncTime":"f965207c45b03fbe59cac40964739354","deviceProperties":{"optionalFeatures":{"optionalFeature":[{"feature":"useAudioProxy2","enabled":"false","platformVersionRange":{"low":"4.0","high":"5.0.0"},"productVersionRange":{"low":"1.6","high":"*"}}]},"adRefreshInterval":4,"videoAdUniqueInterval":0,"videoAdRefreshInterval":870,"videoAdStartInterval":180,"ooyala":{"streamingPercentage":0,"streamingWhitelist":[534051315],"videoAdBufferRetryCount":3,"videoAdLoadingTimeout":2,"videoAdPlayTimeout":8}},"stationSkipUnit":"hour"}}

2016-01-21 22:02:54,869 - INFO     TRANSPORT: 
RESULT: {"stat":"ok","result":{"stationSkipLimit":6,"partnerId":"42","partnerAuthToken":"VAI+vKUfyXtPfOIZIgqV3pK15HA63B1nFA","syncTime":"78a1790b9f3995cd59cac40964739354","deviceProperties":{"optionalFeatures":{"optionalFeature":[{"feature":"useAudioProxy2","enabled":"false","platformVersionRange":{"low":"4.0","high":"5.0.0"},"productVersionRange":{"low":"1.6","high":"*"}}]},"adRefreshInterval":4,"videoAdUniqueInterval":0,"videoAdRefreshInterval":870,"videoAdStartInterval":180,"ooyala":{"streamingPercentage":0,"streamingWhitelist":[534051315],"videoAdBufferRetryCount":3,"videoAdLoadingTimeout":2,"videoAdPlayTimeout":8}},"stationSkipUnit":"hour"}}

2016-01-21 22:02:54,875 - INFO     TRANSPORT: 
METHOD: auth.userLogin
PARAMS: {'user_id': None, 'auth_token': u'VAI+vKUfyXtPfOIZIgqV3pK15HA63B1nFA', 'partner_id': u'42', 'method': 'auth.userLogin'}
DATA: {'username': u'name', 'includePandoraOneInfo': True, 'password': u'pwd', 'partnerAuthToken': u'VAI+vKUfyXtPfOIZIgqV3pK15HA63B1nFA', 'syncTime': 1453406569, 'includeSubscriptionExpiration': True, 'loginType': 'user', 'userAuthToken': None, 'xplatformAdCapable': True, 'returnCapped': True, 'includeAdAttributes': True, 'includeAdvertiserAttributes': True}
URL: https://tuner.pandora.com/services/json/
2016-01-21 22:02:54,879 - INFO     TRANSPORT: 
METHOD: auth.userLogin
PARAMS: {'user_id': None, 'auth_token': u'VAI+vKUfyXtPfOIZIgqV3pK15HA63B1nFA', 'partner_id': u'42', 'method': 'auth.userLogin'}
DATA: {'username': u'name', 'includePandoraOneInfo': True, 'password': u'pwd', 'partnerAuthToken': u'VAI+vKUfyXtPc0fIJakAaeb15HA63B1nFA', 'syncTime': 1453406569, 'includeSubscriptionExpiration': True, 'loginType': 'user', 'userAuthToken': None, 'xplatformAdCapable': True, 'returnCapped': True, 'includeAdAttributes': True, 'includeAdvertiserAttributes': True}
URL: https://tuner.pandora.com/services/json/
2016-01-21 22:02:55,312 - INFO     TRANSPORT: 
RESULT: {"stat":"fail","message":"An unexpected error occurred","code":1001}

2016-01-21 22:02:55,317 - ERROR    PandoraBackend backend caused an exception.
Traceback (most recent call last):
  File "/var/lib/git/mopidy/mopidy/core/library.py", line 19, in _backend_error_handling
    yield
  File "/var/lib/git/mopidy/mopidy/core/library.py", line 112, in _browse
    result = backend.library.browse(uri).get()
  File "/usr/local/lib/python2.7/dist-packages/pykka/threading.py", line 52, in get
    compat.reraise(*self._data['exc_info'])
  File "/usr/local/lib/python2.7/dist-packages/pykka/compat.py", line 12, in reraise
    exec('raise tp, value, tb')
  File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 201, in _actor_loop
    response = self._handle_receive(message)
  File "/usr/local/lib/python2.7/dist-packages/pykka/actor.py", line 295, in _handle_receive
    return callee(*message['args'], **message['kwargs'])
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/library.py", line 40, in browse
    return self._browse_stations()
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/library.py", line 139, in _browse_stations
    stations = self.backend.api.get_station_list()
  File "/var/lib/git/mopidy-pandora/mopidy_pandora/client.py", line 57, in get_station_list
    station_list = super(MopidyAPIClient, self).get_station_list()
  File "/var/lib/git/pydora/pandora/client.py", line 125, in get_station_list
    includeStationArtUrl=True))
  File "/var/lib/git/pydora/pandora/client.py", line 109, in __call__
    self._authenticate()
  File "/var/lib/git/pydora/pandora/client.py", line 86, in _authenticate
    xplatformAdCapable=True)
  File "/var/lib/git/pydora/pandora/transport.py", line 50, in function
    return func(*args, **kwargs)
  File "/var/lib/git/pydora/pandora/transport.py", line 243, in __call__
    return self._parse_response(result)
  File "/var/lib/git/pydora/pandora/transport.py", line 225, in _parse_response
    raise PandoraException.from_code(result["code"], result["message"])
InvalidAuthToken: Invalid Auth Token
2016-01-21 22:02:55,407 - INFO     TRANSPORT: 
RESULT: {"stat":"ok","result":{"hasAudioAds":true,"minimumAdRefreshInterval":5,"userAuthToken":"VIDQ8w2fcJ2Gm7vIDQ7vla8U877HgKCDPef8rMUJp4LtwDTr+EUrusag==","userId":"175482532","username":"uname","canListen":true,"isCapped":false,"promotedStationsPrefetchExpirationSeconds":14400,"listeningTimeoutAlertMsgUri":"/mobile/still_listening.vm","zeroVolumeNumMutedTracks":1,"listeningTimeoutMinutes":"180","splashScreenAdUrl":"http://ad.doubleclick.net/adx/pand.android/prod.welcome;a10=1;a11=1;a11=12;a11=16;a11=17;a11=21;a11=23;a11=25;a11=4;a11=6;a12=28;a12=38;a12=39;a12=40;d1=6;d2=32;d3=48;d3=50;d3=53;d4=415;d4=433;d8=0;p=1;p=4;p=8;t4=160;t4=208;t4=218;t4=220;t4=221;t4=225;t4=226;t4=227;t4=229;t4=233;t4=236;t4=256;t4=274;t4=275;t4=276;t4=281;mdid=9f058025faaef7993be67cfc3596c8cd;msa=003;OS=;aa=0;ag=38;app=;bz=;clean=0;co=06037;con=;dma=803;et=0;fam=-1;gnd=1;hhi=1;hisp=0;hours=0;iat=1;l=27oiry5k23232pxkduq56o55suf2ymd56cwjd3q;mc=0;model=;tablet=0;mp=1;st=CA;uq=9f058025faaef7993be67cfc3596c8cd;vx=;vxc=;zip=90210;sz=320x50;ord=__CACHEBUST__","userPPID":"9f058025faaef7993be67cfc3596c8cd","promotedStationsRecommendationFallback":true,"eligibleForPromotedStations":true,"userProfileUrl":"https://www.pandora.com/login?auth_token=VIDQ8w2fcJ2Gm7vIDQ7vla8U877HgKCDPef8rMUJp4LtwDTr%2BEUrusag%3D%3D&target=%2Fprofile%2Fpandora.dev2","maxStationsAllowed":100,"videoAdUrl":"http://ad.doubleclick.net/pfadx/pand.android/prod.nowplaying;a10=1;a11=1;a11=12;a11=16;a11=17;a11=21;a11=23;a11=25;a11=4;a11=6;a12=28;a12=38;a12=39;a12=40;d1=6;d2=32;d3=48;d3=50;d3=53;d4=415;d4=433;d8=0;p=1;p=4;p=8;t4=160;t4=208;t4=218;t4=220;t4=221;t4=225;t4=226;t4=227;t4=229;t4=233;t4=236;t4=256;t4=274;t4=275;t4=276;t4=281;mdid=9f058025faaef7993be67cfc3596c8cd;msa=003;OS=;aa=0;ag=38;app=;bz=;clean=0;co=06037;con=;dma=803;et=0;fam=-1;gnd=1;hhi=1;hisp=0;hours=0;index=__INDEX__;l=r6d4lrx4bdxzssyes7batwqg4n34kcvezidyhdq;mc=0;model=;tablet=0;mp=1;st=CA;uq=9f058025faaef7993be67cfc3596c8cd;vx=;zip=90210;sz=442x188;ord=__CACHEBUST__","stationCreationAdUrl":"http://ad.doubleclick.net/adx/pand.android/prod.createstation;a10=1;a11=1;a11=12;a11=16;a11=17;a11=21;a11=23;a11=25;a11=4;a11=6;a12=28;a12=38;a12=39;a12=40;d1=6;d2=32;d3=48;d3=50;d3=53;d4=415;d4=433;d8=0;p=1;p=4;p=8;t4=160;t4=208;t4=218;t4=220;t4=221;t4=225;t4=226;t4=227;t4=229;t4=233;t4=236;t4=256;t4=274;t4=275;t4=276;t4=281;mdid=9f058025faaef7993be67cfc3596c8cd;msa=003;OS=;aa=0;ag=38;app=;bz=;clean=0;co=06037;con=;dma=803;et=0;fam=-1;genre=0;gnd=1;hhi=1;hisp=0;l=krizdbpuhvsf355svqp4fjq2wpfbntp3gtx33pi;mc=0;model=;tablet=0;mp=1;st=CA;uq=9f058025faaef7993be67cfc3596c8cd;vx=;zip=90210;tile=1;sz=320x50;ord=__CACHEBUST__","subscriptionHasExpired":false,"zeroVolumeAutoPauseEnabledFlag":true}}

2016-01-21 22:02:55,412 - INFO     TRANSPORT: 
METHOD: station.getGenreStations
PARAMS: {'user_id': u'175482532', 'auth_token': u'VIDQ8w2fcJ2Gm7vIDQ7vla8U877HgKCDPef8rMUJp4LtwDTr+EUrusag==', 'partner_id': u'42', 'method': 'station.getGenreStations'}
DATA: {'userAuthToken': u'VIDQ8w2fcJ2Gm7vIDQ7vla8U877HgKCDPef8rMUJp4LtwDTr+EUrusag==', 'syncTime': 1453406570}
URL: http://tuner.pandora.com/services/json/

Mopidy 2.0 seems to break Mopidy-Pandora

After pip upgrading all of my mopidy extensions, I'm getting this message when I start mopidy:

ERROR Setup of extension from entry point pandora failed, ignoring extension. Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/mopidy/ext.py", line 218, in load_extensions config_schema = extension.get_config_schema() File "/usr/lib/python2.7/site-packages/mopidy_pandora/__init__.py", line 21, in get_config_schema from pandora import BaseAPIClient File "/usr/lib/python2.7/site-packages/pandora/__init__.py", line 13, in <module> from .transport import APITransport, Encryptor, DEFAULT_API_HOST File "/usr/lib/python2.7/site-packages/pandora/transport.py", line 18, in <module> from Crypto.Cipher import Blowfish File "/usr/lib/python2.7/site-packages/Crypto/Cipher/Blowfish.py", line 55, in <module> from Crypto.Cipher import _create_cipher ImportError: cannot import name _create_cipher

IIRC, the mopidy-gmusic extension upgraded some crypto libraries, so that may be the culprit.

Station start but plays only few seconds

Hello
i am having the following issue.

Many times when i click on the station, it starts but plays only few seconds (~5s) and then stops and loops back from the beginning. I can see the progress bar starting counting to ~ 5s and starting back from 0.
I have to press "Next Track" button for the same station few times to start the next song and make it play.

Please let me know if someone have seen this behavior.
Also any suggestions on how to debug it, fix the issue.

Thanks

Different ads being assigned the same URI

Ad tokens can contain a ':', which is also the default separator used by PandoraUri.

e.g.: 'adToken': u'2949971379462973092-pod:2/2/1'

This messes up the URI parsing logic, and if two ads with the same adToken prefix end up in the track list at the same time, Mopidy-Pandora will just keep looping between these two tracks instead of advancing to the next Pandora track.

Pandora track skip limit exceeded - how to know when a track is playable?

Hi all, I'm creating an application that switches pandora stations (on a free account) somewhat frequently, but doesn't try to manually skip tracks. The sequence is: clear tracklist, add pandora station, play. Mopidy automatically loads tracks from the station and plays them. For the most part, it's working very well.
I often get this: "track is not playable: pandora:ad:..." Usually this isn't a problem and it can go to the next track.

However, occasionally I get warnings like this in a row:

WARNING Track is not playable: pandora:ad:4092143028425283980:4092143028425283980-pod%3A1/2/8
WARNING Maximum track skip limit (5) exceeded.
WARNING Track is not playable: pandora:ad:4092143028425283980:4092143028425283980-pod%3A2/2/

When this happens, the next track doesn't play, and the station is just silent.

I looked at issue #43 so I want to ask what determines when a pandora track is playble? Are ads always not playable? Because sometimes the ads will successfully play. Other times only the tracks will play, and rarely I'll get the issue I just described where nothing plays. Restarting mopidy fixes the problem, as noted in #43, but I'll try to avoid it if there's a better way.
Thanks in advance!

Auto setup should be performed every time first Pandora track plays

Mopidy-Pandora automatically sets the appropriate playback settings when the first track is played (repeat on, with shuffle, single, and consume off).

It is possible that the user will play other tracks using other Mopidy extensions, and then go back into Mopidy-Pandora at some point afterwards. When that happens the auto setup should ideally be performed again.

Perhaps implementing BackendListener.playlists_loaded to call the setup routines when a new playlist is loaded would be the most standard approach.

Unofficial Pandora API Discord

Hello! πŸ‘‹

πŸ’  I'm going around all of the Pandora Libraries's as well as their products, and telling users about a Discord server I've been making to allow us all to communicate easily and quickly. All library creators will be given their own role and their own support channel to (optionally) help users. All product creators will be given their own role, and their own support channels as well. Please join! We're looking to get as many Unofficial Pandora API dev's to come together, and allow for easy communication.

πŸ’  Some more info about me: A simple Discord user. I'm looking to create Node.js API, but noticed there was no way to contact anyone nor a simple community behind it that I could talk to, so I've made this guild to try to make the community visible as one giant group.

πŸ’  We think you'd be an awesome addition to the community, please, join! Let's bring this Unofficial API all into one place for easy support and documentation, as well as product listings and library listings. Hope to see you there! πŸ‘

Join Here
https://discord.gg/VqzGTV8

Music stops playing after 2-3 songs.

First I'll start this by saying I'm working with a non-standard configuration.

I started with a MusicBox Image which I wanted to run on a pi3. I manually updated some of the boot files and got it to boot up.. then updated the repositories to jessie repositories and ran apt-get update/upgrade on everything... then I installed the newest firmware with rpi-update. After that musicbox appeared to start up and run normally.

Then I attempted an install of mopidy-pandora.. which made musicbox not work every time I tried until I realized it was installing mopidy 2.0 which wasn't working right due to other things missing. anyway. I finally had success. I installed the dev-tools needed and then updated mopidy and installed pydora and mopidy-pandora. this has left me with the following versions of things. full list at the very bottom of this text.

pydora (1.7.0)
Mopidy-Pandora (0.1.8)
cachetools (1.0.0)
requests (2.5.1)

The issue I'm having is this. I click a pandora station and it lists one "Track" (which also has the name of that pandora station). I click the track and it starts playing. As each song plays in the log I get 2 lines that look like this:
Up next: 'The Killing Moon' by Echo & The Bunnymen
WARNING Element doesn't implement handling of this stream. Please file a bug.

repeat does not appear as though it gets turned on no its own... though I can hit the button and turn it on when it starts

the music plays fine for a song or two.. at which point it just stops at the end of a song. this error shows in the log:

2016-04-11 20:19:53,927 - INFO Up next: 'Gonna Find You' by Operation Ivy 2016-04-11 20:19:54,066 - WARNING Element doesn't implement handling of this stream. Please file a bug. 2016-04-11 20:20:22,648 - INFO 200 GET / (127.0.0.1) 2.59ms 2016-04-11 20:21:49,098 - ERROR Triggering event failed: reached_end_of_stream Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/mopidy/listener.py", line 55, in on_event getattr(self, event)(**kwargs) File "/usr/local/lib/python2.7/dist-packages/mopidy/core/actor.py", line 87, in reached_end_of_stream self.playback._on_end_of_track() File "/usr/local/lib/python2.7/dist-packages/mopidy/core/playback.py", line 243, in _on_end_of_track self._change_track(next_tl_track) File "/usr/local/lib/python2.7/dist-packages/mopidy/core/playback.py", line 208, in _change_track self._play(on_error_step=on_error_step) File "/usr/local/lib/python2.7/dist-packages/mopidy/core/playback.py", line 359, in _play backend.playback.change_track(tl_track.track).get() and File "/usr/lib/python2.7/dist-packages/pykka/threading.py", line 52, in get compat.reraise(*self._data['exc_info']) File "/usr/lib/python2.7/dist-packages/pykka/compat.py", line 12, in reraise exec('raise tp, value, tb') File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 201, in _actor_loop response = self._handle_receive(message) File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 295, in _handle_receive return callee(*message['args'], **message['kwargs']) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/playback.py", line 63, in change_track next_track = self.get_next_track(track_uri.index) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/playback.py", line 87, in get_next_track logger.warning("Track with uri '%s' is not playable.", TrackUri.from_track(track).uri) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/uri.py", line 83, in from_track return TrackUri(track.station_id, track.track_token, track.song_name, track.song_detail_url, AttributeError: 'AdItem' object has no attribute 'track_token'

Side Note: if I update mopidy-pandora to v0.2.0 and click on a station the track title actually looks like a track.. not just the title of the station.. but clicking on it gives me the error:
2016-04-11 20:31:57,760 - ERROR PandoraBackend backend caused an exception. Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/mopidy/core/library.py", line 19, in _backend_error_handling yield File "/usr/local/lib/python2.7/dist-packages/mopidy/core/library.py", line 236, in lookup result = future.get() File "/usr/lib/python2.7/dist-packages/pykka/threading.py", line 52, in get compat.reraise(*self._data['exc_info']) File "/usr/lib/python2.7/dist-packages/pykka/compat.py", line 12, in reraise exec('raise tp, value, tb') File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 201, in _actor_loop response = self._handle_receive(message) File "/usr/lib/python2.7/dist-packages/pykka/actor.py", line 295, in _handle_receive return callee(*message['args'], **message['kwargs']) File "/usr/local/lib/python2.7/dist-packages/mopidy_pandora/library.py", line 85, in lookup track_kwargs['bitrate'] = int(track.bitrate)

Receiving Invalid Auth Token

I haven't used the Pandora plugin in a week or so but after a restart of my machine I'm now receiving the error below in the logs from Mopidy-Pandora. The username and password are correct for Pandora so not sure what else may have changed on their side to cause this.

OS: Ubuntu 20.04
Python: 3.8.10
Mopidy Info:

Mopidy 3.2.0
Mopidy-Pandora 1.1.1

Log Output:

Dec 22 18:26:23 daplex mopidy[318526]: ERROR [PandoraBackend-7] pykka Unhandled exception in PandoraBackend (urn:uuid:a5ecfc09-df51-490e-bf31-bd95ee1b31d0):
Dec 22 18:26:23 daplex mopidy[318526]: Traceback (most recent call last):
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/lib/python3/dist-packages/pykka/_actor.py", line 186, in _actor_loop
Dec 22 18:26:23 daplex mopidy[318526]: self.on_start()
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/mopidy_pandora/backend.py", line 48, in on_start
Dec 22 18:26:23 daplex mopidy[318526]: self.api.login(self.config["username"], self.config["password"])
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/pandora/client.py", line 64, in login
Dec 22 18:26:23 daplex mopidy[318526]: return self._authenticate()
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/pandora/client.py", line 70, in > _authenticate
Dec 22 18:26:23 daplex mopidy[318526]: user = self.transport(
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/pandora/transport.py", line 51, in function
Dec 22 18:26:23 daplex mopidy[318526]: return func(*args, **kwargs)
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/pandora/transport.py", line 243, in call
Dec 22 18:26:23 daplex mopidy[318526]: return self._parse_response(result)
Dec 22 18:26:23 daplex mopidy[318526]: File "/usr/local/lib/python3.8/dist-packages/pandora/transport.py", line 232, in _parse_response
Dec 22 18:26:23 daplex mopidy[318526]: raise PandoraException.from_code(result["code"], result["message"])
Dec 22 18:26:23 daplex mopidy[318526]: pandora.errors.InvalidAuthToken: Invalid Auth Token
Dec 22 18:26:23 daplex mopidy[318526]: ERROR [MainThread] mopidy.commands Actor died: PandoraBackend (urn:uuid:a5ecfc09-df51-490e-bf31-bd95ee1b31d0) stopped before handling the message

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.