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:
parent
5c1139747f
commit
ef1358e5aa
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue