/* This file is part of Clementine. Copyright 2011, Tyler Rhodes Copyright 2011-2012, 2014, Arnaud Bienner Copyright 2011-2012, 2014, John Maguire Copyright 2011-2012, 2014, David Sansome 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_SPOTIFY_SPOTIFYSERVICE_H_ #define INTERNET_SPOTIFY_SPOTIFYSERVICE_H_ #include #include #include "internet/core/internetmodel.h" #include "internet/core/internetservice.h" #include "spotifymessages.pb.h" class Playlist; class SearchBoxWidget; class SpotifyServer; class QMenu; class SpotifyService : public InternetService { Q_OBJECT public: SpotifyService(Application* app, InternetModel* parent); ~SpotifyService(); enum Type { Type_SearchResults = InternetModel::TypeCount, Type_StarredPlaylist, Type_InboxPlaylist, Type_Toplist, }; enum Role { Role_UserPlaylistIndex = InternetModel::RoleCount, }; // Values are persisted - don't change. enum LoginState { LoginState_LoggedIn = 1, LoginState_Banned = 2, LoginState_BadCredentials = 3, LoginState_NoPremium = 4, LoginState_OtherError = 5, LoginState_ReloginFailed = 6 }; static const char* kServiceName; static const char* kSettingsGroup; static const char* kBlobDownloadUrl; static const int kSearchDelayMsec; void ReloadSettings() override; QStandardItem* CreateRootItem() override; void LazyPopulate(QStandardItem* parent) override; void ShowContextMenu(const QPoint& global_pos) override; void DropMimeData(const QMimeData* data, const QModelIndex& index) override; QList playlistitem_actions(const Song& song) override; PlaylistItem::Options playlistitem_options() const override; QWidget* HeaderWidget() const override; void Logout(); void Login(const QString& username, const QString& password); Q_INVOKABLE void LoadImage(const QString& id); Q_INVOKABLE void SetPaused(bool paused); SpotifyServer* server() const; bool IsBlobInstalled() const; void InstallBlob(); // Persisted in the settings and updated on each Login(). LoginState login_state() const { return login_state_; } bool IsLoggedIn() const { return login_state_ == LoginState_LoggedIn; } bool ConfigRequired() override { return !IsLoggedIn(); } static void SongFromProtobuf(const cpb::spotify::Track& track, Song* song); signals: void BlobStateChanged(); void LoginFinished(bool success); void ImageLoaded(const QString& id, const QImage& image); public slots: void Search(const QString& text, bool now = false); void ShowConfig() override; void RemoveCurrentFromPlaylist(); private: void StartBlobProcess(); void FillPlaylist( QStandardItem* item, const google::protobuf::RepeatedPtrField& tracks); void FillPlaylist(QStandardItem* item, const cpb::spotify::LoadPlaylistResponse& response); void AddSongsToUserPlaylist(int playlist_index, const QList& songs_urls); void AddSongsToStarred(const QList& songs_urls); void EnsureMenuCreated(); // Create a new "show config" action. The caller is responsible for deleting // the pointer (or adding it to menu or anything else that will take ownership // of it) QAction* GetNewShowConfigAction(); void InitSearch(); void ClearSearchResults(); QStandardItem* PlaylistBySpotifyIndex(int index) const; bool DoPlaylistsDiffer(const cpb::spotify::Playlists& response) const; private slots: void EnsureServerCreated(const QString& username = QString(), const QString& password = QString()); void BlobProcessError(QProcess::ProcessError error); void LoginCompleted(bool success, const QString& error, cpb::spotify::LoginResponse_Error error_code); void AddCurrentSongToUserPlaylist(QAction* action); void AddCurrentSongToStarredPlaylist(); void RemoveSongsFromUserPlaylist(int playlist_index, const QList& songs_indices_to_remove); void RemoveSongsFromStarred(const QList& songs_indices_to_remove); void PlaylistsUpdated(const cpb::spotify::Playlists& response); void InboxLoaded(const cpb::spotify::LoadPlaylistResponse& response); void StarredLoaded(const cpb::spotify::LoadPlaylistResponse& response); void UserPlaylistLoaded(const cpb::spotify::LoadPlaylistResponse& response); void SearchResults(const cpb::spotify::SearchResponse& response); void SyncPlaylistProgress(const cpb::spotify::SyncPlaylistProgress& progress); void ToplistLoaded(const cpb::spotify::BrowseToplistResponse& response); void GetCurrentSongUrlToShare() const; void GetCurrentPlaylistUrlToShare() const; void DoSearch(); void SyncPlaylist(); void BlobDownloadFinished(); private: SpotifyServer* server_; QString system_blob_path_; QString local_blob_version_; QString local_blob_path_; QProcess* blob_process_; QStandardItem* root_; QStandardItem* search_; QStandardItem* starred_; QStandardItem* inbox_; QStandardItem* toplist_; QList playlists_; int login_task_id_; QString pending_search_; QMenu* playlist_context_menu_; QMenu* song_context_menu_; QAction* playlist_sync_action_; QAction* get_url_to_share_playlist_; QList playlistitem_actions_; QAction* remove_from_playlist_; QUrl current_song_url_; QUrl current_playlist_url_; SearchBoxWidget* search_box_; QTimer* search_delay_; int inbox_sync_id_; int starred_sync_id_; QMap playlist_sync_ids_; LoginState login_state_; cpb::spotify::Bitrate bitrate_; bool volume_normalisation_; }; #endif // INTERNET_SPOTIFY_SPOTIFYSERVICE_H_