54 QDir dir( privatePathQt ); |
57 QDir dir( privatePathQt ); |
55 QString newDir = "detailsview"; |
58 QString newDir = "detailsview"; |
56 bool res = dir.mkdir( newDir ); |
59 bool res = dir.mkdir( newDir ); |
57 TX_LOG_ARGS( "New dir creation result: " << res); |
60 TX_LOG_ARGS( "New dir creation result: " << res); |
58 |
61 |
59 // We're not handling a negative result for directory creation here, |
62 // TODO: Instead of writing the album art to a file, |
60 // instead it will be escalated in DownloadFinished() method. |
63 // then using Thumbnail Manager to convert it, etc. |
|
64 // have you considered just loading it directly into QPixmap? |
|
65 // QPixmap provides a loadFromData() that can load from QByteArray. |
|
66 // This would not only make the availability of the album art immediate, |
|
67 // but also save a lot of cleanup in file system, thumbnail manager, etc. |
61 privatePathQt = privatePathQt + "/detailsview"; |
68 privatePathQt = privatePathQt + "/detailsview"; |
62 QString albumArt1( privatePathQt + "/albumOne.png" ); |
69 QString albumArt1( privatePathQt + "/albumOne.png" ); |
63 QString albumArt2( privatePathQt + "/albumTwo.png" ); |
70 QString albumArt2( privatePathQt + "/albumTwo.png" ); |
64 mRecommendationAlbumArtsName << albumArt1 << albumArt2; |
71 mRecommendationAlbumArtsName << albumArt1 << albumArt2; |
65 TX_LOG_ARGS( "recommendation album art names: " << mRecommendationAlbumArtsName ); |
72 TX_LOG_ARGS( "recommendation album art names: " << mRecommendationAlbumArtsName ); |
66 |
73 |
67 mManager = new QNetworkAccessManager( this ); |
74 mManager = new QNetworkAccessManager( this ); |
68 |
75 mAlbumArtDownloader = new QNetworkAccessManager( this ); // TODO: check if we can only use mManager |
69 mDownloadManager = new QNetworkAccessManager( this ); |
|
70 connect( mDownloadManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( DownloadFinished( QNetworkReply * ) ) ); |
|
71 |
|
72 mThumbnailManager = new ThumbnailManager( this ); |
76 mThumbnailManager = new ThumbnailManager( this ); |
73 mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality ); |
77 mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality ); |
74 mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall ); |
78 mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall ); |
75 QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ), |
79 |
76 this, SLOT( thumbnailReady( QPixmap , void * , int , int ) ) ); |
|
77 // TODO: Use the album art in provided by 10.1 wk16 platform. Current one is in the binary |
|
78 mDefaultRecommendationAlbumArt = QPixmap( ":/mpdetailsviewicons/qtg_large_music_album.svg" ); |
|
79 |
|
80 TX_EXIT |
80 TX_EXIT |
81 } |
81 } |
82 |
82 |
83 MpQueryManager::~MpQueryManager() |
83 MpQueryManager::~MpQueryManager() |
84 { |
84 { |
85 TX_ENTRY |
85 TX_ENTRY |
|
86 reset(); |
86 if ( mManager ) { |
87 if ( mManager ) { |
87 mManager->deleteLater(); |
88 mManager->deleteLater(); |
88 } |
89 } |
89 if ( mDownloadManager ) { |
90 if ( mAlbumArtDownloader ) { |
90 mDownloadManager->deleteLater(); |
91 mAlbumArtDownloader->deleteLater(); |
91 } |
92 } |
92 delete mThumbnailManager; |
93 if( mThumbnailManager ) { |
|
94 mThumbnailManager->deleteLater(); |
|
95 } |
93 TX_EXIT |
96 TX_EXIT |
94 } |
97 } |
95 |
98 |
96 |
99 |
97 void MpQueryManager::clearNetworkReplies() |
100 void MpQueryManager::clearNetworkReplies() |
98 { |
101 { |
|
102 mRequestType = NoRequest; |
99 disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
103 disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
100 TX_ENTRY_ARGS( "Reply count = " << mReplys.count() ); |
104 TX_ENTRY_ARGS( "Reply count = " << mReplys.count() ); |
101 for ( int i = 0; i < mReplys.count(); i++ ) { |
105 for ( int i = 0; i < mReplys.count(); ++i ) { |
102 QNetworkReply *reply = mReplys.at( i ); |
106 QNetworkReply *reply = mReplys.at( i ); |
103 disconnect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
107 disconnect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
104 if ( reply != NULL ) { |
108 if ( reply != NULL ) { |
105 reply->close(); |
109 reply->close(); |
106 reply->deleteLater(); |
110 reply->deleteLater(); |
107 reply = NULL; |
111 reply = NULL; |
108 } |
112 } |
109 } |
113 } |
110 mReplys.clear(); |
114 mReplys.clear(); |
111 TX_EXIT |
115 TX_EXIT |
112 } |
116 } |
113 |
117 |
121 // TODO: country information handling, MCC |
125 // TODO: country information handling, MCC |
122 QString queryURI("http://api.music.ovi.com/1.0/ru/?"); |
126 QString queryURI("http://api.music.ovi.com/1.0/ru/?"); |
123 constructRequest( queryURI ); |
127 constructRequest( queryURI ); |
124 TX_LOG_ARGS( "queryURI : " << queryURI ); |
128 TX_LOG_ARGS( "queryURI : " << queryURI ); |
125 retrieveInformation( queryURI ); |
129 retrieveInformation( queryURI ); |
|
130 mRequestType = LocalStoreRequest; |
126 TX_EXIT |
131 TX_EXIT |
127 } |
132 } |
128 |
133 |
129 void MpQueryManager::queryInspireMeItems(QString artist,QString album,QString title) |
134 void MpQueryManager::queryInspireMeItems(QString artist,QString album,QString title) |
130 { |
135 { |
131 TX_ENTRY |
136 TX_ENTRY |
132 mArtist=artist; |
137 mArtist=artist; |
133 mAlbum=album; |
138 mAlbum=album; |
134 mTitle=title; |
139 mTitle=title; |
135 // start querying inspire me items |
140 // start querying inspire me items |
136 QString queryRecommendation("http://api.music.ovi.com/1.0/gb/releases/recommend/?"); |
141 QString queryRecommendation("http://api.music.ovi.com/1.0/" + mMusicStore + "/releases/recommend/?"); |
137 constructRequest( queryRecommendation ); |
142 constructRequest( queryRecommendation ); |
138 TX_LOG_ARGS( "queryRecommendation : " << queryRecommendation ); |
143 // TODO: Store the token to a cenrep key |
|
144 // TODO: Tokens change per new ovi api release. |
|
145 // Need to figure out a way to get them updated on the fly |
|
146 queryRecommendation.append("&Token=03574704-e3d1-4466-9691-e0b34c7abfff"); |
|
147 |
|
148 TX_LOG_ARGS( queryRecommendation ); |
139 retrieveInformation( queryRecommendation ); |
149 retrieveInformation( queryRecommendation ); |
|
150 mRequestType = InspireMeItemsMetadataRequest; |
140 TX_EXIT |
151 TX_EXIT |
141 } |
152 } |
142 |
153 |
143 void MpQueryManager::clearRecommendations() |
154 void MpQueryManager::clearRecommendations() |
144 { |
155 { |
145 TX_ENTRY |
156 TX_ENTRY |
|
157 mRecommendationCount = 0; |
146 mDownloadedAlbumArts = 0; |
158 mDownloadedAlbumArts = 0; |
147 mAlbumArtsReadyCount = 0; |
159 mAlbumArtsReadyCount = 0; |
148 for ( int i = 0; i < KRecommendationCount; i++ ) { |
160 mRecommendationSongs.clear(); |
149 mRecommendationSongs.clear(); |
161 mRecommendationArtists.clear(); |
150 mRecommendationArtists.clear(); |
162 mRecommendationAlbumArtsLink.clear(); |
151 mRecommendationAlbumArtsLink.clear(); |
163 mRecommendationAlbumArtsMap.clear(); |
152 mRecommendationAlbumArtsMap.clear(); |
164 for ( int i = 0; i < mRecommendationAlbumArtsName.count(); ++i ) { |
153 QFile file( mRecommendationAlbumArtsName.at( i ) ); |
165 QFile file( mRecommendationAlbumArtsName.at( i ) ); |
154 if ( file.exists() ) { |
166 TX_LOG_ARGS( "File " << file.fileName() << " exists: " << file.exists() ); |
155 if ( file.remove() ) { |
167 if ( file.exists() && file.remove() ) { |
156 TX_LOG_ARGS( "File removed - " << file.fileName() ); |
168 TX_LOG_ARGS( "File " << file.fileName() << " removed"); |
157 } |
|
158 else { |
|
159 TX_LOG_ARGS( "Cannot remove file - " << file.fileName() ); |
|
160 } |
|
161 } else { |
|
162 TX_LOG_ARGS( "File doesn't exist - " << file.fileName() ); |
|
163 } |
169 } |
164 } |
170 } |
165 TX_EXIT |
171 TX_EXIT |
166 } |
172 } |
167 |
173 |
168 /*! |
174 |
169 Return recommendation songs |
175 |
170 */ |
176 /*! |
171 QStringList MpQueryManager::recommendationSongs() |
177 Returns the Local Music Store(if available) to be used while querying "Inspire Me" Items |
172 { |
178 */ |
173 TX_LOG |
179 void MpQueryManager::queryLocalMusicStore() |
174 return mRecommendationSongs; |
180 { |
|
181 TX_ENTRY |
|
182 QString imsi,mcc; |
|
183 |
|
184 XQSysInfo sysInfo( this ); |
|
185 imsi = sysInfo.imsi(); |
|
186 mcc= imsi.left(3); |
|
187 TX_LOG_ARGS( "mcc : " << mcc ); |
|
188 |
|
189 QString queryLocalMusicStore("http://api.music.cq1.brislabs.com/1.0/?mcc=" + mcc + "&token=06543e34-0261-40a4-a03a-9e09fe110c1f"); |
|
190 TX_LOG_ARGS( "queryLocalMusicStore : " << queryLocalMusicStore ); |
|
191 retrieveInformation( queryLocalMusicStore ); |
|
192 mRequestType = LocalStoreRequest; |
|
193 TX_EXIT |
|
194 } |
|
195 |
|
196 |
|
197 int MpQueryManager::recommendationsCount() const |
|
198 { |
|
199 TX_LOG_ARGS ("count: " << mRecommendationSongs.count()); |
|
200 return mRecommendationSongs.count(); |
|
201 } |
|
202 |
|
203 QString MpQueryManager::recommendedSong(int index) const |
|
204 { |
|
205 QString result; |
|
206 if( (0 <= index) && (index < mRecommendationSongs.count())) { |
|
207 result = mRecommendationSongs.at(index); |
|
208 } |
|
209 TX_LOG_ARGS ("recommendedSong: " << result); |
|
210 return result; |
175 } |
211 } |
176 |
212 |
177 /*! |
213 /*! |
178 Return recommendation artists |
214 Return recommendation artists |
179 */ |
215 */ |
180 QStringList MpQueryManager::recommendationArtists() |
216 QString MpQueryManager::recommendedArtist(int index) const |
181 { |
217 { |
182 TX_LOG |
218 QString result; |
183 return mRecommendationArtists; |
219 if( (0 <= index) && (index < mRecommendationArtists.count())) { |
184 } |
220 result = mRecommendationArtists.at(index); |
185 |
221 } |
186 /*! |
222 TX_LOG_ARGS ("recommendedArtist: " << result); |
187 Return recommendation album arts links |
223 return result; |
188 */ |
|
189 QStringList MpQueryManager::recommendationAlbumArtsLink() |
|
190 { |
|
191 TX_LOG |
|
192 return mRecommendationAlbumArtsLink; |
|
193 } |
|
194 |
|
195 /*! |
|
196 Return map of name and pixmap |
|
197 */ |
|
198 QMap<QString, QPixmap> MpQueryManager::recommendationAlbumArtsMap() |
|
199 { |
|
200 TX_LOG |
|
201 return mRecommendationAlbumArtsMap; |
|
202 } |
|
203 |
|
204 /*! |
|
205 Insert one uri & pixmap item into map |
|
206 */ |
|
207 void MpQueryManager::insertMapItem( const QString &uri, const QPixmap &pixmap ) |
|
208 { |
|
209 TX_ENTRY_ARGS( "Map Item URI: " << uri ); |
|
210 mRecommendationAlbumArtsMap.insert( uri, pixmap ); |
|
211 TX_EXIT |
|
212 } |
224 } |
213 |
225 |
214 /*! |
226 /*! |
215 Slot to call when getting response |
227 Slot to call when getting response |
216 */ |
228 */ |
219 TX_ENTRY |
231 TX_ENTRY |
220 QString errorStr; |
232 QString errorStr; |
221 int errorLine; |
233 int errorLine; |
222 int errorColumn; |
234 int errorColumn; |
223 bool parsingSuccess; |
235 bool parsingSuccess; |
224 |
236 |
225 if ( reply->error() == QNetworkReply::NoError ) |
237 if ( reply->error() != QNetworkReply::NoError ) { |
226 { |
238 TX_LOG_ARGS("reply->error(): " << reply->error()); |
227 parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn ); |
239 signalError(); |
228 if ( parsingSuccess ) { |
240 return; |
229 handleParsedXML(); //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function. |
241 } |
230 } else { |
242 |
231 // TODO: agree on error handling |
243 parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn ); |
232 TX_LOG_ARGS( "XML parsing error" ); |
244 if ( !parsingSuccess ) { |
233 } |
245 TX_LOG_ARGS("Parsing Received Content Failed"); |
234 } |
246 signalError(); |
235 else |
247 return; |
236 { |
248 } |
237 // TODO: agree on error handling |
249 |
238 TX_LOG_ARGS( "Network error in retrieving Information" ); |
250 handleParsedXML(); //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function. |
239 emit networkError(); |
251 |
240 } |
252 mReplys.removeAll(reply); // remove it so that we wont process it again |
241 TX_EXIT |
253 reply->deleteLater(); // make sure reply is deleted, as we longer care about it |
|
254 |
|
255 TX_EXIT |
|
256 } |
|
257 |
|
258 void MpQueryManager::signalError() |
|
259 { |
|
260 TX_ENTRY; |
|
261 switch(mRequestType) { |
|
262 case InspireMeItemsMetadataRequest: |
|
263 TX_LOG_ARGS("emit inspireMeItemsRetrievalError"); |
|
264 emit inspireMeItemsRetrievalError(); |
|
265 break; |
|
266 case InspireMeItemsAlbumArtRequest: |
|
267 TX_LOG_ARGS("Warning: InspireMeItemsAlbumArtRequestError, will keep using the default AA icon"); |
|
268 break; |
|
269 case LocalStoreRequest: |
|
270 TX_LOG_ARGS("emit localMusicStoreRetrievalError"); |
|
271 emit localMusicStoreRetrievalError(); |
|
272 break; |
|
273 case NoRequest: |
|
274 default: |
|
275 TX_LOG_ARGS("Warning!! Possible uninitialized mRequestType"); |
|
276 break; |
|
277 } |
|
278 TX_EXIT |
242 } |
279 } |
243 |
280 |
244 /*! |
281 /*! |
245 Slot to call when there is network error |
282 Slot to call when there is network error |
246 */ |
283 */ |
247 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error ) |
284 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error ) |
248 { |
285 { |
|
286 TX_ENTRY_ARGS( "Network error for retrieving Information" << error); |
249 // TODO: agree on error handling |
287 // TODO: agree on error handling |
|
288 |
250 Q_UNUSED(error) |
289 Q_UNUSED(error) |
251 TX_ENTRY_ARGS( "Network error for retrieving Information" << error); |
290 |
|
291 disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
|
292 signalError(); |
252 TX_EXIT |
293 TX_EXIT |
253 } |
294 } |
254 |
295 |
255 /*! |
296 /*! |
256 Slot to call when there is ssl error |
297 Slot to call when there is ssl error |
257 */ |
298 */ |
258 void MpQueryManager::retrieveInformationSslErrors( const QList<QSslError> &/*error*/ ) |
299 void MpQueryManager::retrieveInformationSslErrors( const QList<QSslError> &/*error*/ ) |
259 { |
300 { |
260 // TODO: agree on error handling |
301 // TODO: agree on error handling |
261 TX_ENTRY_ARGS( "SSL error for retrieving Information" ); |
302 TX_ENTRY_ARGS( "SSL error for retrieving Information" ); |
|
303 disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
|
304 signalError(); |
262 TX_EXIT |
305 TX_EXIT |
263 } |
306 } |
264 |
307 |
265 /*! |
308 /*! |
266 Slot to call when downloading finished |
309 Slot to call when downloading finished |
267 */ |
310 */ |
268 void MpQueryManager::DownloadFinished( QNetworkReply* reply ) |
311 void MpQueryManager::albumArtDownloaded( QNetworkReply* reply ) |
269 { |
312 { |
270 TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts ); |
313 TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts ); |
271 if ( reply->error() == QNetworkReply::NoError ) |
314 TX_ENTRY_ARGS( "QNetworkReply obj " << reply); |
272 { |
315 |
|
316 // It seems we get several finished signals for the same reply obj |
|
317 // do nothing if we get a second signal |
|
318 if( mReplys.indexOf(reply) == -1 ) { |
|
319 TX_LOG_ARGS("Warning: QNetworkReply AA request may have been processed in previous call: " << reply ); |
|
320 return; |
|
321 } |
|
322 |
|
323 if ( reply->error() == QNetworkReply::NoError ) { |
|
324 |
273 QString fileName = mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ); |
325 QString fileName = mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ); |
274 QByteArray imageData = reply->readAll(); |
326 QByteArray imageData = reply->readAll(); |
275 bool ret = writeImageToFile( imageData, fileName ); |
327 bool ret = writeImageToFile( imageData, fileName ); |
276 |
328 |
277 // If file writing went OK, emit a signal with the real filename |
329 // If file writing went OK, emit a signal with the real filename |
278 // If it failed, use empty filename (since file was removed in any case) |
330 // If it failed, use empty filename (since file was removed in any case) |
279 if ( ret ) |
331 if ( ret ) { |
280 { |
332 // TODO: If album album arts come in different order than they have been asked, |
|
333 // then inspire me items will use swapped album arts. Correct |
281 setAlbumArtUri( mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), |
334 setAlbumArtUri( mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), |
282 mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) ); |
335 mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) ); |
283 } |
336 } |
284 else |
337 else { |
285 { |
|
286 setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), ""); |
338 setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), ""); |
287 } |
339 } |
288 } |
340 ++mDownloadedAlbumArts; |
289 else |
341 mReplys.removeAll(reply); // remove it so that we wont process it again |
290 { |
342 reply->deleteLater(); // make sure reply is deleted, as we longer care about it |
291 TX_LOG_ARGS( "Downloading album art failed!" ); |
343 } |
292 emit networkError(); |
344 else { |
293 } |
345 TX_LOG_ARGS( "Error: Downloading album art failed! Will keep using the default AA" ); |
294 |
346 } |
295 mDownloadedAlbumArts++; |
347 |
|
348 if( mDownloadedAlbumArts == mRecommendationCount) { |
|
349 // no need to be informed anymore |
|
350 mAlbumArtDownloader->disconnect(this); |
|
351 } |
|
352 |
296 TX_EXIT |
353 TX_EXIT |
297 } |
354 } |
298 |
355 |
299 /*! |
356 /*! |
300 Write the image data to a file with the given filename. |
357 Write the image data to a file with the given filename. |
301 If writing operation fails for any reason (e.g. OOD), |
358 If writing operation fails for any reason (e.g. OOD), |
302 returns false, otherwise true. |
359 returns false, otherwise true. |
303 */ |
360 */ |
304 bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName ) |
361 bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName ) |
305 { |
362 { |
306 bool ret( false ); |
363 bool ret( false ); |
307 TX_ENTRY_ARGS( "imagefile: " << aImageFileName ); |
364 TX_ENTRY_ARGS( "imagefile: " << aImageFileName ); |
308 if ( aImageFileName.isEmpty() ) |
365 if ( aImageFileName.isEmpty() ) { |
309 { |
|
310 TX_LOG_ARGS( "Only store two album arts" ); |
366 TX_LOG_ARGS( "Only store two album arts" ); |
311 } |
367 } |
312 else |
368 else { |
313 { |
|
314 QFile file( aImageFileName ); |
369 QFile file( aImageFileName ); |
315 |
370 if ( !file.open( QIODevice::ReadWrite ) ) { |
316 if ( !file.open( QIODevice::ReadWrite ) ) |
|
317 { |
|
318 TX_LOG_ARGS( "Unable to open file" ); |
371 TX_LOG_ARGS( "Unable to open file" ); |
319 } |
372 } |
320 else |
373 else { |
321 { |
|
322 qint64 writtenBytes = file.write( aImageData ); |
374 qint64 writtenBytes = file.write( aImageData ); |
323 |
|
324 // Verify file write status |
375 // Verify file write status |
325 if ( writtenBytes < aImageData.size() ) |
376 if ( writtenBytes < aImageData.size() ) { |
326 { |
|
327 // If write succeeded only partially, or completely failed, |
377 // If write succeeded only partially, or completely failed, |
328 // remove the file from filesystem to remove risk of corruption |
378 // remove the file from filesystem to remove risk of corruption |
329 TX_LOG_ARGS( "Wrote only " << writtenBytes << " bytes, aborting operation!" ); |
379 TX_LOG_ARGS( "Wrote only " << writtenBytes << " bytes, aborting operation!" ); |
330 file.close(); |
380 file.close(); |
331 QFile::remove( mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) ); |
381 QFile::remove( mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) ); |
332 } |
382 } |
333 else |
383 else { |
334 { |
|
335 // If write fully succeeded, flush contents |
384 // If write fully succeeded, flush contents |
336 TX_LOG_ARGS( "Wrote all the bytes (" << writtenBytes << "), flushing and closing!"); |
385 TX_LOG_ARGS( "Wrote all the bytes (" << writtenBytes << "), flushing and closing!"); |
337 file.flush(); |
386 file.flush(); |
338 file.close(); |
387 file.close(); |
339 ret = true; |
388 ret = true; |
340 } |
|
341 } |
389 } |
342 } |
390 } |
|
391 } |
343 TX_LOG_ARGS( "Returning with value: " << ret ); |
392 TX_LOG_ARGS( "Returning with value: " << ret ); |
344 TX_EXIT |
393 TX_EXIT |
345 return ret; |
394 return ret; |
346 } |
395 } |
347 |
396 |
348 /*! |
397 /*! |
349 Get Atom response from Ovi server based on query |
398 Get Atom response from Ovi server based on query |
350 */ |
399 */ |
351 void MpQueryManager::retrieveInformation( const QString &urlEncoded ) |
400 void MpQueryManager::retrieveInformation( const QString &urlEncoded ) |
352 { |
401 { |
353 TX_ENTRY_ARGS( "urlEconded = " << urlEncoded) |
402 TX_ENTRY_ARGS( "urlEconded = " << urlEncoded) |
354 connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
403 connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ), Qt::UniqueConnection ); |
355 QNetworkReply *reply = mManager->get( QNetworkRequest( QUrl( urlEncoded ) ) ); |
404 QNetworkReply *reply = mManager->get( QNetworkRequest( QUrl( urlEncoded ) ) ); |
356 mReplys.append( reply ); |
405 mReplys.append( reply ); |
357 |
406 |
358 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
407 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
359 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) ); |
408 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) ); |
367 void MpQueryManager::handleParsedXML() |
416 void MpQueryManager::handleParsedXML() |
368 { |
417 { |
369 TX_ENTRY |
418 TX_ENTRY |
370 QDomElement rootElement = mDomDocument.documentElement(); |
419 QDomElement rootElement = mDomDocument.documentElement(); |
371 |
420 |
372 if ( rootElement.attribute( "type" ) == "search" ) { |
421 if ( rootElement.attribute( "type" ) == "recommendedTracks" ) { |
373 TX_LOG_ARGS( "URI response" ) |
422 TX_LOG_ARGS( "Recommendation response" ) |
374 QString result; |
|
375 QDomElement entry = rootElement.firstChildElement( "entry" ); |
423 QDomElement entry = rootElement.firstChildElement( "entry" ); |
376 while ( !entry.isNull() ) |
424 mRecommendationCount = 0; |
377 { |
425 while ( !entry.isNull() && mRecommendationCount < KRecommendationCount ) { |
378 if ( entry.attribute( "type" ) == "musictrack" ) { |
426 if ( entry.attribute( "type" ) == "musictrack" ) { |
379 QDomElement link = entry.firstChildElement( "link" ); |
427 QDomElement link = entry.firstChildElement( "link" ); |
380 while ( !link.isNull() ) |
428 while ( !link.isNull() ) { |
381 { |
|
382 if ( link.attribute( "rel" ) == "alternate" |
|
383 && link.attribute( "type" ) == "text/html" ) { |
|
384 result = link.attribute( "href" ); |
|
385 } |
|
386 link = link.nextSiblingElement( "link" ); |
|
387 } |
|
388 } |
|
389 entry = entry.nextSiblingElement( "entry" ); |
|
390 } |
|
391 // Signal that the url was received. Might be empty string. |
|
392 emit searchUrlRetrieved( result ); |
|
393 } else if ( rootElement.attribute( "type" ) == "recommendedTracks" ) { |
|
394 TX_LOG_ARGS( "Recommendation response" ) |
|
395 QDomElement entry = rootElement.firstChildElement( "entry" ); |
|
396 QNetworkReply *reply; |
|
397 int count = 0; |
|
398 while ( !entry.isNull() && count < KRecommendationCount ) |
|
399 { |
|
400 if ( entry.attribute( "type" ) == "musictrack" ) { |
|
401 QDomElement link = entry.firstChildElement( "link" ); |
|
402 while ( !link.isNull() ) |
|
403 { |
|
404 if ( link.attribute( "title" ) == "albumart100" ) { |
429 if ( link.attribute( "title" ) == "albumart100" ) { |
405 mRecommendationAlbumArtsLink.append( link.attribute( "href" ) ); |
430 mRecommendationAlbumArtsLink.append( link.attribute( "href" ) ); |
|
431 // TODO: This may get called twice for one inspire me item. Investigate why |
|
432 mRecommendationAlbumArtsMap.insert( link.attribute( "href" ), mDefaultRecommendationAlbumArt ); |
406 break; |
433 break; |
407 } else { |
434 } |
|
435 else { |
408 link = link.nextSiblingElement( "link" ); |
436 link = link.nextSiblingElement( "link" ); |
409 } |
437 } |
410 } |
438 } |
411 QDomElement metadata = entry.firstChildElement( "metadata" ); |
439 QDomElement metadata = entry.firstChildElement( "metadata" ); |
412 mRecommendationSongs.append( metadata.firstChildElement( "name" ).text() ); |
440 mRecommendationSongs.append( metadata.firstChildElement( "name" ).text() ); |
413 mRecommendationArtists.append( metadata.firstChildElement( "primaryartist" ).text() ); |
441 mRecommendationArtists.append( metadata.firstChildElement( "primaryartist" ).text() ); |
414 count++; |
442 ++mRecommendationCount; |
415 } |
443 } |
416 entry = entry.nextSiblingElement( "entry" ); |
444 entry = entry.nextSiblingElement( "entry" ); |
417 } |
445 } |
418 |
446 |
419 for (int i = 0; i < KRecommendationCount; i++ ) { |
447 emit inspireMeItemsMetadataRetrieved(); |
|
448 |
|
449 QNetworkReply *reply = 0; |
|
450 // we need to channel the retrieved album arts to albumArtDownloaded slot only |
|
451 disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) ); |
|
452 for (int i = 0; i < mRecommendationCount; i++ ) { |
420 TX_LOG_ARGS( "song name: " << mRecommendationSongs.at(i) ); |
453 TX_LOG_ARGS( "song name: " << mRecommendationSongs.at(i) ); |
421 TX_LOG_ARGS( "Artist name: " << mRecommendationArtists.at(i) ); |
454 TX_LOG_ARGS( "Artist name: " << mRecommendationArtists.at(i) ); |
422 TX_LOG_ARGS( "Album art link: " << mRecommendationAlbumArtsLink.at(i) ); |
455 TX_LOG_ARGS( "Album art link: " << mRecommendationAlbumArtsLink.at(i) ); |
423 |
456 mRequestType = InspireMeItemsAlbumArtRequest; |
424 if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) { |
457 if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) { |
425 reply = mDownloadManager->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) ); |
458 reply = mAlbumArtDownloader->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) ); |
426 mReplys.append( reply ); |
459 mReplys.append( reply ); |
427 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
460 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) ); |
428 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) ); |
461 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) ); |
429 } |
462 } |
430 } |
463 } |
431 } else { |
464 // we have queried for album arts for inspire me items. Now, time to wait for a response |
|
465 connect( mAlbumArtDownloader, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( albumArtDownloaded( QNetworkReply * ) ) ); |
|
466 |
|
467 } |
|
468 else if ( rootElement.attribute( "type" ) == "storeList" ) { |
|
469 TX_LOG_ARGS( "Music Store List" ) |
|
470 QDomElement entry = rootElement.firstChildElement( "workspace" ); |
|
471 QString previousMusicStore = mMusicStore; |
|
472 mMusicStore = entry.attribute( "countryCode" ); |
|
473 if(!mMusicStore.isEmpty()) { |
|
474 bool musicStoreUpdated = (previousMusicStore != mMusicStore); |
|
475 TX_LOG_ARGS("Music Store" << mMusicStore ); |
|
476 emit localMusicStoreRetrieved(musicStoreUpdated); |
|
477 } |
|
478 else { |
|
479 emit localMusicStoreRetrievalError(); |
|
480 } |
|
481 } |
|
482 else { |
432 TX_LOG_ARGS( "Not supported response" ) |
483 TX_LOG_ARGS( "Not supported response" ) |
433 } |
484 } |
434 TX_EXIT |
485 TX_EXIT |
435 } |
486 } |
436 |
487 |
|
488 void MpQueryManager::clearThumbnails() |
|
489 { |
|
490 TX_ENTRY |
|
491 for(int i = 0; i < mThumbnailRequests.count(); ++i ) { |
|
492 mThumbnailManager->cancelRequest(mThumbnailRequests.at(i)); |
|
493 } |
|
494 mThumbnailRequests.clear(); |
|
495 for(int i = 0; i < mRecommendationAlbumArtsName.count(); ++i) { |
|
496 mThumbnailManager->deleteThumbnails(mRecommendationAlbumArtsName.at(i)); // async, returns immidiately |
|
497 } |
|
498 TX_EXIT |
|
499 } |
|
500 |
|
501 void MpQueryManager::reset() |
|
502 { |
|
503 TX_ENTRY |
|
504 mManager->disconnect(this); |
|
505 mAlbumArtDownloader->disconnect(this); |
|
506 mThumbnailManager->disconnect(this); |
|
507 clearNetworkReplies(); |
|
508 clearRecommendations(); |
|
509 clearThumbnails(); |
|
510 mRecommendationAlbumArtsMap.clear(); |
|
511 TX_EXIT |
|
512 } |
|
513 |
437 /*! |
514 /*! |
438 Construct the query for fetching URI & recommendations |
515 Construct the query for fetching URI & recommendations |
439 */ |
516 */ |
440 void MpQueryManager::constructRequest( QString &uri ) |
517 void MpQueryManager::constructRequest( QString &uri ) |
441 { |
518 { |
484 /*! |
561 /*! |
485 Sets recommendation album art |
562 Sets recommendation album art |
486 */ |
563 */ |
487 void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName ) |
564 void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName ) |
488 { |
565 { |
|
566 // TODO: rename this function. Doing too many things |
489 TX_ENTRY_ARGS( "albumArtUri = " << albumArtUri ) |
567 TX_ENTRY_ARGS( "albumArtUri = " << albumArtUri ) |
490 TX_LOG_ARGS( "albumArtName = " << albumArtName ) |
568 TX_LOG_ARGS( "albumArtName = " << albumArtName ) |
491 if ( !albumArtUri.isEmpty() && !albumArtName.isEmpty() ) { |
569 if ( !albumArtUri.isEmpty() && !albumArtName.isEmpty() ) { |
|
570 // TODO: this is no good to pass the address of the albumArtUri. It is an item in the list, which can cleaned |
492 int id = mThumbnailManager->getThumbnail( albumArtName, reinterpret_cast<void *>( const_cast<QString *>( &albumArtUri ) ) ); |
571 int id = mThumbnailManager->getThumbnail( albumArtName, reinterpret_cast<void *>( const_cast<QString *>( &albumArtUri ) ) ); |
493 if ( id == KUndefined ) { |
572 if ( id == KUndefined ) { |
494 // Request failed. Set default album art. |
573 // Request failed. Set default album art |
495 insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt ); |
574 mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt ); |
|
575 } |
|
576 else { |
|
577 // Async request went throu |
|
578 TX_LOG_ARGS("Request to thumbnail manager made. Id: " << id) |
|
579 mThumbnailRequests.append(id); |
|
580 mThumbnailManager->disconnect( this ); // to prevent multiple same connections with thumbnailmanager |
|
581 QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ), |
|
582 this, SLOT( thumbnailReady( QPixmap , void * , int , int ) ) ); |
496 } |
583 } |
497 } |
584 } |
498 else { |
585 else { |
499 // No album art uri. Set default album art. |
586 // No album art uri. Set default album art. |
500 insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt ); |
587 mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt ); |
501 } |
588 } |
502 TX_EXIT |
589 TX_EXIT |
503 } |
590 } |
504 |
591 |
505 /*! |
592 /*! |
506 Slot to handle the recommendation album art |
593 Slot to handle the recommendation album art |
507 */ |
594 */ |
508 void MpQueryManager::thumbnailReady( |
595 void MpQueryManager::thumbnailReady( |
509 const QPixmap& pixmap, |
596 const QPixmap pixmap, |
510 void *data, |
597 void *data, |
511 int /*id*/, |
598 int id, |
512 int error ) |
599 int error ) |
513 { |
600 { |
514 TX_ENTRY |
601 TX_ENTRY |
515 // TODO: Hkn: use qobject_cast |
602 |
|
603 if( mThumbnailRequests.indexOf(id) == -1 ) { |
|
604 TX_LOG_ARGS("Warning: some old thumbnail request from previous song. Ignoring") |
|
605 return; |
|
606 } |
|
607 |
|
608 // TODO: Using data from array, which can be reset. There must be a safer way |
516 QString uri = *( reinterpret_cast<QString *>( data ) ); |
609 QString uri = *( reinterpret_cast<QString *>( data ) ); |
517 TX_LOG_ARGS( "Uri: " << uri ); |
610 TX_LOG_ARGS( "Uri: " << uri ); |
518 |
611 |
519 if ( error == 0 ) { |
612 if ( error == 0 ) { |
520 TX_LOG_ARGS( "album art link: " << uri ); |
613 TX_LOG_ARGS( "album art link: " << uri ); |
521 insertMapItem( uri, pixmap ); |
614 mRecommendationAlbumArtsMap.insert( uri, HbIcon(QIcon(pixmap)) ); |
522 } else { |
615 } |
523 insertMapItem( uri, mDefaultRecommendationAlbumArt ); |
616 else { |
524 } |
617 mRecommendationAlbumArtsMap.insert( uri, mDefaultRecommendationAlbumArt ); |
525 if(++mAlbumArtsReadyCount == KRecommendationCount) { |
618 } |
526 emit recommendationAlbumArtsReady(); |
619 |
527 } |
620 emit inspireMeItemAlbumArtReady(); |
528 TX_EXIT |
621 TX_EXIT |
529 } |
622 } |
|
623 |
|
624 bool MpQueryManager::isLocalMusicStore() const |
|
625 { |
|
626 TX_LOG_ARGS( "isLocalMusicStore = " << !mMusicStore.isEmpty() ) |
|
627 return !mMusicStore.isEmpty(); |
|
628 } |
|
629 |
|
630 HbIcon MpQueryManager::recommendedAlbumArt(int index) const |
|
631 { |
|
632 TX_LOG_ARGS( "index = " << index ) |
|
633 return mRecommendationAlbumArtsMap.value( mRecommendationAlbumArtsLink.at( index ) ); |
|
634 } |