1 /* This file is part of Clementine. 2 Copyright 2011, Tyler Rhodes <tyler.s.rhodes@gmail.com> 3 Copyright 2011-2012, 2014, Arnaud Bienner <arnaud.bienner@gmail.com> 4 Copyright 2011-2012, 2014, John Maguire <john.maguire@gmail.com> 5 Copyright 2011-2012, 2014, David Sansome <me@davidsansome.com> 6 Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com> 7 8 Clementine is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 Clementine is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Clementine. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef INTERNET_SPOTIFY_SPOTIFYSERVICE_H_ 23 #define INTERNET_SPOTIFY_SPOTIFYSERVICE_H_ 24 25 #include "internet/core/internetmodel.h" 26 #include "internet/core/internetservice.h" 27 #include "spotifymessages.pb.h" 28 29 #include <QProcess> 30 #include <QTimer> 31 32 class Playlist; 33 class SearchBoxWidget; 34 class SpotifyServer; 35 36 class QMenu; 37 38 class SpotifyService : public InternetService { 39 Q_OBJECT 40 41 public: 42 SpotifyService(Application* app, InternetModel* parent); 43 ~SpotifyService(); 44 45 enum Type { 46 Type_SearchResults = InternetModel::TypeCount, 47 Type_StarredPlaylist, 48 Type_InboxPlaylist, 49 Type_Toplist, 50 }; 51 52 enum Role { 53 Role_UserPlaylistIndex = InternetModel::RoleCount, 54 }; 55 56 // Values are persisted - don't change. 57 enum LoginState { 58 LoginState_LoggedIn = 1, 59 LoginState_Banned = 2, 60 LoginState_BadCredentials = 3, 61 LoginState_NoPremium = 4, 62 LoginState_OtherError = 5, 63 LoginState_ReloginFailed = 6 64 }; 65 66 static const char* kServiceName; 67 static const char* kSettingsGroup; 68 static const char* kBlobDownloadUrl; 69 static const int kSearchDelayMsec; 70 71 void ReloadSettings() override; 72 73 QStandardItem* CreateRootItem() override; 74 void LazyPopulate(QStandardItem* parent) override; 75 void ShowContextMenu(const QPoint& global_pos) override; 76 void ItemDoubleClicked(QStandardItem* item) override; 77 void DropMimeData(const QMimeData* data, const QModelIndex& index) override; 78 QList<QAction*> playlistitem_actions(const Song& song) override; 79 PlaylistItem::Options playlistitem_options() const override; 80 QWidget* HeaderWidget() const override; 81 82 void Logout(); 83 void Login(const QString& username, const QString& password); 84 Q_INVOKABLE void LoadImage(const QString& id); 85 Q_INVOKABLE void SetPaused(bool paused); 86 87 SpotifyServer* server() const; 88 89 bool IsBlobInstalled() const; 90 void InstallBlob(); 91 92 // Persisted in the settings and updated on each Login(). login_state()93 LoginState login_state() const { return login_state_; } IsLoggedIn()94 bool IsLoggedIn() const { return login_state_ == LoginState_LoggedIn; } 95 96 static void SongFromProtobuf(const pb::spotify::Track& track, Song* song); 97 98 signals: 99 void BlobStateChanged(); 100 void LoginFinished(bool success); 101 void ImageLoaded(const QString& id, const QImage& image); 102 103 public slots: 104 void Search(const QString& text, bool now = false); 105 void ShowConfig() override; 106 void RemoveCurrentFromPlaylist(); 107 108 private: 109 void StartBlobProcess(); 110 void FillPlaylist( 111 QStandardItem* item, 112 const google::protobuf::RepeatedPtrField<pb::spotify::Track>& tracks); 113 void FillPlaylist(QStandardItem* item, 114 const pb::spotify::LoadPlaylistResponse& response); 115 void AddSongsToUserPlaylist(int playlist_index, 116 const QList<QUrl>& songs_urls); 117 void AddSongsToStarred(const QList<QUrl>& songs_urls); 118 void EnsureMenuCreated(); 119 // Create a new "show config" action. The caller is responsible for deleting 120 // the pointer (or adding it to menu or anything else that will take ownership 121 // of it) 122 QAction* GetNewShowConfigAction(); 123 void InitSearch(); 124 void ClearSearchResults(); 125 QStandardItem* PlaylistBySpotifyIndex(int index) const; 126 bool DoPlaylistsDiffer(const pb::spotify::Playlists& response) const; 127 128 private slots: 129 void EnsureServerCreated(const QString& username = QString(), 130 const QString& password = QString()); 131 void BlobProcessError(QProcess::ProcessError error); 132 void LoginCompleted(bool success, const QString& error, 133 pb::spotify::LoginResponse_Error error_code); 134 void AddCurrentSongToUserPlaylist(QAction* action); 135 void AddCurrentSongToStarredPlaylist(); 136 void RemoveSongsFromUserPlaylist(int playlist_index, 137 const QList<int>& songs_indices_to_remove); 138 void RemoveSongsFromStarred(const QList<int>& songs_indices_to_remove); 139 void PlaylistsUpdated(const pb::spotify::Playlists& response); 140 void InboxLoaded(const pb::spotify::LoadPlaylistResponse& response); 141 void StarredLoaded(const pb::spotify::LoadPlaylistResponse& response); 142 void UserPlaylistLoaded(const pb::spotify::LoadPlaylistResponse& response); 143 void SearchResults(const pb::spotify::SearchResponse& response); 144 void SyncPlaylistProgress(const pb::spotify::SyncPlaylistProgress& progress); 145 void ToplistLoaded(const pb::spotify::BrowseToplistResponse& response); 146 void GetCurrentSongUrlToShare() const; 147 void GetCurrentPlaylistUrlToShare() const; 148 149 void DoSearch(); 150 151 void SyncPlaylist(); 152 void BlobDownloadFinished(); 153 154 private: 155 SpotifyServer* server_; 156 157 QString system_blob_path_; 158 QString local_blob_version_; 159 QString local_blob_path_; 160 QProcess* blob_process_; 161 162 QStandardItem* root_; 163 QStandardItem* search_; 164 QStandardItem* starred_; 165 QStandardItem* inbox_; 166 QStandardItem* toplist_; 167 QList<QStandardItem*> playlists_; 168 169 int login_task_id_; 170 QString pending_search_; 171 172 QMenu* context_menu_; 173 QMenu* playlist_context_menu_; 174 QMenu* song_context_menu_; 175 QAction* playlist_sync_action_; 176 QAction* get_url_to_share_playlist_; 177 QList<QAction*> playlistitem_actions_; 178 QAction* remove_from_playlist_; 179 QUrl current_song_url_; 180 QUrl current_playlist_url_; 181 182 SearchBoxWidget* search_box_; 183 184 QTimer* search_delay_; 185 186 int inbox_sync_id_; 187 int starred_sync_id_; 188 QMap<int, int> playlist_sync_ids_; 189 190 LoginState login_state_; 191 pb::spotify::Bitrate bitrate_; 192 bool volume_normalisation_; 193 }; 194 195 #endif // INTERNET_SPOTIFY_SPOTIFYSERVICE_H_ 196