Update the digitallyimported-radio plugin to work with the new scripting api. Almost works - listing stations works, but can't play playlists yet because of QList<Song> binding problem

This commit is contained in:
David Sansome 2011-05-19 23:02:37 +00:00
parent 5c1139747f
commit ef1358e5aa
5 changed files with 91 additions and 66 deletions

View File

@ -2,8 +2,8 @@ import clementine
from servicebase import DigitallyImportedServiceBase
from PyQt4.QtCore import QSettings, QUrl
from PyQt4.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
from PythonQt.QtCore import QSettings, QUrl
from PythonQt.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
class DigitallyImportedService(DigitallyImportedServiceBase):
HOMEPAGE_URL = QUrl("http://www.di.fm/")
@ -26,8 +26,8 @@ class DigitallyImportedService(DigitallyImportedServiceBase):
{"premium": True, "url": "http://www.di.fm/listen/%s/128k.asx"},
]
def __init__(self, model):
DigitallyImportedServiceBase.__init__(self, model)
def __init__(self, model, settings_dialog_callback):
DigitallyImportedServiceBase.Init(self, model, settings_dialog_callback)
def ReloadSettings(self):
DigitallyImportedServiceBase.ReloadSettings(self)
@ -48,5 +48,5 @@ class DigitallyImportedService(DigitallyImportedServiceBase):
# Start fetching the playlist. Can't use a SongLoader to do this because
# we have to use the cookies we set in ReloadSettings()
reply = self.network.get(QNetworkRequest(QUrl(playlist_url)))
reply.finished.connect(self.LoadPlaylistFinished)
self.load_station_reply = self.network.get(QNetworkRequest(QUrl(playlist_url)))
self.load_station_reply.connect("finished()", self.LoadPlaylistFinished)

View File

@ -9,24 +9,20 @@ class Plugin:
self.settings_dialog = None
# Create the services and add them to the Internet tab
self.di_service = DigitallyImportedService(clementine.radio_model)
self.sky_service = SkyFmService(clementine.radio_model)
self.di_service = DigitallyImportedService(clementine.radio_model, self.ShowSettings)
self.sky_service = SkyFmService(clementine.radio_model, self.ShowSettings)
clementine.radio_model.AddService(self.di_service)
clementine.radio_model.AddService(self.sky_service)
# Register for when the user clicks the Settings button
script.SettingsDialogRequested.connect(self.ShowSettings)
# Register for the "Configure..." right click menu items
self.di_service.SettingsDialogRequested.connect(self.ShowSettings)
self.sky_service.SettingsDialogRequested.connect(self.ShowSettings)
script.connect("SettingsDialogRequested()", self.ShowSettings)
def ShowSettings(self):
if not self.settings_dialog:
# Create the dialog the first time it's shown
self.settings_dialog = SettingsDialog()
self.settings_dialog.accepted.connect(self.di_service.ReloadSettings)
self.settings_dialog.accepted.connect(self.sky_service.ReloadSettings)
self.settings_dialog.connect("accepted()", self.di_service.ReloadSettings)
self.settings_dialog.connect("accepted()", self.sky_service.ReloadSettings)
self.settings_dialog.show()

View File

@ -1,10 +1,10 @@
import clementine
from PyQt4.QtCore import QSettings, QUrl
from PyQt4.QtGui import QAction, QDesktopServices, QIcon, QMenu, \
QStandardItem
from PyQt4.QtNetwork import QNetworkRequest
import PyQt4.QtCore
import PythonQt
from PythonQt.QtCore import QSettings, QUrl
from PythonQt.QtGui import QAction, QDesktopServices, QIcon, QMenu, \
QStandardItem
from PythonQt.QtNetwork import QNetworkRequest
import json
import operator
@ -23,7 +23,7 @@ class DigitallyImportedUrlHandler(clementine.UrlHandler):
return self.url_scheme
def StartLoading(self, original_url):
result = clementine.UrlHandler.LoadResult()
result = clementine.UrlHandler_LoadResult()
if self.task_id is not None:
return result
@ -41,7 +41,7 @@ class DigitallyImportedUrlHandler(clementine.UrlHandler):
# Tell the user what's happening
self.task_id = clementine.task_manager.StartTask(self.tr("Loading stream"))
result.type_ = clementine.UrlHandler.LoadResult.WillLoadAsynchronously
result.type_ = clementine.UrlHandler_LoadResult.WillLoadAsynchronously
result.original_url_ = original_url
return result
@ -64,11 +64,11 @@ class DigitallyImportedUrlHandler(clementine.UrlHandler):
self.service.StreamError.emit("Error loading playlist '%s'" % reply.url().toString())
return
result = clementine.UrlHandler.LoadResult()
result = clementine.UrlHandler_LoadResult()
result.original_url_ = self.last_original_url
# Take the first track in the playlist
result.type_ = clementine.UrlHandler.LoadResult.TrackAvailable
result.type_ = clementine.UrlHandler_LoadResult.TrackAvailable
result.media_url_ = songs[0].url()
self.AsyncLoadComplete.emit(result)
@ -87,11 +87,11 @@ class DigitallyImportedServiceBase(clementine.RadioService):
SETTINGS_GROUP = "digitally_imported"
SettingsDialogRequested = PyQt4.QtCore.pyqtSignal()
def __init__(self, model):
def Init(self, model, settings_dialog_callback):
clementine.RadioService.__init__(self, self.SERVICE_NAME, model)
self.settings_dialog_callback = settings_dialog_callback
self.url_handler = DigitallyImportedUrlHandler(self.URL_SCHEME, self)
clementine.player.RegisterUrlHandler(self.url_handler)
@ -106,6 +106,9 @@ class DigitallyImportedServiceBase(clementine.RadioService):
self.menu = None
self.root = None
self.task_id = None
self.refresh_streams_reply = None
self.load_station_reply = None
self.items = []
self.ReloadSettings()
@ -113,9 +116,9 @@ class DigitallyImportedServiceBase(clementine.RadioService):
settings = QSettings()
settings.beginGroup(self.SETTINGS_GROUP)
self.audio_type = int(settings.value("audio_type", 0).toPyObject())
self.username = unicode(settings.value("username", "").toPyObject().toUtf8())
self.password = unicode(settings.value("password", "").toPyObject().toUtf8())
self.audio_type = int(settings.value("audio_type", 0))
self.username = unicode(settings.value("username", ""))
self.password = unicode(settings.value("password", ""))
def CreateRootItem(self):
self.root = QStandardItem(QIcon(os.path.join(self.path, self.ICON_FILENAME)),
@ -142,7 +145,7 @@ class DigitallyImportedServiceBase(clementine.RadioService):
self.menu.addSeparator()
self.menu.addAction(clementine.IconLoader.Load("configure"),
self.tr("Configure..."), self.SettingsDialogRequested.emit)
self.tr("Configure..."), self.settings_dialog_callback())
self.context_index = index
self.menu.popup(global_pos)
@ -158,15 +161,17 @@ class DigitallyImportedServiceBase(clementine.RadioService):
return
# Request the list of stations
reply = self.network.get(QNetworkRequest(self.STREAM_LIST_URL))
reply.finished.connect(self.RefreshStreamsFinished)
self.refresh_streams_reply = self.network.get(QNetworkRequest(self.STREAM_LIST_URL))
self.refresh_streams_reply.connect("finished()", self.RefreshStreamsFinished)
# Give the user some indication that we're doing something
self.task_id = clementine.task_manager.StartTask(self.tr("Getting streams"))
def RefreshStreamsFinished(self):
# Get the QNetworkReply that called this slot
reply = self.sender()
if self.refresh_streams_reply is None:
return
reply = self.refresh_streams_reply
reply.deleteLater()
if self.task_id is None:
@ -189,17 +194,21 @@ class DigitallyImportedServiceBase(clementine.RadioService):
self.root.removeRows(0, self.root.rowCount())
for stream in streams:
print stream
song = clementine.Song()
song.set_title(stream["name"])
song.set_artist(self.SERVICE_DESCRIPTION)
song.set_url(QUrl("%s://%s" % (self.URL_SCHEME, stream["key"])))
item = QStandardItem(QIcon(":last.fm/icon_radio.png"), stream["name"])
item.setData(stream["description"], PyQt4.QtCore.Qt.ToolTipRole)
item.setData(stream["description"], PythonQt.QtCore.Qt.ToolTipRole)
item.setData(clementine.RadioModel.PlayBehaviour_SingleItem, clementine.RadioModel.Role_PlayBehaviour)
item.setData(song, clementine.RadioModel.Role_SongMetadata)
self.root.appendRow(item)
# Keep references to the items otherwise Python will delete them
self.items.append(item)
def playlistitem_options(self):
return clementine.PlaylistItem.Options(clementine.PlaylistItem.PauseDisabled)
@ -207,4 +216,4 @@ class DigitallyImportedServiceBase(clementine.RadioService):
raise NotImplementedError()
def LoadPlaylistFinished(self):
self.url_handler.LoadPlaylistFinished(self.sender())
self.url_handler.LoadPlaylistFinished(self.load_station_reply)

View File

