206 lines
6.8 KiB
Python
206 lines
6.8 KiB
Python
import common
|
|
|
|
import clementine
|
|
|
|
from PyQt4.QtCore import QSettings, QUrl
|
|
from PyQt4.QtGui import QAction, QDesktopServices, QIcon, QMenu, \
|
|
QStandardItem
|
|
from PyQt4.QtNetwork import QNetworkCookie, QNetworkCookieJar, QNetworkRequest
|
|
import PyQt4.QtCore
|
|
|
|
import json
|
|
import operator
|
|
import os.path
|
|
|
|
class DigitallyImportedService(clementine.RadioService):
|
|
SERVICE_NAME = "digitally_imported"
|
|
HOMEPAGE_URL = QUrl("http://www.di.fm/")
|
|
STREAM_LIST_URL = QUrl("http://listen.di.fm/")
|
|
|
|
SettingsDialogRequested = PyQt4.QtCore.pyqtSignal()
|
|
|
|
def __init__(self, model):
|
|
clementine.RadioService.__init__(self, self.SERVICE_NAME, model)
|
|
|
|
self.network = clementine.NetworkAccessManager(self)
|
|
self.path = os.path.dirname(__file__)
|
|
|
|
self.audio_type = 0
|
|
|
|
self.context_index = None
|
|
self.last_original_url = None
|
|
self.menu = None
|
|
self.root = None
|
|
self.song_loader = None
|
|
self.task_id = None
|
|
|
|
self.ReloadSettings()
|
|
|
|
def ReloadSettings(self):
|
|
settings = QSettings()
|
|
settings.beginGroup(self.SERVICE_NAME)
|
|
|
|
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):
|
|
self.root = QStandardItem(QIcon(os.path.join(self.path, "icon-small.png")),
|
|
"Digitally Imported")
|
|
self.root.setData(True, clementine.RadioModel.Role_CanLazyLoad)
|
|
return self.root
|
|
|
|
def LazyPopulate(self, parent):
|
|
if parent == self.root:
|
|
# Download the list of streams the first time the user expands the root
|
|
self.RefreshStreams()
|
|
|
|
def ShowContextMenu(self, index, global_pos):
|
|
if not self.menu:
|
|
self.menu = QMenu()
|
|
self.menu.addAction(clementine.IconLoader.Load("media-playback-start"),
|
|
self.tr("Add to playlist"), self.AddToPlaylist)
|
|
self.menu.addAction(clementine.IconLoader.Load("media-playback-start"),
|
|
self.tr("Load"), self.LoadToPlaylist)
|
|
|
|
self.menu.addSeparator()
|
|
|
|
self.menu.addAction(clementine.IconLoader.Load("download"),
|
|
self.tr("Open www.di.fm in browser"), self.Homepage)
|
|
self.menu.addAction(clementine.IconLoader.Load("view-refresh"),
|
|
self.tr("Refresh streams"), self.RefreshStreams)
|
|
|
|
self.menu.addSeparator()
|
|
|
|
self.menu.addAction(clementine.IconLoader.Load("configure"),
|
|
self.tr("Configure Digitally Imported..."), self.SettingsDialogRequested.emit)
|
|
|
|
self.context_index = index
|
|
self.menu.popup(global_pos)
|
|
|
|
def AddToPlaylist(self):
|
|
print "Add to playlist"
|
|
|
|
def LoadToPlaylist(self):
|
|
print "Load to playlist"
|
|
|
|
def Homepage(self):
|
|
QDesktopServices.openUrl(self.HOMEPAGE_URL)
|
|
|
|
def RefreshStreams(self):
|
|
if self.task_id is not None:
|
|
return
|
|
|
|
# Request the list of stations
|
|
reply = self.network.get(QNetworkRequest(self.STREAM_LIST_URL))
|
|
reply.finished.connect(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()
|
|
reply.deleteLater()
|
|
|
|
if self.task_id is None:
|
|
return
|
|
|
|
# Stop the spinner in the status bar
|
|
clementine.task_manager.SetTaskFinished(self.task_id)
|
|
self.task_id = None
|
|
|
|
# Read the data and parse the json object inside
|
|
json_data = reply.readAll().data()
|
|
streams = json.loads(json_data)
|
|
|
|
# Sort by name
|
|
streams = sorted(streams, key=operator.itemgetter("name"))
|
|
|
|
# Now we have the list of streams, so clear any existing items in the list
|
|
# and insert the new ones
|
|
if self.root.hasChildren():
|
|
self.root.removeRows(0, self.root.rowCount())
|
|
|
|
for stream in streams:
|
|
item = QStandardItem(QIcon(":last.fm/icon_radio.png"), stream["name"])
|
|
item.setData(stream["description"], PyQt4.QtCore.Qt.ToolTipRole)
|
|
item.setData("digitallyimported://%s" % stream["key"], clementine.RadioModel.Role_Url)
|
|
item.setData(clementine.RadioModel.PlayBehaviour_SingleItem, clementine.RadioModel.Role_PlayBehaviour)
|
|
item.setData(stream["name"], clementine.RadioModel.Role_Title)
|
|
item.setData("Digitally Imported", clementine.RadioModel.Role_Artist)
|
|
self.root.appendRow(item)
|
|
|
|
def playlistitem_options(self):
|
|
return clementine.PlaylistItem.Options(
|
|
clementine.PlaylistItem.SpecialPlayBehaviour |
|
|
clementine.PlaylistItem.PauseDisabled)
|
|
|
|
def StartLoading(self, original_url):
|
|
result = clementine.PlaylistItem.SpecialLoadResult()
|
|
|
|
if self.task_id is not None:
|
|
return result
|
|
if original_url.scheme() != "digitallyimported":
|
|
return result
|
|
|
|
key = original_url.host()
|
|
playlist_url = common.PLAYLISTS[self.audio_type]["url"] % key
|
|
|
|
# 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)
|
|
|
|
# Save the original URL so we can emit it in the finished signal later
|
|
self.last_original_url = original_url
|
|
|
|
# Tell the user what's happening
|
|
self.task_id = clementine.task_manager.StartTask(self.tr("Loading stream"))
|
|
|
|
result.type_ = clementine.PlaylistItem.SpecialLoadResult.WillLoadAsynchronously
|
|
result.original_url_ = original_url
|
|
return result
|
|
|
|
def LoadPlaylistFinished(self):
|
|
# Get the QNetworkReply that called this slot
|
|
reply = self.sender()
|
|
reply.deleteLater()
|
|
|
|
if self.task_id is None:
|
|
return
|
|
|
|
# Stop the spinner in the status bar
|
|
clementine.task_manager.SetTaskFinished(self.task_id)
|
|
self.task_id = None
|
|
|
|
# Try to parse the playlist
|
|
parser = clementine.PlaylistParser(clementine.library)
|
|
songs = parser.Load(reply)
|
|
|
|
# Failed to get the playlist?
|
|
if len(songs) == 0:
|
|
self.StreamError.emit("Error loading playlist '%s'" % self.song_loader.url().toString())
|
|
return
|
|
|
|
result = clementine.PlaylistItem.SpecialLoadResult()
|
|
result.original_url_ = self.last_original_url
|
|
|
|
# Take the first track in the playlist
|
|
result.type_ = clementine.PlaylistItem.SpecialLoadResult.TrackAvailable
|
|
result.media_url_ = QUrl(songs[0].filename())
|
|
|
|
self.AsyncLoadFinished.emit(result)
|