Add c++ implementations of the di.fm and sky.fm radio services
This commit is contained in:
parent
b6ee23dc43
commit
a0258a9e81
|
@ -340,5 +340,8 @@
|
|||
<file>pythonlibs/uic/uiparser.py</file>
|
||||
<file>pythonlibs/clementinelogging.py</file>
|
||||
<file>nyancat.png</file>
|
||||
<file>providers/digitallyimported.png</file>
|
||||
<file>providers/skyfm.png</file>
|
||||
<file>providers/digitallyimported-32.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 211 B |
Binary file not shown.
After Width: | Height: | Size: 864 B |
|
@ -118,6 +118,10 @@ set(SOURCES
|
|||
engines/gstenginepipeline.cpp
|
||||
engines/gstelementdeleter.cpp
|
||||
|
||||
internet/digitallyimportedconfig.cpp
|
||||
internet/digitallyimportedservice.cpp
|
||||
internet/digitallyimportedservicebase.cpp
|
||||
internet/digitallyimportedurlhandler.cpp
|
||||
internet/icecastbackend.cpp
|
||||
internet/icecastfilterwidget.cpp
|
||||
internet/icecastmodel.cpp
|
||||
|
@ -136,6 +140,7 @@ set(SOURCES
|
|||
internet/magnatuneservice.cpp
|
||||
internet/magnatuneurlhandler.cpp
|
||||
internet/savedradio.cpp
|
||||
internet/skyfmservice.cpp
|
||||
internet/somafmservice.cpp
|
||||
internet/somafmurlhandler.cpp
|
||||
|
||||
|
@ -346,6 +351,8 @@ set(HEADERS
|
|||
engines/gstenginepipeline.h
|
||||
engines/gstelementdeleter.h
|
||||
|
||||
internet/digitallyimportedconfig.h
|
||||
internet/digitallyimportedservicebase.h
|
||||
internet/icecastbackend.h
|
||||
internet/icecastfilterwidget.h
|
||||
internet/icecastmodel.h
|
||||
|
@ -361,6 +368,7 @@ set(HEADERS
|
|||
internet/magnatunedownloaddialog.h
|
||||
internet/magnatuneservice.h
|
||||
internet/savedradio.h
|
||||
internet/skyfmservice.h
|
||||
internet/somafmservice.h
|
||||
internet/somafmurlhandler.h
|
||||
|
||||
|
@ -502,6 +510,7 @@ set(UI
|
|||
|
||||
devices/deviceproperties.ui
|
||||
|
||||
internet/digitallyimportedconfig.ui
|
||||
internet/icecastfilterwidget.ui
|
||||
internet/magnatuneconfig.ui
|
||||
internet/magnatunedownloaddialog.ui
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedconfig.h"
|
||||
#include "digitallyimportedservicebase.h"
|
||||
#include "ui_digitallyimportedconfig.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
|
||||
DigitallyImportedConfig::DigitallyImportedConfig(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
ui_(new Ui_DigitallyImportedConfig)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
DigitallyImportedConfig::~DigitallyImportedConfig() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void DigitallyImportedConfig::Load() {
|
||||
QSettings s;
|
||||
s.beginGroup(DigitallyImportedServiceBase::kSettingsGroup);
|
||||
|
||||
ui_->audio_type->setCurrentIndex(s.value("audio_type", 0).toInt());
|
||||
ui_->username->setText(s.value("username").toString());
|
||||
ui_->password->setText(s.value("password").toString());
|
||||
}
|
||||
|
||||
void DigitallyImportedConfig::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(DigitallyImportedServiceBase::kSettingsGroup);
|
||||
|
||||
s.setValue("audio_type", ui_->audio_type->currentIndex());
|
||||
s.setValue("username", ui_->username->text());
|
||||
s.setValue("password", ui_->password->text());
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIGITALLYIMPORTEDCONFIG_H
|
||||
#define DIGITALLYIMPORTEDCONFIG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class Ui_DigitallyImportedConfig;
|
||||
|
||||
class DigitallyImportedConfig : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DigitallyImportedConfig(QWidget* parent = 0);
|
||||
~DigitallyImportedConfig();
|
||||
|
||||
public slots:
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
Ui_DigitallyImportedConfig* ui_;
|
||||
};
|
||||
|
||||
#endif // DIGITALLYIMPORTEDCONFIG_H
|
|
@ -0,0 +1,162 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DigitallyImportedConfig</class>
|
||||
<widget class="QWidget" name="DigitallyImportedConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>715</width>
|
||||
<height>425</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Account details (Premium)</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Digitally Imported username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Digitally Imported password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>You can <b>listen for free</b> without an account, but Premium members can listen to <b>higher quality</b> streams without advertisements.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="upgrade_link">
|
||||
<property name="text">
|
||||
<string><a href="http://www.di.fm/premium/">Upgrade to Premium now</a></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Audio type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="audio_type">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MP3 96k</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MP3 256k (Premium only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AAC 32k</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AAC 64k (Premium only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AAC 128k (Premium only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Windows Media 40k</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Windows Media 64k (Premium only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Windows Media 128k (Premium only)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>166</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,64 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedservice.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkReply>
|
||||
|
||||
DigitallyImportedService::DigitallyImportedService(InternetModel* model, QObject* parent)
|
||||
: DigitallyImportedServiceBase(
|
||||
"DigitallyImported", "Digitally Imported", QUrl("http://www.di.fm"),
|
||||
"di.fm", QUrl("http://listen.di.fm"), "digitallyimported",
|
||||
QIcon(":/providers/digitallyimported.png"), model, parent)
|
||||
{
|
||||
playlists_ = QList<Playlist>()
|
||||
<< Playlist(false, "http://listen.di.fm/public3/%1.pls")
|
||||
<< Playlist(true, "http://www.di.fm/listen/%1/premium.pls")
|
||||
<< Playlist(false, "http://listen.di.fm/public2/%1.pls")
|
||||
<< Playlist(true, "http://www.di.fm/listen/%1/64k.pls")
|
||||
<< Playlist(true, "http://www.di.fm/listen/%1/128k.pls")
|
||||
<< Playlist(false, "http://listen.di.fm/public5/%1.asx")
|
||||
<< Playlist(true, "http://www.di.fm/listen/%1/64k.asx")
|
||||
<< Playlist(true, "http://www.di.fm/listen/%1/128k.asx");
|
||||
}
|
||||
|
||||
void DigitallyImportedService::ReloadSettings() {
|
||||
DigitallyImportedServiceBase::ReloadSettings();
|
||||
|
||||
QNetworkCookieJar* cookies = new QNetworkCookieJar;
|
||||
|
||||
if (is_premium_account()) {
|
||||
qLog(Debug) << "Setting premium account cookies";
|
||||
cookies->setCookiesFromUrl(QList<QNetworkCookie>()
|
||||
<< QNetworkCookie("_amember_ru", username_.toUtf8())
|
||||
<< QNetworkCookie("_amember_rp", password_.toUtf8()),
|
||||
QUrl("http://www.di.fm/"));
|
||||
}
|
||||
|
||||
network_->setCookieJar(cookies);
|
||||
}
|
||||
|
||||
void DigitallyImportedService::LoadStation(const QString& key) {
|
||||
QUrl playlist_url(playlists_[audio_type_].url_template_.arg(key));
|
||||
qLog(Debug) << "Getting playlist URL" << playlist_url;
|
||||
|
||||
QNetworkReply* reply = network_->get(QNetworkRequest(playlist_url));
|
||||
connect(reply, SIGNAL(finished()), SLOT(LoadPlaylistFinished()));
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIGITALLYIMPORTEDSERVICE_H
|
||||
#define DIGITALLYIMPORTEDSERVICE_H
|
||||
|
||||
#include "digitallyimportedservicebase.h"
|
||||
|
||||
class DigitallyImportedService : public DigitallyImportedServiceBase {
|
||||
public:
|
||||
DigitallyImportedService(InternetModel* model, QObject* parent = NULL);
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
void LoadStation(const QString& key);
|
||||
};
|
||||
|
||||
#endif // DIGITALLYIMPORTEDSERVICE_H
|
|
@ -0,0 +1,221 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedservicebase.h"
|
||||
#include "digitallyimportedurlhandler.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
#include "core/player.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QMenu>
|
||||
#include <QNetworkReply>
|
||||
#include <QSettings>
|
||||
|
||||
const char* DigitallyImportedServiceBase::kSettingsGroup = "digitally_imported";
|
||||
|
||||
|
||||
DigitallyImportedServiceBase::DigitallyImportedServiceBase(
|
||||
const QString& name, const QString& description, const QUrl& homepage_url,
|
||||
const QString& homepage_name, const QUrl& stream_list_url,
|
||||
const QString& url_scheme, const QIcon& icon,
|
||||
InternetModel* model, QObject* parent)
|
||||
: InternetService(name, model, parent),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
url_handler_(new DigitallyImportedUrlHandler(this)),
|
||||
audio_type_(0),
|
||||
task_id_(-1),
|
||||
homepage_url_(homepage_url),
|
||||
homepage_name_(homepage_name),
|
||||
stream_list_url_(stream_list_url),
|
||||
icon_(icon),
|
||||
service_description_(description),
|
||||
url_scheme_(url_scheme),
|
||||
root_(NULL),
|
||||
context_menu_(NULL),
|
||||
context_item_(NULL)
|
||||
{
|
||||
model->player()->RegisterUrlHandler(url_handler_);
|
||||
}
|
||||
|
||||
DigitallyImportedServiceBase::~DigitallyImportedServiceBase() {
|
||||
delete context_menu_;
|
||||
}
|
||||
|
||||
QStandardItem* DigitallyImportedServiceBase::CreateRootItem() {
|
||||
root_ = new QStandardItem(icon_, service_description_);
|
||||
root_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
return root_;
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::LazyPopulate(QStandardItem* parent) {
|
||||
if (parent == root_) {
|
||||
RefreshStreams();
|
||||
}
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::RefreshStreams() {
|
||||
if (task_id_ != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
qLog(Info) << "Getting stream list from" << stream_list_url_;
|
||||
|
||||
// Get the list of streams
|
||||
QNetworkReply* reply = network_->get(QNetworkRequest(stream_list_url_));
|
||||
connect(reply, SIGNAL(finished()), SLOT(RefreshStreamsFinished()));
|
||||
|
||||
// Start a task to tell the user we're busy
|
||||
task_id_ = model()->task_manager()->StartTask(tr("Getting streams"));
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::RefreshStreamsFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) {
|
||||
return;
|
||||
}
|
||||
|
||||
model()->task_manager()->SetTaskFinished(task_id_);
|
||||
reply->deleteLater();
|
||||
|
||||
const QString data = QString::fromUtf8(reply->readAll());
|
||||
|
||||
// Poor man's JSON parser that's good enough for the stream lists and means
|
||||
// we don't have to pull in QJSON as a dependency.
|
||||
const QRegExp re("\\{"
|
||||
"\"id\":(\\d+),"
|
||||
"\"key\":\"([^\"]+)\","
|
||||
"\"name\":\"([^\"]+)\","
|
||||
"\"description\":\"([^\"]+)\"");
|
||||
|
||||
QList<Stream> streams;
|
||||
|
||||
int pos = 0;
|
||||
while (pos >= 0) {
|
||||
pos = re.indexIn(data, pos);
|
||||
if (pos == -1) {
|
||||
break;
|
||||
}
|
||||
pos += re.matchedLength();
|
||||
|
||||
Stream stream;
|
||||
stream.id_ = re.cap(1).toInt();
|
||||
stream.key_ = re.cap(2).replace("\\/", "/");
|
||||
stream.name_ = re.cap(3).replace("\\/", "/");
|
||||
stream.description_ = re.cap(4).replace("\\/", "/");
|
||||
streams << stream;
|
||||
}
|
||||
|
||||
// Sort by name
|
||||
qSort(streams);
|
||||
|
||||
// Add each stream to the model
|
||||
foreach (const Stream& stream, streams) {
|
||||
Song song;
|
||||
song.set_title(stream.name_);
|
||||
song.set_artist(service_description_);
|
||||
song.set_url(QUrl(url_scheme_ + "://" + stream.key_));
|
||||
|
||||
QStandardItem* item = new QStandardItem(QIcon(":/last.fm/icon_radio.png"),
|
||||
stream.name_);
|
||||
item->setData(stream.description_, Qt::ToolTipRole);
|
||||
item->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour);
|
||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
root_->appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::Homepage() {
|
||||
QDesktopServices::openUrl(homepage_url_);
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::ReloadSettings() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
audio_type_ = s.value("audio_type", 0).toInt();
|
||||
username_ = s.value("username").toString();
|
||||
password_ = s.value("password").toString();
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::ShowContextMenu(
|
||||
const QModelIndex& index, const QPoint& global_pos) {
|
||||
if (!context_menu_) {
|
||||
context_menu_ = new QMenu;
|
||||
context_menu_->addActions(GetPlaylistActions());
|
||||
context_menu_->addAction(IconLoader::Load("download"),
|
||||
tr("Open %1 in browser").arg(homepage_name_),
|
||||
this, SLOT(Homepage()));
|
||||
context_menu_->addAction(IconLoader::Load("view-refresh"),
|
||||
tr("Refresh streams"),
|
||||
this, SLOT(RefreshStreams()));
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addAction(IconLoader::Load("configure"),
|
||||
tr("Configure..."),
|
||||
this, SLOT(ShowSettingsDialog()));
|
||||
}
|
||||
|
||||
context_item_ = model()->itemFromIndex(index);
|
||||
context_menu_->popup(global_pos);
|
||||
}
|
||||
|
||||
QModelIndex DigitallyImportedServiceBase::GetCurrentIndex() {
|
||||
return context_item_->index();
|
||||
}
|
||||
|
||||
bool DigitallyImportedServiceBase::is_valid_stream_selected() const {
|
||||
return audio_type_ >= 0 && audio_type_ < playlists_.count();
|
||||
}
|
||||
|
||||
bool DigitallyImportedServiceBase::is_premium_account() const {
|
||||
return !username_.isEmpty() && !password_.isEmpty();
|
||||
}
|
||||
|
||||
bool DigitallyImportedServiceBase::is_premium_stream_selected() const {
|
||||
if (!is_valid_stream_selected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return playlists_[audio_type_].premium_;
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::LoadPlaylistFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) {
|
||||
return;
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->header(QNetworkRequest::ContentTypeHeader).toString() == "text/html") {
|
||||
url_handler_->CancelTask();
|
||||
|
||||
if (is_premium_stream_selected()) {
|
||||
emit StreamError(tr("Invalid di.fm username or password"));
|
||||
} else {
|
||||
emit StreamError(tr("Error loading di.fm playlist"));
|
||||
}
|
||||
} else {
|
||||
url_handler_->LoadPlaylistFinished(reply);
|
||||
}
|
||||
}
|
||||
|
||||
void DigitallyImportedServiceBase::ShowSettingsDialog() {
|
||||
emit OpenSettingsAtPage(SettingsDialog::Page_DigitallyImported);
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIGITALLYIMPORTEDSERVICEBASE_H
|
||||
#define DIGITALLYIMPORTEDSERVICEBASE_H
|
||||
|
||||
#include "internetservice.h"
|
||||
|
||||
class DigitallyImportedUrlHandler;
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
|
||||
class DigitallyImportedServiceBase : public InternetService {
|
||||
Q_OBJECT
|
||||
friend class DigitallyImportedUrlHandler;
|
||||
|
||||
public:
|
||||
DigitallyImportedServiceBase(
|
||||
const QString& name, const QString& description, const QUrl& homepage_url,
|
||||
const QString& homepage_name, const QUrl& stream_list_url,
|
||||
const QString& url_scheme, const QIcon& icon,
|
||||
InternetModel* model, QObject* parent = NULL);
|
||||
~DigitallyImportedServiceBase();
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
QStandardItem* CreateRootItem();
|
||||
void LazyPopulate(QStandardItem* parent);
|
||||
void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos);
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
bool is_valid_stream_selected() const;
|
||||
bool is_premium_stream_selected() const;
|
||||
bool is_premium_account() const;
|
||||
|
||||
protected:
|
||||
struct Playlist {
|
||||
Playlist(bool premium, const QString& url_template)
|
||||
: premium_(premium), url_template_(url_template) {}
|
||||
|
||||
bool premium_;
|
||||
QString url_template_;
|
||||
};
|
||||
|
||||
QModelIndex GetCurrentIndex();
|
||||
|
||||
// Called by DigitallyImportedUrlHandler, implemented by subclasses, must
|
||||
// call LoadPlaylistFinished eventually.
|
||||
virtual void LoadStation(const QString& key) = 0;
|
||||
|
||||
protected slots:
|
||||
void LoadPlaylistFinished();
|
||||
|
||||
private slots:
|
||||
void Homepage();
|
||||
void RefreshStreams();
|
||||
void RefreshStreamsFinished();
|
||||
void ShowSettingsDialog();
|
||||
|
||||
protected:
|
||||
QNetworkAccessManager* network_;
|
||||
DigitallyImportedUrlHandler* url_handler_;
|
||||
|
||||
int audio_type_;
|
||||
QString username_;
|
||||
QString password_;
|
||||
|
||||
int task_id_;
|
||||
|
||||
QList<Playlist> playlists_;
|
||||
|
||||
private:
|
||||
struct Stream {
|
||||
int id_;
|
||||
QString key_;
|
||||
QString name_;
|
||||
QString description_;
|
||||
|
||||
bool operator <(const Stream& other) const { return name_ < other.name_; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Set by subclasses through the constructor
|
||||
QUrl homepage_url_;
|
||||
QString homepage_name_;
|
||||
QUrl stream_list_url_;
|
||||
QIcon icon_;
|
||||
QString service_description_;
|
||||
QString url_scheme_;
|
||||
|
||||
QStandardItem* root_;
|
||||
|
||||
QMenu* context_menu_;
|
||||
QStandardItem* context_item_;
|
||||
};
|
||||
|
||||
#endif // DIGITALLYIMPORTEDSERVICEBASE_H
|
|
@ -0,0 +1,96 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedservicebase.h"
|
||||
#include "digitallyimportedurlhandler.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
|
||||
DigitallyImportedUrlHandler::DigitallyImportedUrlHandler(DigitallyImportedServiceBase* service)
|
||||
: UrlHandler(service),
|
||||
service_(service),
|
||||
task_id_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
QString DigitallyImportedUrlHandler::scheme() const {
|
||||
return service_->url_scheme_;
|
||||
}
|
||||
|
||||
UrlHandler_LoadResult DigitallyImportedUrlHandler::StartLoading(const QUrl& url) {
|
||||
UrlHandler_LoadResult ret(url);
|
||||
if (task_id_ != -1) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!service_->is_valid_stream_selected()) {
|
||||
service_->StreamError(tr("You have selected an invalid audio type setting"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (service_->is_premium_stream_selected() && !service_->is_premium_account()) {
|
||||
service_->StreamError(tr("You have selected a Premium-only audio type but do not have any account details entered"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Start loading the station
|
||||
const QString key = url.host();
|
||||
qLog(Info) << "Loading station" << key;
|
||||
service_->LoadStation(key);
|
||||
|
||||
// Save the URL so we can emit it in the finished signal later
|
||||
last_original_url_ = url;
|
||||
|
||||
// Tell the user what's happening
|
||||
task_id_ = service_->model()->task_manager()->StartTask(tr("Loading stream"));
|
||||
|
||||
ret.type_ = UrlHandler_LoadResult::WillLoadAsynchronously;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DigitallyImportedUrlHandler::LoadPlaylistFinished(QIODevice* device) {
|
||||
if (task_id_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop the spinner in the status bar
|
||||
CancelTask();
|
||||
|
||||
// Try to parse the playlist
|
||||
PlaylistParser parser(NULL);
|
||||
QList<Song> songs = parser.LoadFromDevice(device);
|
||||
|
||||
qLog(Info) << "Loading station finished, got" << songs.count() << "songs";
|
||||
|
||||
// Failed to get playlist?
|
||||
if (songs.count() == 0) {
|
||||
service_->StreamError(tr("Error loading di.fm playlist"));
|
||||
return;
|
||||
}
|
||||
|
||||
emit AsyncLoadComplete(UrlHandler_LoadResult(
|
||||
last_original_url_,
|
||||
UrlHandler_LoadResult::TrackAvailable,
|
||||
songs[0].url()));
|
||||
}
|
||||
|
||||
void DigitallyImportedUrlHandler::CancelTask() {
|
||||
service_->model()->task_manager()->SetTaskFinished(task_id_);
|
||||
task_id_ = -1;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DIGITALLYIMPORTEDURLHANDLER_H
|
||||
#define DIGITALLYIMPORTEDURLHANDLER_H
|
||||
|
||||
#include "core/urlhandler.h"
|
||||
|
||||
class DigitallyImportedServiceBase;
|
||||
|
||||
|
||||
class DigitallyImportedUrlHandler : public UrlHandler {
|
||||
public:
|
||||
DigitallyImportedUrlHandler(DigitallyImportedServiceBase* service);
|
||||
|
||||
QString scheme() const;
|
||||
UrlHandler_LoadResult StartLoading(const QUrl& url);
|
||||
|
||||
void CancelTask();
|
||||
void LoadPlaylistFinished(QIODevice* device);
|
||||
|
||||
private:
|
||||
DigitallyImportedServiceBase* service_;
|
||||
int task_id_;
|
||||
|
||||
QUrl last_original_url_;
|
||||
};
|
||||
|
||||
#endif // DIGITALLYIMPORTEDURLHANDLER_H
|
|
@ -15,6 +15,7 @@
|
|||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedservice.h"
|
||||
#include "icecastservice.h"
|
||||
#include "jamendoservice.h"
|
||||
#include "magnatuneservice.h"
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include "internetmodel.h"
|
||||
#include "internetservice.h"
|
||||
#include "savedradio.h"
|
||||
#include "skyfmservice.h"
|
||||
#include "somafmservice.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mergedproxymodel.h"
|
||||
|
@ -54,17 +56,19 @@ InternetModel::InternetModel(BackgroundThread<Database>* db_thread,
|
|||
|
||||
merged_model_->setSourceModel(this);
|
||||
|
||||
AddService(new DigitallyImportedService(this));
|
||||
AddService(new IcecastService(this));
|
||||
AddService(new JamendoService(this));
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
AddService(new LastFMService(this));
|
||||
#endif
|
||||
#ifdef HAVE_SPOTIFY
|
||||
AddService(new SpotifyService(task_manager, this));
|
||||
#endif
|
||||
AddService(new SomaFMService(this));
|
||||
AddService(new MagnatuneService(this));
|
||||
AddService(new JamendoService(this));
|
||||
AddService(new IcecastService(this));
|
||||
AddService(new SavedRadio(this));
|
||||
AddService(new SkyFmService(this));
|
||||
AddService(new SomaFMService(this));
|
||||
#ifdef HAVE_SPOTIFY
|
||||
AddService(new SpotifyService(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
void InternetModel::AddService(InternetService *service) {
|
||||
|
@ -86,6 +90,8 @@ void InternetModel::AddService(InternetService *service) {
|
|||
connect(service, SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)), SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)));
|
||||
connect(service, SIGNAL(AddToPlaylistSignal(QMimeData*)), SIGNAL(AddToPlaylist(QMimeData*)));
|
||||
connect(service, SIGNAL(destroyed()), SLOT(ServiceDeleted()));
|
||||
|
||||
service->ReloadSettings();
|
||||
}
|
||||
|
||||
void InternetModel::RemoveService(InternetService* service) {
|
||||
|
|
|
@ -84,7 +84,6 @@ LastFMService::LastFMService(InternetModel* parent)
|
|||
neighbours_list_(NULL),
|
||||
connection_problems_(false)
|
||||
{
|
||||
ReloadSettings();
|
||||
//we emit the signal the first time to be sure the buttons are in the right state
|
||||
emit ScrobblingEnabledChanged(scrobbling_enabled_);
|
||||
|
||||
|
|
|
@ -76,8 +76,6 @@ MagnatuneService::MagnatuneService(InternetModel* parent)
|
|||
total_song_count_(0),
|
||||
network_(new NetworkAccessManager(this))
|
||||
{
|
||||
ReloadSettings();
|
||||
|
||||
// Create the library backend in the database thread
|
||||
library_backend_ = new LibraryBackend;
|
||||
library_backend_->moveToThread(parent->db_thread());
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "digitallyimportedurlhandler.h"
|
||||
#include "internetmodel.h"
|
||||
#include "skyfmservice.h"
|
||||
#include "core/taskmanager.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
SkyFmService::SkyFmService(InternetModel* model, QObject* parent)
|
||||
: DigitallyImportedServiceBase(
|
||||
"SKY.fm", "SKY.fm", QUrl("http://www.sky.fm"), "sky.fm",
|
||||
QUrl("http://listen.sky.fm"), "skyfm", QIcon(":/providers/skyfm.png"),
|
||||
model, parent)
|
||||
{
|
||||
playlists_ = QList<Playlist>()
|
||||
<< Playlist(false, "http://listen.sky.fm/public3/%1.pls")
|
||||
<< Playlist(true, "http://listen.sky.fm/premium_high/%1.pls?hash=%2")
|
||||
<< Playlist(false, "http://listen.sky.fm/public1/%1.pls")
|
||||
<< Playlist(true, "http://listen.sky.fm/premium_medium/%1.pls?hash=%2")
|
||||
<< Playlist(true, "http://listen.sky.fm/premium/%1.pls?hash=%2")
|
||||
<< Playlist(false, "http://listen.sky.fm/public5/%1.asx")
|
||||
<< Playlist(true, "http://listen.sky.fm/premium_wma_low/%1.asx?hash=%2")
|
||||
<< Playlist(true, "http://listen.sky.fm/premium_wma/%1.asx?hash=%2");
|
||||
}
|
||||
|
||||
void SkyFmService::LoadStation(const QString& key) {
|
||||
if (!is_premium_stream_selected()) {
|
||||
// Non-premium streams can just start loading straight away
|
||||
LoadPlaylist(key);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we have to get the user's hashKey
|
||||
QNetworkRequest req(QUrl("http://www.sky.fm/configure_player.php"));
|
||||
QByteArray postdata = "amember_login=" + QUrl::toPercentEncoding(username_) +
|
||||
"&amember_pass=" + QUrl::toPercentEncoding(password_);
|
||||
|
||||
QNetworkReply* reply = network_->post(req, postdata);
|
||||
connect(reply, SIGNAL(finished()), SLOT(LoadHashKeyFinished()));
|
||||
|
||||
last_key_ = key;
|
||||
}
|
||||
|
||||
void SkyFmService::LoadHashKeyFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (!reply) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString page_data = QString::fromUtf8(reply->readAll().data());
|
||||
QRegExp re("hashKey\\s*=\\s*'([0-9a-f]+)'");
|
||||
|
||||
if (re.indexIn(page_data) == -1) {
|
||||
url_handler_->CancelTask();
|
||||
emit StreamError(tr("Invalid SKY.fm username or password"));
|
||||
return;
|
||||
}
|
||||
|
||||
LoadPlaylist(last_key_, re.cap(1));
|
||||
}
|
||||
|
||||
void SkyFmService::LoadPlaylist(const QString& key, const QString& hash_key) {
|
||||
QString url_template = playlists_[audio_type_].url_template_;
|
||||
QUrl url;
|
||||
|
||||
if (hash_key.isEmpty()) {
|
||||
url = QUrl(url_template.arg(key));
|
||||
} else {
|
||||
url = QUrl(url_template.arg(key, hash_key));
|
||||
}
|
||||
|
||||
QNetworkReply* reply = network_->get(QNetworkRequest(url));
|
||||
connect(reply, SIGNAL(finished()), SLOT(LoadPlaylistFinished()));
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SKYFMSERVICE_H
|
||||
#define SKYFMSERVICE_H
|
||||
|
||||
#include "digitallyimportedservicebase.h"
|
||||
|
||||
class SkyFmService : public DigitallyImportedServiceBase {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SkyFmService(InternetModel* model, QObject* parent = NULL);
|
||||
|
||||
void LoadStation(const QString& key);
|
||||
|
||||
private:
|
||||
void LoadPlaylist(const QString& key, const QString& hash_key = QString());
|
||||
|
||||
private slots:
|
||||
void LoadHashKeyFinished();
|
||||
|
||||
private:
|
||||
QString last_key_;
|
||||
};
|
||||
|
||||
#endif // SKYFMSERVICE_H
|
|
@ -34,7 +34,7 @@ const char* SpotifyService::kSettingsGroup = "Spotify";
|
|||
const char* SpotifyService::kBlobDownloadUrl = "http://spotify.clementine-player.org/";
|
||||
const int SpotifyService::kSearchDelayMsec = 400;
|
||||
|
||||
SpotifyService::SpotifyService(TaskManager* task_manager, InternetModel* parent)
|
||||
SpotifyService::SpotifyService(InternetModel* parent)
|
||||
: InternetService(kServiceName, parent, parent),
|
||||
server_(NULL),
|
||||
url_handler_(new SpotifyUrlHandler(this, this)),
|
||||
|
@ -46,8 +46,7 @@ SpotifyService::SpotifyService(TaskManager* task_manager, InternetModel* parent)
|
|||
login_task_id_(0),
|
||||
pending_search_playlist_(NULL),
|
||||
context_menu_(NULL),
|
||||
search_delay_(new QTimer(this)),
|
||||
task_manager_(task_manager) {
|
||||
search_delay_(new QTimer(this)) {
|
||||
// Build the search path for the binary blob.
|
||||
// Look for one distributed alongside clementine first, then check in the
|
||||
// user's home directory for any that have been downloaded.
|
||||
|
@ -441,16 +440,16 @@ void SpotifyService::SyncPlaylist() {
|
|||
int index = item->data(Role_UserPlaylistIndex).toInt();
|
||||
server_->SyncUserPlaylist(index);
|
||||
playlist_sync_ids_[index] =
|
||||
task_manager_->StartTask(tr("Syncing Spotify playlist"));
|
||||
model()->task_manager()->StartTask(tr("Syncing Spotify playlist"));
|
||||
break;
|
||||
}
|
||||
case Type_InboxPlaylist:
|
||||
server_->SyncInbox();
|
||||
inbox_sync_id_ = task_manager_->StartTask(tr("Syncing Spotify inbox"));
|
||||
inbox_sync_id_ = model()->task_manager()->StartTask(tr("Syncing Spotify inbox"));
|
||||
break;
|
||||
case Type_StarredPlaylist:
|
||||
server_->SyncStarred();
|
||||
starred_sync_id_ = task_manager_->StartTask(tr("Syncing Spotify starred tracks"));
|
||||
starred_sync_id_ = model()->task_manager()->StartTask(tr("Syncing Spotify starred tracks"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -582,9 +581,9 @@ void SpotifyService::SyncPlaylistProgress(
|
|||
qLog(Warning) << "Received sync progress for unknown playlist";
|
||||
return;
|
||||
}
|
||||
task_manager_->SetTaskProgress(task_id, progress.sync_progress(), 100);
|
||||
model()->task_manager()->SetTaskProgress(task_id, progress.sync_progress(), 100);
|
||||
if (progress.sync_progress() == 100) {
|
||||
task_manager_->SetTaskFinished(task_id);
|
||||
model()->task_manager()->SetTaskFinished(task_id);
|
||||
if (progress.request().type() == protobuf::UserPlaylist) {
|
||||
playlist_sync_ids_.remove(task_id);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class SpotifyService : public InternetService {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SpotifyService(TaskManager* task_manager, InternetModel* parent);
|
||||
SpotifyService(InternetModel* parent);
|
||||
~SpotifyService();
|
||||
|
||||
enum Type {
|
||||
|
@ -119,7 +119,6 @@ private:
|
|||
|
||||
QTimer* search_delay_;
|
||||
|
||||
TaskManager* task_manager_;
|
||||
int inbox_sync_id_;
|
||||
int starred_sync_id_;
|
||||
QMap<int, int> playlist_sync_ids_;
|
||||
|
|
|
@ -468,6 +468,7 @@ void SettingsDialog::accept() {
|
|||
|
||||
ui_->library_config->Save();
|
||||
ui_->magnatune->Save();
|
||||
ui_->digitally_imported->Save();
|
||||
ui_->global_shortcuts->Save();
|
||||
|
||||
streams_->SaveStreams();
|
||||
|
@ -558,6 +559,9 @@ void SettingsDialog::showEvent(QShowEvent*) {
|
|||
// Magnatune
|
||||
ui_->magnatune->Load();
|
||||
|
||||
// Digitally Imported
|
||||
ui_->digitally_imported->Load();
|
||||
|
||||
// Global Shortcuts
|
||||
ui_->global_shortcuts->Load();
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ class SettingsDialog : public QDialog {
|
|||
Page_Spotify,
|
||||
#endif
|
||||
Page_Magnatune,
|
||||
Page_DigitallyImported,
|
||||
Page_BackgroundStreams,
|
||||
Page_Proxy,
|
||||
Page_Transcoding,
|
||||
|
|
|
@ -93,6 +93,15 @@
|
|||
<normaloff>:/providers/magnatune.png</normaloff>:/providers/magnatune.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Digitally Imported</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/providers/digitallyimported-32.png</normaloff>:/providers/digitallyimported-32.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Background Streams</string>
|
||||
|
@ -125,7 +134,7 @@
|
|||
<item>
|
||||
<widget class="QStackedWidget" name="stacked_widget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>7</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="playback_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
|
@ -1095,6 +1104,19 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="digitally_imported_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_27">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="DigitallyImportedConfig" name="digitally_imported" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="streams_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
|
@ -1564,6 +1586,12 @@
|
|||
<header>transcoder/transcoderoptionswma.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DigitallyImportedConfig</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>internet/digitallyimportedconfig.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>list</tabstop>
|
||||
|
|
Loading…
Reference in New Issue