@ -1,39 +1,59 @@
from servicebase import DigitallyImportedServiceBase
from PyQt4.QtCore import QSettings
from PyQt4.QtGui import QDialog, QIcon
import PyQt4.uic
from PythonQt.QtCore import QEvent, QFile, QObject, QSettings
from PythonQt.QtGui import QComboBox, QDialog, QIcon, QLineEdit
from PythonQt.QtUiTools import QUiLoader
import os.path
class SettingsDialog(QDialog):
class SettingsDialog(QObject):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
QObject.__init__(self, parent)
self.path = os.path.dirname(__file__)
# Set up the user interface
PyQt4.uic.loadUi(os.path.join(self.path, "settingsdialog.ui"), self)
ui_filename = os.path.join(self.path, "settingsdialog.ui")
ui_file = QFile(ui_filename)
if not ui_file.open(QFile.ReadOnly):
raise IOError(ui_file)
loader = QUiLoader()
self.dialog = loader.load(ui_file)
# Get the widgets from the dialog so we can use them later
self.type = self.dialog.findChild(QComboBox, "type")
self.username = self.dialog.findChild(QLineEdit, "username")
self.password = self.dialog.findChild(QLineEdit, "password")
# Install ourselves as an event filter on the dialog so we can see when
# it gets shown
self.dialog.installEventFilter(self)
# Connect to the accepted signal so we can save settings when the user
# clicks OK
self.dialog.connect("accepted()", self.SaveSettings)
# Set the window icon
self.setWindowIcon(QIcon(os.path.join(self.path, "icon-small.png")))
self.dialog.setWindowIcon(QIcon(os.path.join(self.path, "icon-small.png")))
def showEvent(self, event):
# Load the settings
def eventFilter(self, obj, event):
if obj == self.dialog:
if event.type() == QEvent.Show:
self.LoadSettings()
QObject.eventFilter(self, obj, event)
def LoadSettings(self):
settings = QSettings()
settings.beginGroup(DigitallyImportedServiceBase.SETTINGS_GROUP)
self.type.setCurrentIndex(int(settings.value("audio_type", 0).toPyObject()))
self.username.setText(settings.value("username", "").toPyObject())
self.password.setText(settings.value("password", "").toPyObject())
self.type.setCurrentIndex(int(settings.value("audio_type", 0)))
self.username.setText(settings.value("username", ""))
self.password.setText(settings.value("password", ""))
QDialog.showEvent(self, event)
def accept(self):
# Save the settings
def SaveSettings(self):
settings = QSettings()
settings.beginGroup(DigitallyImportedServiceBase.SETTINGS_GROUP)
settings.setValue("audio_type", self.type.currentIndex())
settings.setValue("username", self.username.text())
settings.setValue("password", self.password.text())
QDialog.accept(self)
settings.setValue("audio_type", self.type.currentIndex)
settings.setValue("username", self.username.text)
settings.setValue("password", self.password.text)

View File

@ -2,8 +2,8 @@ import clementine
from servicebase import DigitallyImportedServiceBase
from PyQt4.QtCore import QSettings, QString, QUrl
from PyQt4.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
from PythonQt.QtCore import QSettings, QUrl
from PythonQt.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
import re
@ -30,8 +30,8 @@ class SkyFmService(DigitallyImportedServiceBase):
{"premium": True, "url": "http://listen.sky.fm/premium_wma/%s.asx?hash=%s"},
]
def __init__(self, model):
DigitallyImportedServiceBase.__init__(self, model)
def __init__(self, model, settings_dialog_callback):
DigitallyImportedServiceBase.Init(self, model, settings_dialog_callback)
self.last_key = None
@ -48,7 +48,7 @@ class SkyFmService(DigitallyImportedServiceBase):
QUrl.toPercentEncoding(self.password))
reply = self.network.post(request, postdata)
reply.finished.connect(self.LoadHashKeyFinished)
reply.connect("finished()", self.LoadHashKeyFinished)
self.last_key = key
@ -58,7 +58,7 @@ class SkyFmService(DigitallyImportedServiceBase):
reply.deleteLater()
# Parse the hashKey out of the reply
data = QString.fromUtf8(reply.readAll())
data = reply.readAll()
match = self.HASHKEY_RE.search(data)
if match:
@ -82,5 +82,5 @@ class SkyFmService(DigitallyImportedServiceBase):
# Start fetching the playlist. Can't use a SongLoader to do this because
# we have to use the cookies we set in ReloadSettings()
reply = self.network.get(QNetworkRequest(QUrl(playlist_url)))
reply.finished.connect(self.LoadPlaylistFinished)
self.load_station_reply = self.network.get(QNetworkRequest(QUrl(playlist_url)))
self.load_station_reply.connect("finished()", self.LoadPlaylistFinished)