Add support for Premium streams in di.fm

This commit is contained in:
David Sansome 2011-01-15 13:59:58 +00:00
parent c6d724f53a
commit 52550acb75
5 changed files with 80 additions and 34 deletions

View File

@ -0,0 +1,11 @@
# These have to be in the same order as in the settings dialog
PLAYLISTS = [
{"premium": False, "url": "http://listen.di.fm/public3/%s.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/premium.pls"},
{"premium": False, "url": "http://listen.di.fm/public2/%s.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/64k.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/128k.pls"},
{"premium": False, "url": "http://listen.di.fm/public5/%s.asx"},
{"premium": True, "url": "http://www.di.fm/listen/%s/64k.asx"},
{"premium": True, "url": "http://www.di.fm/listen/%s/128k.asx"},
]

View File

@ -18,11 +18,11 @@ class Plugin:
self.service.SettingsDialogRequested.connect(self.ShowSettings) self.service.SettingsDialogRequested.connect(self.ShowSettings)
def ShowSettings(self): def ShowSettings(self):
# Create the dialog the first time it's shown
if not self.settings_dialog: if not self.settings_dialog:
# Create the dialog the first time it's shown
self.settings_dialog = SettingsDialog() self.settings_dialog = SettingsDialog()
self.settings_dialog.accepted.connect(self.service.ReloadSettings)
# Show the dialog
self.settings_dialog.show() self.settings_dialog.show()
plugin = Plugin() plugin = Plugin()

View File

