~ubuntu-branches/ubuntu/saucy/clementine/saucy

« back to all changes in this revision

Viewing changes to src/internet/spotifyserver.cpp

  • Committer: Package Import Robot
  • Author(s): Thomas PIERSON
  • Date: 2012-01-01 20:43:39 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120101204339-lsb6nndwhfy05sde
Tags: 1.0.1+dfsg-1
New upstream release. (Closes: #653926, #651611, #657391)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of Clementine.
 
2
   Copyright 2010, David Sansome <me@davidsansome.com>
 
3
 
 
4
   Clementine is free software: you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation, either version 3 of the License, or
 
7
   (at your option) any later version.
 
8
 
 
9
   Clementine is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
 
16
*/
 
17
 
 
18
#include "spotifyserver.h"
 
19
#include "core/closure.h"
 
20
#include "core/logging.h"
 
21
 
 
22
#include "spotifyblob/common/spotifymessages.pb.h"
 
23
#include "spotifyblob/common/spotifymessagehandler.h"
 
24
 
 
25
#include <QTcpServer>
 
26
#include <QTcpSocket>
 
27
#include <QTimer>
 
28
 
 
29
SpotifyServer::SpotifyServer(QObject* parent)
 
30
  : QObject(parent),
 
31
    server_(new QTcpServer(this)),
 
32
    protocol_socket_(NULL),
 
33
    handler_(NULL),
 
34
    logged_in_(false)
 
35
{
 
36
  connect(server_, SIGNAL(newConnection()), SLOT(NewConnection()));
 
37
}
 
38
 
 
39
void SpotifyServer::Init() {
 
40
  if (!server_->listen(QHostAddress::LocalHost)) {
 
41
    qLog(Error) << "Couldn't open server socket" << server_->errorString();
 
42
  }
 
43
}
 
44
 
 
45
int SpotifyServer::server_port() const {
 
46
  return server_->serverPort();
 
47
}
 
48
 
 
49
void SpotifyServer::NewConnection() {
 
50
  delete protocol_socket_;
 
51
  delete handler_;
 
52
 
 
53
  protocol_socket_ = server_->nextPendingConnection();
 
54
  handler_ = new SpotifyMessageHandler(protocol_socket_, this);
 
55
  connect(handler_, SIGNAL(MessageArrived(spotify_pb::SpotifyMessage)),
 
56
          SLOT(HandleMessage(spotify_pb::SpotifyMessage)));
 
57
 
 
58
  qLog(Info) << "Connection from port" << protocol_socket_->peerPort();
 
59
 
 
60
  // Send any login messages that were queued before the client connected
 
61
  foreach (const spotify_pb::SpotifyMessage& message, queued_login_messages_) {
 
62
    SendMessage(message);
 
63
  }
 
64
  queued_login_messages_.clear();
 
65
}
 
66
 
 
67
void SpotifyServer::SendMessage(const spotify_pb::SpotifyMessage& message) {
 
68
  const bool is_login_message = message.has_login_request();
 
69
 
 
70
  QList<spotify_pb::SpotifyMessage>* queue =
 
71
      is_login_message ? &queued_login_messages_ : &queued_messages_;
 
72
 
 
73
  if (!protocol_socket_ || (!is_login_message && !logged_in_)) {
 
74
    queue->append(message);
 
75
  } else {
 
76
    handler_->SendMessage(message);
 
77
  }
 
78
}
 
79
 
 
80
void SpotifyServer::Login(const QString& username, const QString& password,
 
81
                          spotify_pb::Bitrate bitrate, bool volume_normalisation) {
 
82
  spotify_pb::SpotifyMessage message;
 
83
 
 
84
  spotify_pb::LoginRequest* request = message.mutable_login_request();
 
85
  request->set_username(DataCommaSizeFromQString(username));
 
86
  if (!password.isEmpty()) {
 
87
    request->set_password(DataCommaSizeFromQString(password));
 
88
  }
 
89
  request->mutable_playback_settings()->set_bitrate(bitrate);
 
90
  request->mutable_playback_settings()->set_volume_normalisation(volume_normalisation);
 
91
 
 
92
  SendMessage(message);
 
93
}
 
94
 
 
95
void SpotifyServer::SetPlaybackSettings(spotify_pb::Bitrate bitrate, bool volume_normalisation) {
 
96
  spotify_pb::SpotifyMessage message;
 
97
 
 
98
  spotify_pb::PlaybackSettings* request = message.mutable_set_playback_settings_request();
 
99
  request->set_bitrate(bitrate);
 
100
  request->set_volume_normalisation(volume_normalisation);
 
101
 
 
102
  SendMessage(message);
 
103
}
 
104
 
 
105
void SpotifyServer::HandleMessage(const spotify_pb::SpotifyMessage& message) {
 
106
  if (message.has_login_response()) {
 
107
    const spotify_pb::LoginResponse& response = message.login_response();
 
108
    logged_in_ = response.success();
 
109
 
 
110
    if (response.success()) {
 
111
      // Send any messages that were queued before the client logged in
 
112
      foreach (const spotify_pb::SpotifyMessage& message, queued_messages_) {
 
113
        SendMessage(message);
 
114
      }
 
115
      queued_messages_.clear();
 
116
    }
 
117
 
 
118
    emit LoginCompleted(response.success(), QStringFromStdString(response.error()),
 
119
                        response.error_code());
 
120
  } else if (message.has_playlists_updated()) {
 
121
    emit PlaylistsUpdated(message.playlists_updated());
 
122
  } else if (message.has_load_playlist_response()) {
 
123
    const spotify_pb::LoadPlaylistResponse& response = message.load_playlist_response();
 
124
 
 
125
    switch (response.request().type()) {
 
126
      case spotify_pb::Inbox:
 
127
        emit InboxLoaded(response);
 
128
        break;
 
129
 
 
130
      case spotify_pb::Starred:
 
131
        emit StarredLoaded(response);
 
132
        break;
 
133
 
 
134
      case spotify_pb::UserPlaylist:
 
135
        emit UserPlaylistLoaded(response);
 
136
        break;
 
137
    }
 
138
  } else if (message.has_playback_error()) {
 
139
    emit PlaybackError(QStringFromStdString(message.playback_error().error()));
 
140
  } else if (message.has_search_response()) {
 
141
    emit SearchResults(message.search_response());
 
142
  } else if (message.has_image_response()) {
 
143
    const spotify_pb::ImageResponse& response = message.image_response();
 
144
    const QString id = QStringFromStdString(response.id());
 
145
 
 
146
    if (response.has_data()) {
 
147
      emit ImageLoaded(id, QImage::fromData(QByteArray(
 
148
          response.data().data(), response.data().size())));
 
149
    } else {
 
150
      emit ImageLoaded(id, QImage());
 
151
    }
 
152
  } else if (message.has_sync_playlist_progress()) {
 
153
    emit SyncPlaylistProgress(message.sync_playlist_progress());
 
154
  } else if (message.has_browse_album_response()) {
 
155
    emit AlbumBrowseResults(message.browse_album_response());
 
156
  }
 
157
}
 
158
 
 
159
void SpotifyServer::LoadPlaylist(spotify_pb::PlaylistType type, int index) {
 
160
  spotify_pb::SpotifyMessage message;
 
161
  spotify_pb::LoadPlaylistRequest* req = message.mutable_load_playlist_request();
 
162
 
 
163
  req->set_type(type);
 
164
  if (index != -1) {
 
165
    req->set_user_playlist_index(index);
 
166
  }
 
167
 
 
168
  SendMessage(message);
 
169
}
 
170
 
 
171
void SpotifyServer::SyncPlaylist(
 
172
    spotify_pb::PlaylistType type, int index, bool offline) {
 
173
  spotify_pb::SpotifyMessage message;
 
174
  spotify_pb::SyncPlaylistRequest* req = message.mutable_sync_playlist_request();
 
175
  req->mutable_request()->set_type(type);
 
176
  if (index != -1) {
 
177
    req->mutable_request()->set_user_playlist_index(index);
 
178
  }
 
179
  req->set_offline_sync(offline);
 
180
 
 
181
  SendMessage(message);
 
182
}
 
183
 
 
184
void SpotifyServer::SyncInbox() {
 
185
  SyncPlaylist(spotify_pb::Inbox, -1, true);
 
186
}
 
187
 
 
188
void SpotifyServer::SyncStarred() {
 
189
  SyncPlaylist(spotify_pb::Starred, -1, true);
 
190
}
 
191
 
 
192
void SpotifyServer::SyncUserPlaylist(int index) {
 
193
  Q_ASSERT(index >= 0);
 
194
  SyncPlaylist(spotify_pb::UserPlaylist, index, true);
 
195
}
 
196
 
 
197
void SpotifyServer::LoadInbox() {
 
198
  LoadPlaylist(spotify_pb::Inbox);
 
199
}
 
200
 
 
201
void SpotifyServer::LoadStarred() {
 
202
  LoadPlaylist(spotify_pb::Starred);
 
203
}
 
204
 
 
205
void SpotifyServer::LoadUserPlaylist(int index) {
 
206
  Q_ASSERT(index >= 0);
 
207
  LoadPlaylist(spotify_pb::UserPlaylist, index);
 
208
}
 
209
 
 
210
void SpotifyServer::StartPlaybackLater(const QString& uri, quint16 port) {
 
211
  QTimer* timer = new QTimer(this);
 
212
  connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
 
213
 
 
214
  timer->start(100); // lol
 
215
  NewClosure(timer, SIGNAL(timeout()),
 
216
             this, SLOT(StartPlayback(QString,quint16)),
 
217
             uri, port);
 
218
}
 
219
 
 
220
void SpotifyServer::StartPlayback(const QString& uri, quint16 port) {
 
221
  spotify_pb::SpotifyMessage message;
 
222
  spotify_pb::PlaybackRequest* req = message.mutable_playback_request();
 
223
 
 
224
  req->set_track_uri(DataCommaSizeFromQString(uri));
 
225
  req->set_media_port(port);
 
226
  SendMessage(message);
 
227
}
 
228
 
 
229
void SpotifyServer::Seek(qint64 offset_bytes) {
 
230
  spotify_pb::SpotifyMessage message;
 
231
  spotify_pb::SeekRequest* req = message.mutable_seek_request();
 
232
 
 
233
  req->set_offset_bytes(offset_bytes);
 
234
  SendMessage(message);
 
235
}
 
236
 
 
237
void SpotifyServer::Search(const QString& text, int limit, int limit_album) {
 
238
  spotify_pb::SpotifyMessage message;
 
239
  spotify_pb::SearchRequest* req = message.mutable_search_request();
 
240
 
 
241
  req->set_query(DataCommaSizeFromQString(text));
 
242
  req->set_limit(limit);
 
243
  req->set_limit_album(limit_album);
 
244
  SendMessage(message);
 
245
}
 
246
 
 
247
void SpotifyServer::LoadImage(const QString& id) {
 
248
  spotify_pb::SpotifyMessage message;
 
249
  spotify_pb::ImageRequest* req = message.mutable_image_request();
 
250
 
 
251
  req->set_id(DataCommaSizeFromQString(id));
 
252
  SendMessage(message);
 
253
}
 
254
 
 
255
void SpotifyServer::AlbumBrowse(const QString& uri) {
 
256
  spotify_pb::SpotifyMessage message;
 
257
  spotify_pb::BrowseAlbumRequest* req = message.mutable_browse_album_request();
 
258
 
 
259
  req->set_uri(DataCommaSizeFromQString(uri));
 
260
  SendMessage(message);
 
261
}