Clementine-audio-player-Mac.../src/internet/groovesharkservice.h

331 lines
12 KiB
C++

/* This file is part of Clementine.
Copyright 2011, 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 GROOVESHARKSERVICE_H
#define GROOVESHARKSERVICE_H
#include "internetmodel.h"
#include "internetservice.h"
#include <QSslError>
class GroovesharkUrlHandler;
class NetworkAccessManager;
class Playlist;
class SearchBoxWidget;
class QMenu;
class QNetworkReply;
class QNetworkRequest;
class QSortFilterProxyModel;
class GroovesharkService : public InternetService {
Q_OBJECT
public:
GroovesharkService(Application* app, InternetModel* parent);
~GroovesharkService();
enum Role {
Role_UserPlaylistId = InternetModel::RoleCount,
Role_PlaylistType
};
enum PlaylistType {
UserPlaylist = Qt::UserRole,
// Favorites and Library list are like playlists, but we want to do special
// treatments in some cases
UserFavorites,
UserLibrary,
SubscribedPlaylist
};
// Values are persisted - don't change.
enum LoginState {
LoginState_LoggedIn = 1,
LoginState_AuthFailed = 2,
LoginState_NoPremium = 3,
LoginState_OtherError = 4
};
// Internet Service methods
QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* parent);
void ItemDoubleClicked(QStandardItem* item);
smart_playlists::GeneratorPtr CreateGenerator(QStandardItem* item);
void DropMimeData(const QMimeData* data, const QModelIndex& index);
QList<QAction*> playlistitem_actions(const Song& song);
void ShowContextMenu(const QPoint& global_pos);
QWidget* HeaderWidget() const;
// User should be logged in to be able to generate streaming urls
QUrl GetStreamingUrlFromSongId(const QString& song_id,
const QString& artist_id, QString* server_id,
QString* stream_key, qint64* length_nanosec);
void Login(const QString& username, const QString& password);
void Logout();
bool IsLoggedIn() const { return !session_id_.isEmpty(); }
void RetrieveUserPlaylists();
void RetrieveUserFavorites();
void RetrieveUserLibrarySongs();
void RetrievePopularSongs();
void RetrievePopularSongsMonth();
void RetrievePopularSongsToday();
void RetrieveSubscribedPlaylists();
void RetrieveAutoplayTags();
void SetPlaylistSongs(int playlist_id, const QList<int>& songs_ids);
void RemoveFromPlaylist(int playlist_id,
const QList<int>& songs_ids_to_remove);
// Refresh playlist_id playlist , or create it if it doesn't exist
void RefreshPlaylist(int playlist_id);
void DeletePlaylist(int playlist_id);
void RenamePlaylist(int playlist_id);
void AddUserFavoriteSong(int song_id);
void RemoveFromFavorites(const QList<int>& songs_ids_to_remove);
void AddUserLibrarySongs(const QList<int>& songs_ids);
void RemoveFromLibrary(const QList<int>& songs_ids_to_remove);
void GetSongUrlToShare(int song_id);
void GetPlaylistUrlToShare(int playlist_id);
// Start autoplay for the given tag_id, fill the autoplay_state, returns a
// first song to play
Song StartAutoplayTag(int tag_id, QVariantMap& autoplay_state);
Song StartAutoplay(QVariantMap& autoplay_state);
// Get another autoplay song. autoplay_state is the autoplay_state received
// from StartAutoplayTag
Song GetAutoplaySong(QVariantMap& autoplay_state);
void MarkStreamKeyOver30Secs(const QString& stream_key,
const QString& server_id);
void MarkSongComplete(const QString& song_id, const QString& stream_key,
const QString& server_id);
// Persisted in the settings and updated on each Login().
LoginState login_state() const { return login_state_; }
const QString& session_id() { return session_id_; }
int SimpleSearch(const QString& query);
int SearchAlbums(const QString& query);
void GetAlbumSongs(quint64 album_id);
static const char* kServiceName;
static const char* kSettingsGroup;
signals:
void LoginFinished(bool success);
void SimpleSearchResults(int id, SongList songs);
// AlbumSearchResult emits the search id and the Grooveshark ids of the
// albums found. Albums' songs will be loaded asynchronously and
// AlbumSongsLoaded will be emitted, containing the actual Albums' songs.
void AlbumSearchResult(int id, QList<quint64> albums_ids);
void AlbumSongsLoaded(quint64 id, SongList songs);
public slots:
void Search(const QString& text, bool now = false);
void ShowConfig();
protected:
struct PlaylistInfo {
PlaylistInfo() {}
PlaylistInfo(int id, QString name, QStandardItem* item = nullptr)
: id_(id), name_(name), item_(item) {}
bool operator<(const PlaylistInfo other) const {
return name_.localeAwareCompare(other.name_) < 0;
}
int id_;
QString name_;
QStandardItem* item_;
QList<int> songs_ids_;
};
private slots:
void SessionCreated(QNetworkReply* reply);
void DoSearch();
void SearchSongsFinished(QNetworkReply* reply);
void SimpleSearchFinished(QNetworkReply* reply, int id);
void SearchAlbumsFinished(QNetworkReply* reply, int id);
void GetAlbumSongsFinished(QNetworkReply* reply, quint64 album_id);
void Authenticated(QNetworkReply* reply);
void UserPlaylistsRetrieved(QNetworkReply* reply);
void UserFavoritesRetrieved(QNetworkReply* reply, int task_id);
void UserLibrarySongsRetrieved(QNetworkReply* reply, int task_id);
void PopularSongsMonthRetrieved(QNetworkReply* reply);
void PopularSongsTodayRetrieved(QNetworkReply* reply);
void SubscribedPlaylistsRetrieved(QNetworkReply* reply);
void AutoplayTagsRetrieved(QNetworkReply* reply);
void PlaylistSongsRetrieved(QNetworkReply* reply, int playlist_id);
void PlaylistSongsSet(QNetworkReply* reply, int playlist_id, int task_id);
void CreateNewPlaylist();
void NewPlaylistCreated(QNetworkReply* reply, const QString& name);
void DeleteCurrentPlaylist();
void RenameCurrentPlaylist();
void PlaylistDeleted(QNetworkReply* reply, int playlist_id);
void PlaylistRenamed(QNetworkReply* reply, int playlist_id,
const QString& new_name);
void AddCurrentSongToUserFavorites() {
AddUserFavoriteSong(current_song_id_);
}
void AddCurrentSongToUserLibrary() {
AddUserLibrarySongs(QList<int>() << current_song_id_);
}
void AddCurrentSongToPlaylist(QAction* action);
void UserFavoriteSongAdded(QNetworkReply* reply, int task_id);
void UserLibrarySongAdded(QNetworkReply* reply, int task_id);
void GetCurrentSongUrlToShare();
void SongUrlToShareReceived(QNetworkReply* reply);
void GetCurrentPlaylistUrlToShare();
void PlaylistUrlToShareReceived(QNetworkReply* reply);
void RemoveCurrentFromPlaylist();
void RemoveCurrentFromFavorites();
void RemoveCurrentFromLibrary();
void SongsRemovedFromFavorites(QNetworkReply* reply, int task_id);
void SongsRemovedFromLibrary(QNetworkReply* reply, int task_id);
void StreamMarked(QNetworkReply* reply);
void SongMarkedAsComplete(QNetworkReply* reply);
void RequestSslErrors(const QList<QSslError>& errors);
void Homepage();
// Refresh all Grooveshark's items, and re-fill them
void RefreshItems();
private:
void EnsureMenuCreated();
void EnsureItemsCreated();
void RemoveItems();
void EnsureConnected();
void ClearSearchResults();
// Create a playlist item, with data set as excepted. Doesn't fill the item
// with songs rows.
QStandardItem* CreatePlaylistItem(const QString& playlist_name,
int playlist_id);
void AuthenticateSession();
void InitCountry();
// Create a request for the given method, with the given params.
// If need_authentication is true, add session_id to params.
// Returns the reply object created
QNetworkReply* CreateRequest(const QString& method_name,
const QList<QPair<QString, QVariant> >& params,
bool use_https = false);
// Convenient function which block until 'reply' replies, or timeout after 10
// seconds. Returns false if reply has timeouted
bool WaitForReply(QNetworkReply* reply);
void ShowUrlBox(const QString& title, const QString& url);
// Convenient function for extracting result from reply
QVariantMap ExtractResult(QNetworkReply* reply);
// Convenient function for extracting songs from grooveshark result. result
// should be the "result" field of most Grooveshark replies
SongList ExtractSongs(const QVariantMap& result);
// Convenient function for extracting song from grooveshark result.
// result_song should be the song field ('song', 'nextSong', ...) of the
// Grooveshark reply
Song ExtractSong(const QVariantMap& result_song);
// Convenient functions for extracting Grooveshark songs ids
QList<int> ExtractSongsIds(const QVariantMap& result);
QList<int> ExtractSongsIds(const QList<QUrl>& urls);
int ExtractSongId(
const QUrl& url); // Returns 0 if url is not a Grooveshark url
// Convenient function for extracting basic playlist info (only 'id' and
// 'name': QStandardItem still need to be created), and sort them by name
QList<PlaylistInfo> ExtractPlaylistInfo(const QVariantMap& result);
void ResetSessionId();
GroovesharkUrlHandler* url_handler_;
QString pending_search_;
int next_pending_search_id_;
QSet<int> pending_retrieve_playlists_;
QMap<int, PlaylistInfo> playlists_;
QMap<int, PlaylistInfo> subscribed_playlists_;
QStandardItem* root_;
QStandardItem* search_;
QStandardItem* popular_month_;
QStandardItem* popular_today_;
QStandardItem* stations_;
QStandardItem* grooveshark_radio_;
QStandardItem* favorites_;
// Grooveshark Library (corresponds to Grooveshark 'MyMusic' actually, but
// called 'Library' in the API).
// Nothing to do with Clementine's local library
QStandardItem* library_;
QStandardItem* playlists_parent_;
QStandardItem* subscribed_playlists_parent_;
NetworkAccessManager* network_;
QMenu* context_menu_;
// IDs kept when showing menu, to know what the user has clicked on, to be
// able to perform actions on corresponding items
int current_song_id_;
int current_playlist_id_;
QAction* create_playlist_;
QAction* delete_playlist_;
QAction* rename_playlist_;
QAction* remove_from_playlist_;
QAction* remove_from_favorites_;
QAction* remove_from_library_;
QAction* get_url_to_share_song_;
QAction* get_url_to_share_playlist_;
QList<QAction*> playlistitem_actions_;
SearchBoxWidget* search_box_;
QTimer* search_delay_;
QNetworkReply* last_search_reply_;
QString username_;
QString password_; // In fact, password's md5 hash
QString user_id_;
QString session_id_;
QMap<QString, QVariant> country_;
// The last artists and songs ids th users has listened to. Used for autoplay
QList<int> last_artists_ids_;
QList<int> last_songs_ids_;
QByteArray api_key_;
LoginState login_state_;
// Tasks' ids: we need to keep them in mind to be able to update task status
// on each step
int task_popular_id_;
int task_playlists_id_;
int task_search_id_;
static const char* kUrl;
static const char* kUrlCover;
static const char* kHomepage;
static const int kSongSearchLimit;
static const int kSongSimpleSearchLimit;
static const int kAlbumSearchLimit;
static const int kSearchDelayMsec;
static const char* kApiKey;
static const char* kApiSecret;
};
#endif // GROOVESHARKSERVICE_H