@ -1,9 +1,11 @@
import common
import clementine import clementine
from PyQt4.QtCore import QSettings, QUrl from PyQt4.QtCore import QSettings, QUrl
from PyQt4.QtGui import QAction, QDesktopServices, QIcon, QMenu, \ from PyQt4.QtGui import QAction, QDesktopServices, QIcon, QMenu, \
QStandardItem QStandardItem
from PyQt4.QtNetwork import QNetworkRequest from PyQt4.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
import PyQt4.QtCore import PyQt4.QtCore
import json import json
@ -15,18 +17,6 @@ class DigitallyImportedService(clementine.RadioService):
HOMEPAGE_URL = QUrl("http://www.di.fm/") HOMEPAGE_URL = QUrl("http://www.di.fm/")
STREAM_LIST_URL = QUrl("http://listen.di.fm/") STREAM_LIST_URL = QUrl("http://listen.di.fm/")
# These have to be in the same order as in the settings dialog
PLAYLISTS = [
{"premium": False, "url": "http://listen.di.fm/public3/%s.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/premium.pls"},
{"premium": False, "url": "http://listen.di.fm/public2/%s.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/64k.pls"},
{"premium": True, "url": "http://www.di.fm/listen/%s/128k.pls"},
{"premium": False, "url": "http://listen.di.fm/public5/%s.asx"},
{"premium": True, "url": "http://www.di.fm/listen/%s/64k.asx"},
{"premium": True, "url": "http://www.di.fm/listen/%s/128k.asx"},
]
SettingsDialogRequested = PyQt4.QtCore.pyqtSignal() SettingsDialogRequested = PyQt4.QtCore.pyqtSignal()
def __init__(self, model): def __init__(self, model):
@ -36,6 +26,7 @@ class DigitallyImportedService(clementine.RadioService):
self.path = os.path.dirname(__file__) self.path = os.path.dirname(__file__)
self.audio_type = 0 self.audio_type = 0
self.context_index = None self.context_index = None
self.last_original_url = None self.last_original_url = None
self.menu = None self.menu = None
@ -50,6 +41,20 @@ class DigitallyImportedService(clementine.RadioService):
settings.beginGroup(self.SERVICE_NAME) settings.beginGroup(self.SERVICE_NAME)
self.audio_type = int(settings.value("audio_type", 0).toPyObject()) self.audio_type = int(settings.value("audio_type", 0).toPyObject())
username = unicode(settings.value("username", "").toPyObject().toUtf8())
password = unicode(settings.value("password", "").toPyObject().toUtf8())
# If a username and password were set by the user then set them in the
# cookies we pass to www.di.fm
cookie_jar = None
if len(username) and len(password):
cookie_jar = QNetworkCookieJar()
cookie_jar.setCookiesFromUrl([
QNetworkCookie("_amember_ru", username),
QNetworkCookie("_amember_rp", password),
], QUrl("http://www.di.fm/"))
self.network.setCookieJar(cookie_jar)
def CreateRootItem(self): def CreateRootItem(self):
self.root = QStandardItem(QIcon(os.path.join(self.path, "icon-small.png")), self.root = QStandardItem(QIcon(os.path.join(self.path, "icon-small.png")),
@ -80,7 +85,7 @@ class DigitallyImportedService(clementine.RadioService):
self.menu.addSeparator() self.menu.addSeparator()
self.menu.addAction(clementine.IconLoader.Load("configure"), self.menu.addAction(clementine.IconLoader.Load("configure"),
self.tr("Configure Digitally Imported..."), self.SettingsDialogRequested) self.tr("Configure Digitally Imported..."), self.SettingsDialogRequested.emit)
self.context_index = index self.context_index = index
self.menu.popup(global_pos) self.menu.popup(global_pos)
@ -152,12 +157,12 @@ class DigitallyImportedService(clementine.RadioService):
return result return result
key = original_url.host() key = original_url.host()
playlist_url = self.PLAYLISTS[self.audio_type]["url"] % key playlist_url = common.PLAYLISTS[self.audio_type]["url"] % key
# Start fetching the playlist # Start fetching the playlist. Can't use a SongLoader to do this because
self.song_loader = clementine.SongLoader(clementine.library) # we have to use the cookies we set in ReloadSettings()
self.song_loader.LoadFinished.connect(self.LoadPlaylistFinished) reply = self.network.get(QNetworkRequest(QUrl(playlist_url)))
self.song_loader.Load(QUrl(playlist_url)) reply.finished.connect(self.LoadPlaylistFinished)
# Save the original URL so we can emit it in the finished signal later # Save the original URL so we can emit it in the finished signal later
self.last_original_url = original_url self.last_original_url = original_url
@ -167,10 +172,13 @@ class DigitallyImportedService(clementine.RadioService):
result.type_ = clementine.PlaylistItem.SpecialLoadResult.WillLoadAsynchronously result.type_ = clementine.PlaylistItem.SpecialLoadResult.WillLoadAsynchronously
result.original_url_ = original_url result.original_url_ = original_url
print result
return result return result
def LoadPlaylistFinished(self, success): def LoadPlaylistFinished(self):
# Get the QNetworkReply that called this slot
reply = self.sender()
reply.deleteLater()
if self.task_id is None: if self.task_id is None:
return return
@ -178,16 +186,20 @@ class DigitallyImportedService(clementine.RadioService):
clementine.task_manager.SetTaskFinished(self.task_id) clementine.task_manager.SetTaskFinished(self.task_id)
self.task_id = None self.task_id = None
# Try to parse the playlist
parser = clementine.PlaylistParser(clementine.library)
songs = parser.Load(reply)
# Failed to get the playlist? # Failed to get the playlist?
if not success: if len(songs) == 0:
self.StreamError.emit("Error loading playlist '%s'" % self.song_loader.url().toString()) self.StreamError.emit("Error loading playlist '%s'" % self.song_loader.url().toString())
return return
result = clementine.PlaylistItem.SpecialLoadResult() result = clementine.PlaylistItem.SpecialLoadResult()
result.original_url_ = self.last_original_url result.original_url_ = self.last_original_url
if len(self.song_loader.songs()) > 0:
# Take the first track in the playlist # Take the first track in the playlist
result.type_ = clementine.PlaylistItem.SpecialLoadResult.TrackAvailable result.type_ = clementine.PlaylistItem.SpecialLoadResult.TrackAvailable
result.media_url_ = QUrl(self.song_loader.songs()[0].filename()) result.media_url_ = QUrl(songs[0].filename())
self.AsyncLoadFinished.emit(result) self.AsyncLoadFinished.emit(result)

View File

@ -1,4 +1,7 @@
from PyQt4.QtGui import QDialog, QIcon from service import DigitallyImportedService
from PyQt4.QtCore import QSettings
from PyQt4.QtGui import QDialog, QIcon
import PyQt4.uic import PyQt4.uic
import os.path import os.path
@ -12,5 +15,25 @@ class SettingsDialog(QDialog):
# Set up the user interface # Set up the user interface
PyQt4.uic.loadUi(os.path.join(self.path, "settingsdialog.ui"), self) PyQt4.uic.loadUi(os.path.join(self.path, "settingsdialog.ui"), self)
# Set the icon # Set the window icon
self.setWindowIcon(QIcon(os.path.join(self.path, "icon-small.png"))) self.setWindowIcon(QIcon(os.path.join(self.path, "icon-small.png")))
def showEvent(self, event):
# Load the settings
settings = QSettings()
settings.beginGroup(DigitallyImportedService.SERVICE_NAME)
self.type.setCurrentIndex(int(settings.value("audio_type", 0).toPyObject()))
self.username.setText(settings.value("username", "").toPyObject())
self.password.setText(settings.value("password", "").toPyObject())
QDialog.showEvent(self, event)
def accept(self):
# Save the settings
settings = QSettings()
settings.beginGroup(DigitallyImportedService.SERVICE_NAME)
settings.setValue("audio_type", self.type.currentIndex())
settings.setValue("username", self.username.text())
settings.setValue("password", self.password.text())
QDialog.accept(self)

View File

@ -16,9 +16,6 @@
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -63,7 +60,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>&lt;a href=&quot;http://www.di.fm/premium/&quot;&gt;Upgrade to Premium now&lt;/a&gt;</string> <string>&lt;a href=&quot;http://www.di.fm/premium/&quot;&gt;Upgrade to Premium now&lt;/a&gt;</string>
@ -71,6 +68,9 @@
<property name="openExternalLinks"> <property name="openExternalLinks">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>