diff --git a/data/data.qrc b/data/data.qrc index 3ea3e2eaa..c39bd5acb 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -350,6 +350,7 @@ providers/22x22/skydrive.png providers/22x22/somafm.png providers/22x22/intergalacticfm.png + providers/22x22/radiobrowser.png providers/22x22/songkick.png providers/22x22/soundcloud.png providers/22x22/spotify.png @@ -383,6 +384,7 @@ providers/32x32/skydrive.png providers/32x32/somafm.png providers/32x32/intergalacticfm.png + providers/32x32/radiobrowser.png providers/32x32/songkick.png providers/32x32/soundcloud.png providers/32x32/spotify.png @@ -416,6 +418,7 @@ providers/48x48/skydrive.png providers/48x48/somafm.png providers/48x48/intergalacticfm.png + providers/48x48/radiobrowser.png providers/48x48/songkick.png providers/48x48/soundcloud.png providers/48x48/spotify.png diff --git a/data/providers/22x22/radiobrowser.png b/data/providers/22x22/radiobrowser.png new file mode 100644 index 000000000..c88fa6be9 Binary files /dev/null and b/data/providers/22x22/radiobrowser.png differ diff --git a/data/providers/32x32/radiobrowser.png b/data/providers/32x32/radiobrowser.png new file mode 100644 index 000000000..8ff7fab11 Binary files /dev/null and b/data/providers/32x32/radiobrowser.png differ diff --git a/data/providers/48x48/radiobrowser.png b/data/providers/48x48/radiobrowser.png new file mode 100644 index 000000000..e6acbc669 Binary files /dev/null and b/data/providers/48x48/radiobrowser.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d5092d5a..93451d6a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -155,6 +155,7 @@ set(SOURCES globalsearch/simplesearchprovider.cpp globalsearch/somafmsearchprovider.cpp globalsearch/intergalacticfmsearchprovider.cpp + globalsearch/radiobrowsersearchprovider.cpp globalsearch/suggestionwidget.cpp globalsearch/urlsearchprovider.cpp @@ -191,6 +192,8 @@ set(SOURCES internet/somafm/somafmurlhandler.cpp internet/intergalacticfm/intergalacticfmservice.cpp internet/intergalacticfm/intergalacticfmurlhandler.cpp + internet/radiobrowser/radiobrowserservice.cpp + internet/radiobrowser/radiobrowserurlhandler.cpp internet/subsonic/subsonicservice.cpp internet/subsonic/subsonicsettingspage.cpp internet/subsonic/subsonicurlhandler.cpp @@ -506,6 +509,8 @@ set(HEADERS internet/somafm/somafmurlhandler.h internet/intergalacticfm/intergalacticfmservice.h internet/intergalacticfm/intergalacticfmurlhandler.h + internet/radiobrowser/radiobrowserservice.h + internet/radiobrowser/radiobrowserurlhandler.h internet/subsonic/subsonicservice.h internet/subsonic/subsonicsettingspage.h internet/subsonic/subsonicurlhandler.h diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index 232b4feb2..8312498b5 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -37,6 +37,7 @@ #include "internet/intergalacticfm/intergalacticfmservice.h" #include "internet/podcasts/podcast.h" #include "internet/podcasts/podcastepisode.h" +#include "internet/radiobrowser/radiobrowserservice.h" #include "internet/somafm/somafmservice.h" #include "library/directory.h" #include "playlist/playlist.h" @@ -98,6 +99,8 @@ void RegisterMetaTypes() { qRegisterMetaType("SomaFMService::Stream"); qRegisterMetaType( "IntergalacticFMService::Stream"); + qRegisterMetaType( + "RadioBrowserService::Stream"); qRegisterMetaType("SongList"); qRegisterMetaType("Song"); qRegisterMetaTypeStreamOperators( @@ -108,6 +111,8 @@ void RegisterMetaTypes() { "SomaFMService::Stream"); qRegisterMetaTypeStreamOperators( "IntergalacticFMService::Stream"); + qRegisterMetaTypeStreamOperators( + "RadioBrowserService::Stream"); qRegisterMetaType("SubdirectoryList"); qRegisterMetaType("Subdirectory"); qRegisterMetaType>("QList"); diff --git a/src/globalsearch/radiobrowsersearchprovider.cpp b/src/globalsearch/radiobrowsersearchprovider.cpp new file mode 100644 index 000000000..3bce35360 --- /dev/null +++ b/src/globalsearch/radiobrowsersearchprovider.cpp @@ -0,0 +1,52 @@ +/* This file is part of Clementine. + Copyright 2011, David Sansome + + 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 . +*/ + +#include "radiobrowsersearchprovider.h" + +RadioBrowserSearchProvider::RadioBrowserSearchProvider( + RadioBrowserServiceBase* service, Application* app, QObject* parent) + : SimpleSearchProvider(app, parent), service_(service) { + Init(service->name(), service->url_scheme(), service->icon(), + CanGiveSuggestions); + set_result_limit(3); + set_max_suggestion_count(3); + icon_ = ScaleAndPad( + service->icon().pixmap(service->icon().availableSizes()[0]).toImage()); + + connect(service, SIGNAL(StreamsChanged()), SLOT(MaybeRecreateItems())); + + // Load the stream list on startup only if it doesn't involve going to update + // info from the server. + if (!service_->IsStreamListStale()) RecreateItems(); +} + +void RadioBrowserSearchProvider::LoadArtAsync(int id, const Result& result) { + emit ArtLoaded(id, icon_); +} + +void RadioBrowserSearchProvider::RecreateItems() { + QList items; + + for (const RadioBrowserService::Stream& stream : service_->Streams()) { + Item item; + item.metadata_ = stream.ToSong(service_->name()); + item.keyword_ = stream.name_; + items << item; + } + + SetItems(items); +} diff --git a/src/globalsearch/radiobrowsersearchprovider.h b/src/globalsearch/radiobrowsersearchprovider.h new file mode 100644 index 000000000..479e67ba9 --- /dev/null +++ b/src/globalsearch/radiobrowsersearchprovider.h @@ -0,0 +1,42 @@ + +/* This file is part of Clementine. + Copyright 2011, David Sansome + + 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 . +*/ + +#ifndef RADIOBROWSERSEARCHPROVIDER_H +#define RADIOBROWSERSEARCHPROVIDER_H + +#include "internet/radiobrowser/radiobrowserservice.h" +#include "simplesearchprovider.h" + +class RadioBrowserSearchProvider : public SimpleSearchProvider { + public: + RadioBrowserSearchProvider(RadioBrowserServiceBase* service, + Application* app, QObject* parent); + // SearchProvider + InternetService* internet_service() override { return service_; } + + void LoadArtAsync(int id, const Result& result) override; + + protected: + void RecreateItems() override; + + private: + RadioBrowserServiceBase* service_; + QImage icon_; +}; + +#endif // RADIOBROWSERSEARCHPROVIDER_H diff --git a/src/internet/core/internetmodel.cpp b/src/internet/core/internetmodel.cpp index bba5ff400..8c1275c92 100644 --- a/src/internet/core/internetmodel.cpp +++ b/src/internet/core/internetmodel.cpp @@ -40,6 +40,7 @@ #include "internet/jamendo/jamendoservice.h" #include "internet/magnatune/magnatuneservice.h" #include "internet/podcasts/podcastservice.h" +#include "internet/radiobrowser/radiobrowserservice.h" #include "internet/somafm/somafmservice.h" #include "internet/subsonic/subsonicservice.h" #include "smartplaylists/generatormimedata.h" @@ -96,6 +97,7 @@ InternetModel::InternetModel(Application* app, QObject* parent) AddService(new RadioTunesService(app, this)); AddService(new SomaFMService(app, this)); AddService(new IntergalacticFMService(app, this)); + AddService(new RadioBrowserService(app, this)); #ifdef HAVE_SPOTIFY AddService(new SpotifyService(app, this)); #endif diff --git a/src/internet/radiobrowser/radiobrowserservice.cpp b/src/internet/radiobrowser/radiobrowserservice.cpp new file mode 100644 index 000000000..cb1a56648 --- /dev/null +++ b/src/internet/radiobrowser/radiobrowserservice.cpp @@ -0,0 +1,254 @@ +/* This file is part of Clementine. + Copyright 2010-2013, David Sansome + Copyright 2011, Tyler Rhodes + Copyright 2011, Paweł Bara + Copyright 2012, 2014, John Maguire + Copyright 2014, Krzysztof Sobiecki + + 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 . +*/ + +#include "radiobrowserservice.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/application.h" +#include "core/closure.h" +#include "core/logging.h" +#include "core/network.h" +#include "core/player.h" +#include "core/taskmanager.h" +#include "core/utilities.h" +#include "globalsearch/globalsearch.h" +#include "globalsearch/radiobrowsersearchprovider.h" +#include "radiobrowserurlhandler.h" +#include "internet/core/internetmodel.h" +#include "ui/iconloader.h" + +const int RadioBrowserServiceBase::kStreamsCacheDurationSecs = + 60 * 60 * 24 * 28; // 4 weeks + +bool operator<(const RadioBrowserServiceBase::Stream& a, + const RadioBrowserServiceBase::Stream& b) { + return a.name_.compare(b.name_, Qt::CaseInsensitive) < 0; +} + +RadioBrowserServiceBase::RadioBrowserServiceBase( + Application* app, InternetModel* parent, const QString& name, + const QUrl& channel_list_url, const QUrl& homepage_url, + const QUrl& donate_page_url, const QIcon& icon) + : InternetService(name, app, parent, parent), + url_scheme_(name.toLower().remove(' ')), + url_handler_(new RadioBrowserUrlHandler(app, this, this)), + root_(nullptr), + context_menu_(nullptr), + network_(new NetworkAccessManager(this)), + streams_(name, "streams", kStreamsCacheDurationSecs), + name_(name), + channel_list_url_(channel_list_url), + homepage_url_(homepage_url), + donate_page_url_(donate_page_url), + icon_(icon) { + ReloadSettings(); + + app_->player()->RegisterUrlHandler(url_handler_); + app_->global_search()->AddProvider( + new RadioBrowserSearchProvider(this, app_, this)); +} + +RadioBrowserServiceBase::~RadioBrowserServiceBase() { + delete context_menu_; +} + +QStandardItem* RadioBrowserServiceBase::CreateRootItem() { + root_ = new QStandardItem(icon_, name_); + root_->setData(true, InternetModel::Role_CanLazyLoad); + return root_; +} + +void RadioBrowserServiceBase::LazyPopulate(QStandardItem* item) { + switch (item->data(InternetModel::Role_Type).toInt()) { + case InternetModel::Type_Service: + RefreshStreams(); + break; + + default: + break; + } +} + +void RadioBrowserServiceBase::ShowContextMenu(const QPoint& global_pos) { + if (!context_menu_) { + context_menu_ = new QMenu; + context_menu_->addActions(GetPlaylistActions()); + context_menu_->addAction(IconLoader::Load("download", IconLoader::Base), + tr("Open %1 in browser").arg(homepage_url_.host()), + this, SLOT(Homepage())); + + if (!donate_page_url_.isEmpty()) { + context_menu_->addAction(IconLoader::Load("download", IconLoader::Base), + tr("Donate"), this, SLOT(Donate())); + } + + context_menu_->addAction(IconLoader::Load("view-refresh", IconLoader::Base), + tr("Refresh channels"), this, + SLOT(ForceRefreshStreams())); + } + + context_menu_->popup(global_pos); +} + +void RadioBrowserServiceBase::ForceRefreshStreams() { + QNetworkReply* reply = network_->get(QNetworkRequest(channel_list_url_)); + int task_id = app_->task_manager()->StartTask(tr("Getting channels")); + + NewClosure(reply, SIGNAL(finished()), this, + SLOT(RefreshStreamsFinished(QNetworkReply*, int)), reply, task_id); +} + +void RadioBrowserServiceBase::RefreshStreamsFinished(QNetworkReply* reply, + int task_id) { + app_->task_manager()->SetTaskFinished(task_id); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + app_->AddError( + tr("Failed to get channel list:\n%1").arg(reply->errorString())); + return; + } + + StreamList list; + + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { + app_->AddError( + tr("Failed to parse channel list:\n%1").arg(error.errorString())); + return; + } + + QJsonArray contents = document.array(); + qLog(Debug) << "RadioBrowser station list found:" << contents.size(); + for (const QJsonValue& c : contents) { + QJsonObject item = c.toObject(); + ReadStation(item, &list); + } + + streams_.Update(list); + streams_.Sort(); + + // Only update the item's children if it's already been populated + if (!root_->data(InternetModel::Role_CanLazyLoad).toBool()) PopulateStreams(); + + emit StreamsChanged(); +} + +void RadioBrowserServiceBase::ReadStation(QJsonObject& item, + StreamList* ret) { + Stream stream; + stream.name_ = item["name"].toString(); + QUrl url(item["url"].toString()); + stream.url_ = url; + ret->append(stream); +} + +Song RadioBrowserServiceBase::Stream::ToSong(const QString& prefix) const { + QString song_title = name_.trimmed(); + if (!song_title.startsWith(prefix)) { + song_title = prefix + " " + song_title; + } + + Song ret; + ret.set_valid(true); + ret.set_title(song_title); + ret.set_artist(name_); + ret.set_url(url_); + return ret; +} + +void RadioBrowserServiceBase::Homepage() { + QDesktopServices::openUrl(homepage_url_); +} + +void RadioBrowserServiceBase::Donate() { + QDesktopServices::openUrl(donate_page_url_); +} + +PlaylistItem::Options RadioBrowserServiceBase::playlistitem_options() const { + return PlaylistItem::PauseDisabled; +} + +RadioBrowserServiceBase::StreamList RadioBrowserServiceBase::Streams() { + if (IsStreamListStale()) { + metaObject()->invokeMethod(this, "ForceRefreshStreams", + Qt::QueuedConnection); + } + return streams_; +} + +void RadioBrowserServiceBase::RefreshStreams() { + if (IsStreamListStale()) { + ForceRefreshStreams(); + return; + } + PopulateStreams(); +} + +void RadioBrowserServiceBase::PopulateStreams() { + if (root_->hasChildren()) root_->removeRows(0, root_->rowCount()); + + for (const Stream& stream : streams_) { + QStandardItem* item = new QStandardItem( + IconLoader::Load("icon_radio", IconLoader::Lastfm), QString()); + item->setText(stream.name_); + item->setData(QVariant::fromValue(stream.ToSong(name_)), + InternetModel::Role_SongMetadata); + item->setData(InternetModel::PlayBehaviour_SingleItem, + InternetModel::Role_PlayBehaviour); + + root_->appendRow(item); + } +} + +QDataStream& operator<<(QDataStream& out, + const RadioBrowserServiceBase::Stream& stream) { + out << stream.name_ << stream.url_; + return out; +} + +QDataStream& operator>>(QDataStream& in, + RadioBrowserServiceBase::Stream& stream) { + in >> stream.name_ >> stream.url_; + return in; +} + +void RadioBrowserServiceBase::ReloadSettings() { + streams_.Load(); + streams_.Sort(); +} + +RadioBrowserService::RadioBrowserService(Application* app, + InternetModel* parent) + : RadioBrowserServiceBase( + app, parent, "Radio-Browser.info", + QUrl("http://all.api.radio-browser.info/json/stations"), + QUrl("https://www.radio-browser.info"), QUrl(), + IconLoader::Load("radiobrowser", IconLoader::Provider)) {} diff --git a/src/internet/radiobrowser/radiobrowserservice.h b/src/internet/radiobrowser/radiobrowserservice.h new file mode 100644 index 000000000..153b882e4 --- /dev/null +++ b/src/internet/radiobrowser/radiobrowserservice.h @@ -0,0 +1,117 @@ +/* This file is part of Clementine. + Copyright 2010-2013, David Sansome + Copyright 2010, 2014, John Maguire + Copyright 2014, Krzysztof Sobiecki + + 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 . +*/ + +#ifndef INTERNET_RADIOBROWSER_RADIOBROWSERSERVICE_H_ +#define INTERNET_RADIOBROWSER_RADIOBROWSERSERVICE_H_ + +#include + +#include "core/cachedlist.h" +#include "internet/core/internetservice.h" + +class RadioBrowserUrlHandler; + +class QNetworkAccessManager; +class QNetworkReply; +class QMenu; + +class RadioBrowserServiceBase : public InternetService { + Q_OBJECT + + public: + RadioBrowserServiceBase(Application* app, InternetModel* parent, + const QString& name, const QUrl& channel_list_url, + const QUrl& homepage_url, + const QUrl& donate_page_url, const QIcon& icon); + ~RadioBrowserServiceBase(); + + enum ItemType { + Type_Stream = 2000, + }; + + struct Stream { + QString name_; + QUrl url_; + + Song ToSong(const QString& prefix) const; + }; + typedef QList StreamList; + + static const int kStreamsCacheDurationSecs; + + const QString& url_scheme() const { return url_scheme_; } + const QIcon& icon() const { return icon_; } + + QStandardItem* CreateRootItem(); + void LazyPopulate(QStandardItem* item); + void ShowContextMenu(const QPoint& global_pos); + + PlaylistItem::Options playlistitem_options() const; + QNetworkAccessManager* network() const { return network_; } + + void ReloadSettings(); + + bool IsStreamListStale() const { return streams_.IsStale(); } + StreamList Streams(); + + signals: + void StreamsChanged(); + + private slots: + void ForceRefreshStreams(); + void RefreshStreams(); + void RefreshStreamsFinished(QNetworkReply* reply, int task_id); + + void Homepage(); + void Donate(); + + private: + void ReadStation(QJsonObject& value, StreamList* ret); + void PopulateStreams(); + + private: + const QString url_scheme_; + RadioBrowserUrlHandler* url_handler_; + + QStandardItem* root_; + QMenu* context_menu_; + + QNetworkAccessManager* network_; + + CachedList streams_; + + const QString name_; + const QUrl channel_list_url_; + const QUrl homepage_url_; + const QUrl donate_page_url_; + const QIcon icon_; +}; + +class RadioBrowserService : public RadioBrowserServiceBase { + public: + RadioBrowserService(Application* app, InternetModel* parent); +}; + +QDataStream& operator<<(QDataStream& out, + const RadioBrowserService::Stream& stream); +QDataStream& operator>>(QDataStream& in, + RadioBrowserService::Stream& stream); +Q_DECLARE_METATYPE(RadioBrowserService::Stream) + +#endif // INTERNET_RADIOBROWSER_RADIOBROWSERSERVICE_H_ diff --git a/src/internet/radiobrowser/radiobrowserurlhandler.cpp b/src/internet/radiobrowser/radiobrowserurlhandler.cpp new file mode 100644 index 000000000..408e37397 --- /dev/null +++ b/src/internet/radiobrowser/radiobrowserurlhandler.cpp @@ -0,0 +1,91 @@ +/* This file is part of Clementine. + Copyright 2011-2013, David Sansome + Copyright 2012, Olaf Christ + Copyright 2014, Krzysztof Sobiecki + Copyright 2014, John Maguire + + 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 . +*/ + +#include "radiobrowserurlhandler.h" + +#include +#include +#include +#include + +#include "core/application.h" +#include "core/logging.h" +#include "core/taskmanager.h" +#include "radiobrowserservice.h" +#include "internet/core/internetmodel.h" +#include "playlistparsers/playlistparser.h" + +RadioBrowserUrlHandler::RadioBrowserUrlHandler( + Application* app, RadioBrowserServiceBase* service, QObject* parent) + : UrlHandler(parent), app_(app), service_(service), task_id_(0) {} + +QString RadioBrowserUrlHandler::scheme() const { + return service_->url_scheme(); +} + +QIcon RadioBrowserUrlHandler::icon() const { return service_->icon(); } + +UrlHandler::LoadResult RadioBrowserUrlHandler::StartLoading( + const QUrl& url) { + QUrl playlist_url = url; + playlist_url.setScheme("https"); + + // Load the playlist + QNetworkReply* reply = + service_->network()->get(QNetworkRequest(playlist_url)); + connect(reply, SIGNAL(finished()), SLOT(LoadPlaylistFinished())); + + if (!task_id_) + task_id_ = app_->task_manager()->StartTask(tr("Loading stream")); + + return LoadResult(url, LoadResult::WillLoadAsynchronously); +} + +void RadioBrowserUrlHandler::LoadPlaylistFinished() { + QNetworkReply* reply = qobject_cast(sender()); + app_->task_manager()->SetTaskFinished(task_id_); + task_id_ = 0; + + QUrl original_url(reply->url()); + original_url.setScheme(scheme()); + + if (reply->error() != QNetworkReply::NoError) { + // TODO((David Sansome): Error handling + qLog(Error) << reply->errorString(); + emit AsyncLoadComplete(LoadResult(original_url, LoadResult::NoMoreTracks)); + return; + } + + // Parse the playlist + PlaylistParser parser(nullptr); + QList songs = parser.LoadFromDevice(reply); + + qLog(Info) << "Loading station finished, got" << songs.count() << "songs"; + + // Failed to get playlist? + if (songs.count() == 0) { + qLog(Error) << "Error loading" << scheme() << "playlist"; + emit AsyncLoadComplete(LoadResult(original_url, LoadResult::NoMoreTracks)); + return; + } + + emit AsyncLoadComplete( + LoadResult(original_url, LoadResult::TrackAvailable, songs[0].url())); +} diff --git a/src/internet/radiobrowser/radiobrowserurlhandler.h b/src/internet/radiobrowser/radiobrowserurlhandler.h new file mode 100644 index 000000000..855636565 --- /dev/null +++ b/src/internet/radiobrowser/radiobrowserurlhandler.h @@ -0,0 +1,50 @@ +/* This file is part of Clementine. + Copyright 2011-2013, David Sansome + Copyright 2014, Krzysztof Sobiecki + Copyright 2014, John Maguire + + 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 . +*/ + +#ifndef INTERNET_RADIOBROWSER_RADIOBROWSERURLHANDLER_H_ +#define INTERNET_RADIOBROWSER_RADIOBROWSERURLHANDLER_H_ + +#include "core/urlhandler.h" + +class Application; +class RadioBrowserServiceBase; + +class RadioBrowserUrlHandler : public UrlHandler { + Q_OBJECT + + public: + RadioBrowserUrlHandler(Application* app, + RadioBrowserServiceBase* service, + QObject* parent); + + QString scheme() const; + QIcon icon() const; + LoadResult StartLoading(const QUrl& url); + + private slots: + void LoadPlaylistFinished(); + + private: + Application* app_; + RadioBrowserServiceBase* service_; + + int task_id_; +}; + +#endif // INTERNET_RADIOBROWSER_RADIOBROWSERURLHANDLER_H_