sbMetadataAlbumArtFetcher.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4  *=BEGIN SONGBIRD GPL
5  *
6  * This file is part of the Songbird web player.
7  *
8  * Copyright(c) 2005-2010 POTI, Inc.
9  * http://www.songbirdnest.com
10  *
11  * This file may be licensed under the terms of of the
12  * GNU General Public License Version 2 (the ``GPL'').
13  *
14  * Software distributed under the License is distributed
15  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
16  * express or implied. See the GPL for the specific language
17  * governing rights and limitations.
18  *
19  * You should have received a copy of the GPL along with this
20  * program. If not, go to http://www.gnu.org/licenses/gpl.html
21  * or write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  *=END SONGBIRD GPL
25  */
26 
27 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
29 //
30 // Songbird metadata album art fetcher.
31 //
32 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
34 
40 //------------------------------------------------------------------------------
41 //
42 // Songbird metadata album art fetcher imported services.
43 //
44 //------------------------------------------------------------------------------
45 
46 // Self imports.
48 
49 // Songbird imports.
50 #include <sbIAlbumArtListener.h>
51 #include <sbIMediaItem.h>
52 #include <sbMemoryUtils.h>
53 #include <sbStandardProperties.h>
54 #include <sbStringBundle.h>
55 
56 // Mozilla imports.
57 #include <nsComponentManagerUtils.h>
58 #include <nsArrayUtils.h>
59 #include <nsIFileURL.h>
60 #include <nsISimpleEnumerator.h>
61 #include <nsServiceManagerUtils.h>
62 #include <nsStringGlue.h>
63 #include <prlog.h>
64 
65 
72 #include "prlog.h"
73 #ifdef PR_LOGGING
74 static PRLogModuleInfo* gMetadataAlbumArtFetcherLog = nsnull;
75 #define TRACE(args) PR_LOG(gMetadataAlbumArtFetcherLog, PR_LOG_DEBUG, args)
76 #define LOG(args) PR_LOG(gMetadataAlbumArtFetcherLog, PR_LOG_WARN, args)
77 #ifdef __GNUC__
78 #define __FUNCTION__ __PRETTY_FUNCTION__
79 #endif
80 #else
81 #define TRACE(args) /* nothing */
82 #define LOG(args) /* nothing */
83 #endif /* PR_LOGGING */
84 
85 //------------------------------------------------------------------------------
86 //
87 // nsISupports implementation.
88 //
89 //------------------------------------------------------------------------------
90 
92 
93 
94 //------------------------------------------------------------------------------
95 //
96 // sbIAlbumArtFetcher implementation.
97 //
98 //------------------------------------------------------------------------------
99 
100 /* \brief try to fetch album art for the given list of media items
101  * \param aMediaItems the list of media items that we're looking for album art
102  * \param aListener the listener to inform of success or failure
103  */
104 
105 NS_IMETHODIMP
106 sbMetadataAlbumArtFetcher::FetchAlbumArtForAlbum(nsIArray* aMediaItems,
107  sbIAlbumArtListener* aListener)
108 {
109  TRACE(("%s[%.8x]", __FUNCTION__, this));
110  // Validate arguments.
111  NS_ENSURE_ARG_POINTER(aMediaItems);
112  nsresult rv;
113 
114  nsCOMPtr<nsISimpleEnumerator> listEnum;
115  rv = aMediaItems->Enumerate(getter_AddRefs(listEnum));
116  NS_ENSURE_SUCCESS(rv, rv);
117 
118  PRBool hasMore;
119  rv = listEnum->HasMoreElements(&hasMore);
120  NS_ENSURE_SUCCESS(rv, rv);
121  if (!hasMore) {
122  return NS_ERROR_NOT_AVAILABLE;
123  }
124 
125  // Get the metadata manager.
126  nsCOMPtr<sbIMetadataManager> metadataManager =
127  do_GetService("@songbirdnest.com/Songbird/MetadataManager;1", &rv);
128  NS_ENSURE_SUCCESS(rv, rv);
129 
130  // Stash the album art source list into temporary variable in case
131  // it's changed from underneath us.
132  // (attempt to fix bug 19617/20161)
133  nsCOMPtr<nsIArray> sourceList = mAlbumArtSourceList;
134 
135  while (NS_SUCCEEDED(listEnum->HasMoreElements(&hasMore)) && hasMore) {
136  nsCOMPtr<nsISupports> next;
137  if (NS_SUCCEEDED(listEnum->GetNext(getter_AddRefs(next))) && next) {
138  nsCOMPtr<sbIMediaItem> mediaItem(do_QueryInterface(next, &rv));
139  if (NS_SUCCEEDED(rv) && mediaItem) {
140  rv = GetImageForItem(mediaItem, sourceList,
141  metadataManager, aListener);
142  if (NS_FAILED(rv) && aListener) {
143  aListener->OnTrackResult(nsnull, mediaItem);
144  }
145  }
146  } else {
147  // Something bad happened that has more returned yes but we could not
148  // get the next item.
149  break;
150  }
151  }
152 
153  if (aListener) {
154  aListener->OnSearchComplete(aMediaItems);
155  }
156  return NS_OK;
157 }
158 
159 NS_IMETHODIMP
160 sbMetadataAlbumArtFetcher::FetchAlbumArtForTrack(sbIMediaItem* aMediaItem,
161  sbIAlbumArtListener* aListener)
162 {
163  TRACE(("%s[%.8x]", __FUNCTION__, this));
164  // Validate arguments.
165  NS_ENSURE_ARG_POINTER(aMediaItem);
166  nsresult rv;
167 
168  // Throw this item into an array and call the Album version so we don't
169  // duplicate code. We can do this since we always go through each item
170  // anyways.
171  nsCOMPtr<nsIMutableArray> items =
172  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
173  NS_ENSURE_SUCCESS(rv, rv);
174  rv = items->AppendElement(NS_ISUPPORTS_CAST(sbIMediaItem*, aMediaItem),
175  PR_FALSE);
176  NS_ENSURE_SUCCESS(rv, rv);
177 
178  return FetchAlbumArtForAlbum(items, aListener);
179 }
180 
181 /* \brief shut down the fetcher
182  */
183 
184 NS_IMETHODIMP
185 sbMetadataAlbumArtFetcher::Shutdown()
186 {
187  TRACE(("%s[%.8x]", __FUNCTION__, this));
188  mAlbumArtService = nsnull;
189  return NS_OK;
190 }
191 
192 
193 //
194 // Getters/setters.
195 //
196 
201 NS_IMETHODIMP
202 sbMetadataAlbumArtFetcher::GetShortName(nsAString& aShortName)
203 {
204  TRACE(("%s[%.8x]", __FUNCTION__, this));
205  aShortName.AssignLiteral("metadata");
206  return NS_OK;
207 }
208 
209 
216 NS_IMETHODIMP
217 sbMetadataAlbumArtFetcher::GetName(nsAString& aName)
218 {
219  TRACE(("%s[%.8x]", __FUNCTION__, this));
220  sbStringBundle stringBundle;
221  aName.Assign(stringBundle.Get("songbird.albumart.metadata.name"));
222  return NS_OK;
223 }
224 
225 
231 NS_IMETHODIMP
232 sbMetadataAlbumArtFetcher::GetDescription(nsAString& aDescription)
233 {
234  TRACE(("%s[%.8x]", __FUNCTION__, this));
235  sbStringBundle stringBundle;
236  aDescription.Assign(stringBundle.Get("songbird.albumart.metadata.description"));
237  return NS_OK;
238 }
239 
240 
245 NS_IMETHODIMP
246 sbMetadataAlbumArtFetcher::GetIsLocal(PRBool* aIsLocal)
247 {
248  TRACE(("%s[%.8x]", __FUNCTION__, this));
249  NS_ENSURE_ARG_POINTER(aIsLocal);
250  *aIsLocal = PR_TRUE;
251  return NS_OK;
252 }
253 
258 NS_IMETHODIMP
259 sbMetadataAlbumArtFetcher::GetIsEnabled(PRBool* aIsEnabled)
260 {
261  TRACE(("%s[%.8x]", __FUNCTION__, this));
262  NS_ENSURE_ARG_POINTER(aIsEnabled);
263  NS_ENSURE_STATE(mPrefService);
264 
265  nsresult rv = mPrefService->GetBoolPref("songbird.albumart.metadata.enabled",
266  aIsEnabled);
267  if (NS_FAILED(rv)) {
268  *aIsEnabled = PR_FALSE;
269  }
270 
271  return NS_OK;
272 }
273 
274 NS_IMETHODIMP
275 sbMetadataAlbumArtFetcher::SetIsEnabled(PRBool aIsEnabled)
276 {
277  TRACE(("%s[%.8x]", __FUNCTION__, this));
278  NS_ENSURE_STATE(mPrefService);
279  return mPrefService->SetBoolPref("songbird.albumart.metadata.enabled",
280  aIsEnabled);
281 }
282 
287 NS_IMETHODIMP
288 sbMetadataAlbumArtFetcher::GetPriority(PRInt32* aPriority)
289 {
290  TRACE(("%s[%.8x]", __FUNCTION__, this));
291  NS_ENSURE_ARG_POINTER(aPriority);
292  NS_ENSURE_STATE(mPrefService);
293 
294  nsresult rv = mPrefService->GetIntPref("songbird.albumart.metadata.priority",
295  aPriority);
296  if (NS_FAILED(rv)) {
297  *aPriority = 0;
298  }
299 
300  return NS_OK;
301 }
302 
303 NS_IMETHODIMP
304 sbMetadataAlbumArtFetcher::SetPriority(PRInt32 aPriority)
305 {
306  TRACE(("%s[%.8x]", __FUNCTION__, this));
307  NS_ENSURE_STATE(mPrefService);
308  return mPrefService->SetIntPref("songbird.albumart.metadata.priority",
309  aPriority);
310 }
311 
312 
317 NS_IMETHODIMP
318 sbMetadataAlbumArtFetcher::GetAlbumArtSourceList(nsIArray** aAlbumArtSourceList)
319 {
320  TRACE(("%s[%.8x]", __FUNCTION__, this));
321  NS_ENSURE_ARG_POINTER(aAlbumArtSourceList);
322  NS_ADDREF(*aAlbumArtSourceList = mAlbumArtSourceList);
323  return NS_OK;
324 }
325 
326 NS_IMETHODIMP
327 sbMetadataAlbumArtFetcher::SetAlbumArtSourceList(nsIArray* aAlbumArtSourceList)
328 {
329  TRACE(("%s[%.8x]", __FUNCTION__, this));
330  mAlbumArtSourceList = aAlbumArtSourceList;
331  return NS_OK;
332 }
333 
334 
339 NS_IMETHODIMP
340 sbMetadataAlbumArtFetcher::GetIsFetching(PRBool* aIsFetching)
341 {
342  NS_ENSURE_ARG_POINTER(aIsFetching);
343  // This fetcher operates synchronously, so indicate that it's not fetching.
344  *aIsFetching = PR_FALSE;
345  return NS_OK;
346 }
347 
348 
349 //------------------------------------------------------------------------------
350 //
351 // Public services.
352 //
353 //------------------------------------------------------------------------------
354 
360 {
361  #ifdef PR_LOGGING
362  if (!gMetadataAlbumArtFetcherLog) {
363  gMetadataAlbumArtFetcherLog = PR_NewLogModule("sbMetadataAlbumArtFetcher");
364  }
365  #endif
366  TRACE(("%s[%.8x]", __FUNCTION__, this));
367 }
368 
369 
375 {
376  TRACE(("%s[%.8x]", __FUNCTION__, this));
377 }
378 
379 
384 nsresult
386 {
387  TRACE(("%s[%.8x]", __FUNCTION__, this));
388  nsresult rv;
389 
390  // Get the album art service.
391  mAlbumArtService = do_GetService(SB_ALBUMARTSERVICE_CONTRACTID, &rv);
392  NS_ENSURE_SUCCESS(rv, rv);
393 
394  // Get the preference branch.
395  mPrefService = do_GetService("@mozilla.org/preferences-service;1", &rv);
396  NS_ENSURE_SUCCESS(rv, rv);
397 
398  return NS_OK;
399 }
400 
401 
402 //------------------------------------------------------------------------------
403 //
404 // Internal services.
405 //
406 //------------------------------------------------------------------------------
407 
420 nsresult
421 sbMetadataAlbumArtFetcher::GetMetadataHandler
422  (nsIURI* aContentSrcURI,
423  nsIArray* aSourceList,
424  sbIMetadataManager* aManager,
425  sbIMetadataHandler** aMetadataHandler)
426 {
427  TRACE(("%s[%.8x]", __FUNCTION__, this));
428  // Validate arguments.
429  NS_ASSERTION(aContentSrcURI, "aContentSrcURI is null");
430  NS_ASSERTION(aMetadataHandler, "aMetadataHandler is null");
431 
432  // Function variables.
433  nsCOMPtr<sbIMetadataHandler> metadataHandler;
434  nsresult rv;
435 
436  // Try getting a metadata handler from the album art source list.
437  if (aSourceList) {
438  PRUint32 albumArtSourceListCount;
439  rv = aSourceList->GetLength(&albumArtSourceListCount);
440  NS_ENSURE_SUCCESS(rv, rv);
441  for (PRUint32 i = 0; i < albumArtSourceListCount; i++) {
442  metadataHandler = do_QueryElementAt(aSourceList, i, &rv);
443  if (NS_SUCCEEDED(rv))
444  break;
445  }
446  }
447 
448  // Try getting a metadata handler from the metadata manager.
449  if (!metadataHandler) {
450  nsCAutoString contentSrcURISpec;
451  rv = aContentSrcURI->GetSpec(contentSrcURISpec);
452  NS_ENSURE_SUCCESS(rv, rv);
453  NS_ENSURE_TRUE(aManager, NS_ERROR_NOT_INITIALIZED);
454  rv = aManager->GetHandlerForMediaURL
455  (NS_ConvertUTF8toUTF16(contentSrcURISpec),
456  getter_AddRefs(metadataHandler));
457  if (NS_FAILED(rv))
458  metadataHandler = nsnull;
459  }
460 
461  // Check if a metadata handler was found.
462  if (!metadataHandler)
463  return NS_ERROR_NOT_AVAILABLE;
464 
465  // Return results.
466  metadataHandler.forget(aMetadataHandler);
467 
468  return NS_OK;
469 }
470 
471 nsresult
472 sbMetadataAlbumArtFetcher::GetImageForItem(sbIMediaItem* aMediaItem,
473  nsIArray* aSourceList,
474  sbIMetadataManager* aManager,
475  sbIAlbumArtListener* aListener)
476 {
477  TRACE(("%s[%.8x]", __FUNCTION__, this));
478  // Validate arguments.
479  NS_ENSURE_ARG_POINTER(aMediaItem);
480 
481  // Function variables.
482  nsresult rv;
483 
484  // Do nothing if media item content is not a local file.
485  nsCOMPtr<nsIURI> contentSrcURI;
486  nsCOMPtr<nsIFileURL> contentSrcFileURL;
487  rv = aMediaItem->GetContentSrc(getter_AddRefs(contentSrcURI));
488  NS_ENSURE_SUCCESS(rv, rv);
489  contentSrcFileURL = do_QueryInterface(contentSrcURI, &rv);
490  NS_ENSURE_SUCCESS(rv, rv);
491 
492  // Get the metadata handler for the media item content. Do nothing more if
493  // none available.
494  nsCOMPtr<sbIMetadataHandler> metadataHandler;
495  rv = GetMetadataHandler(contentSrcURI, aSourceList, aManager,
496  getter_AddRefs(metadataHandler));
497  NS_ENSURE_SUCCESS(rv, rv);
498 
499  // Try reading the front cover metadata image.
500  nsCAutoString mimeType;
501  PRUint32 dataLength = 0;
502  PRUint8* data = nsnull;
503  rv = metadataHandler->GetImageData
505  mimeType,
506  &dataLength,
507  &data);
508  if (NS_FAILED(rv))
509  dataLength = 0;
510 
511  // If album art not found, try reading from other metadata image.
512  if (dataLength == 0) {
513  rv = metadataHandler->GetImageData
515  mimeType,
516  &dataLength,
517  &data);
518  if (NS_FAILED(rv))
519  dataLength = 0;
520  }
521 
522  // If no album art found, do nothing more.
523  if (dataLength == 0) {
524  return NS_ERROR_FAILURE;
525  }
526 
527  // Set up album art data for auto-disposal.
528  sbAutoNSMemPtr autoData(data);
529 
530  // Cache album art image.
531  nsCOMPtr<nsIURI> cacheURI;
532  NS_ENSURE_TRUE(mAlbumArtService, NS_ERROR_NOT_INITIALIZED);
533  rv = mAlbumArtService->CacheImage(mimeType,
534  data,
535  dataLength,
536  getter_AddRefs(cacheURI));
537  NS_ENSURE_SUCCESS(rv, rv);
538 
539  if (aListener) {
540  // Notify caller we found an image for this item
541  aListener->OnTrackResult(cacheURI, aMediaItem);
542  }
543 
544  return NS_OK;
545 }
546 
return NS_OK
#define SB_ALBUMARTSERVICE_CONTRACTID
nsString Get(const nsAString &aKey, const nsAString &aDefault=SBVoidString())
NS_DECL_ISUPPORTS NS_DECL_SBIALBUMARTFETCHER sbMetadataAlbumArtFetcher()
const PRUint32 METADATA_IMAGE_TYPE_OTHER
Constant for the type of image in the metadata, these are pulled from the taglib/attachedpictureframe...
The manager from which to request a metadata handler.
const PRUint32 METADATA_IMAGE_TYPE_FRONTCOVER
NS_IMPL_THREADSAFE_ISUPPORTS1(sbDeviceCapsCompatibility, sbIDeviceCapsCompatibility) sbDeviceCapsCompatibility
A component which is interested in the result of an album art fetch request.
#define TRACE(args)
An object capable of manipulating the metadata tags for a media file.
Songbird String Bundle Definitions.
_updateCookies aName
StringArrayEnumerator prototype hasMore
Songbird Metadata Album Art Fetcher Definitions.
Interface that defines a single item of media in the system.
Interface for an album art fetcher. Instantiate as a component instance.
observe data
Definition: FeedWriter.js:1329
_getSelectedPageStyle s i
function next()