sbDeviceLibrary.cpp
Go to the documentation of this file.
1 /* vim: set sw=2 :miv */
2 /*
3  *=BEGIN SONGBIRD GPL
4  *
5  * This file is part of the Songbird web player.
6  *
7  * Copyright(c) 2005-2011 POTI, Inc.
8  * http://www.songbirdnest.com
9  *
10  * This file may be licensed under the terms of of the
11  * GNU General Public License Version 2 (the ``GPL'').
12  *
13  * Software distributed under the License is distributed
14  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
15  * express or implied. See the GPL for the specific language
16  * governing rights and limitations.
17  *
18  * You should have received a copy of the GPL along with this
19  * program. If not, go to http://www.gnu.org/licenses/gpl.html
20  * or write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  *=END SONGBIRD GPL
24  */
25 
26 /* base class */
27 #include "sbDeviceLibrary.h"
28 
29 /* mozilla interfaces */
30 #include <nsIClassInfoImpl.h>
31 #include <nsIProgrammingLanguage.h>
32 #include <nsIFileURL.h>
33 #include <nsIPrefBranch.h>
34 #include <nsIPrefService.h>
35 #include <nsISupportsPrimitives.h>
36 #include <nsIVariant.h>
37 #include <nsIWritablePropertyBag2.h>
38 
39 /* nspr headers */
40 #include <prlog.h>
41 #include <prprf.h>
42 #include <prtime.h>
43 
44 /* mozilla headers */
45 #include <nsAppDirectoryServiceDefs.h>
46 #include <nsArrayUtils.h>
47 #include <nsAutoLock.h>
48 #include <nsAutoPtr.h>
49 #include <nsCOMArray.h>
51 #include <nsComponentManagerUtils.h>
52 #include <nsDirectoryServiceUtils.h>
53 #include <nsIFile.h>
54 #include <nsILocalFile.h>
55 #include <nsMemory.h>
56 #include <nsServiceManagerUtils.h>
57 #include <nsThreadUtils.h>
58 #include <nsXPCOM.h>
59 #include <nsXPCOMCIDInternal.h>
60 
61 /* songbird interfaces */
62 #include <sbIDevice.h>
63 #include <sbIDeviceCapabilities.h>
64 #include <sbIDeviceContent.h>
65 #include <sbIDeviceEvent.h>
66 #include <sbIDeviceEventTarget.h>
67 #include <sbIDeviceManager.h>
68 #include <sbIDeviceProperties.h>
69 #include <sbILibraryFactory.h>
70 #include <sbILibraryManager.h>
71 #include <sbILocalDatabaseSmartMediaList.h>
72 #include <sbIPrompter.h>
73 #include <sbIPropertyArray.h>
74 #include <sbIPropertyManager.h>
75 
76 /* songbird headers */
77 #include <sbDeviceLibraryHelpers.h>
79 #include <sbDeviceUtils.h>
80 #include <sbLibraryUtils.h>
81 #include <sbLocalDatabaseCID.h>
82 #include <sbMemoryUtils.h>
83 #include <sbPropertiesCID.h>
86 #include <sbStandardProperties.h>
87 #include <sbStringUtils.h>
88 #include <sbVariantUtils.h>
89 
90 #define SB_AUDIO_SMART_PLAYLIST "<sbaudio>"
91 
92 char const * const gMediaType[] = {
93  ".audio",
94  ".video",
95  ".image"
96 };
97 
98 
99 /* List of properties for which to sync updates. */
101 {
139 };
140 
143 
144 NS_INTERFACE_MAP_BEGIN(sbDeviceLibrary)
145  NS_IMPL_QUERY_CLASSINFO(sbDeviceLibrary)
146  NS_INTERFACE_MAP_ENTRY(sbIDeviceLibrary)
147  NS_INTERFACE_MAP_ENTRY(sbILibrary)
148  NS_INTERFACE_MAP_ENTRY(sbIMediaList)
149  NS_INTERFACE_MAP_ENTRY(sbIMediaItem)
150  NS_INTERFACE_MAP_ENTRY(sbILibraryResource)
151  NS_INTERFACE_MAP_ENTRY(sbIMediaListListener)
152  NS_INTERFACE_MAP_ENTRY(sbILocalDatabaseMediaListCopyListener)
153  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, sbIDeviceLibrary)
154 NS_INTERFACE_MAP_END
155 
157  nsIClassInfo,
159  sbILibrary,
160  sbIMediaList,
161  sbIMediaItem,
163 
164 NS_DECL_CLASSINFO(sbDeviceLibrary)
165 NS_IMPL_THREADSAFE_CI(sbDeviceLibrary)
166 
171 #ifdef PR_LOGGING
172 static PRLogModuleInfo* gDeviceLibraryLog = nsnull;
173 #define TRACE(args) PR_LOG(gDeviceLibraryLog, PR_LOG_DEBUG, args)
174 #define LOG(args) PR_LOG(gDeviceLibraryLog, PR_LOG_WARN, args)
175 #else
176 #define TRACE(args) /* nothing */
177 #define LOG(args) /* nothing */
178 #endif /* PR_LOGGING */
179 
181  : mDevice(aDevice),
182  mMonitor(nsnull)
183 {
184 #ifdef PR_LOGGING
185  if (!gDeviceLibraryLog) {
186  gDeviceLibraryLog = PR_NewLogModule("sbDeviceLibrary");
187  }
188 #endif
189  TRACE(("DeviceLibrary[0x%.8x] - Constructed", this));
190 }
191 
193 {
194  Finalize();
195 
196  if(mMonitor) {
197  nsAutoMonitor::DestroyMonitor(mMonitor);
198  }
199 
200  TRACE(("DeviceLibrary[0x%.8x] - Destructed", this));
201 }
202 
203 NS_IMETHODIMP
204 sbDeviceLibrary::Initialize(const nsAString& aLibraryId)
205 {
206  NS_ENSURE_FALSE(mMonitor, NS_ERROR_ALREADY_INITIALIZED);
207  mMonitor = nsAutoMonitor::NewMonitor(__FILE__ "sbDeviceLibrary::mMonitor");
208  NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
209  PRBool succeeded = mListeners.Init();
210  NS_ENSURE_TRUE(succeeded, NS_ERROR_OUT_OF_MEMORY);
211  return CreateDeviceLibrary(aLibraryId, nsnull);
212 }
213 
214 NS_IMETHODIMP
215 sbDeviceLibrary::Finalize()
216 {
217  nsresult rv;
218 
219  // unhook the main library listener
220  if (mMainLibraryListener) {
221  nsCOMPtr<sbILibrary> mainLib;
222  rv = GetMainLibrary(getter_AddRefs(mainLib));
223  NS_ASSERTION(NS_SUCCEEDED(rv), "WTF this should never fail");
224  // if we fail, meh, too bad, we still need to get on with the releasing
225  if (NS_SUCCEEDED(rv)) {
226  rv = mainLib->RemoveListener(mMainLibraryListener);
227  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to remove main lib listener");
228  }
229  mMainLibraryListener = nsnull;
230  }
231 
232  // remove the device event listener
233  nsCOMPtr<sbIDeviceEventTarget>
234  deviceEventTarget = do_QueryInterface(mDevice, &rv);
235  if (NS_SUCCEEDED(rv))
236  deviceEventTarget->RemoveEventListener(this);
237 
238  // remove device library listener
239  if (mDeviceLibrary) {
240  nsCOMPtr<sbIMediaList> list = do_QueryInterface(mDeviceLibrary);
241  if (list)
242  list->RemoveListener(this);
243  }
244 
245  if (mDeviceLibrary)
246  UnregisterDeviceLibrary();
247 
248  // let go of the owner device
249  mDevice = nsnull;
250 
251  // Don't null out mDeviceLibrary since there may be listeners on it that still
252  // need to be removed.
253 
254  return NS_OK;
255 }
256 
257 nsresult
258 sbDeviceLibrary::CreateDeviceLibrary(const nsAString &aDeviceIdentifier,
259  nsIURI *aDeviceDatabaseURI)
260 {
261  nsresult rv;
262  nsCOMPtr<sbILibraryFactory> libraryFactory =
263  do_GetService(SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID, &rv);
264  NS_ENSURE_SUCCESS(rv, rv);
265 
266  nsCOMPtr<nsIWritablePropertyBag2> libraryProps =
267  do_CreateInstance(NS_HASH_PROPERTY_BAG_CONTRACTID, &rv);
268  NS_ENSURE_SUCCESS(rv, rv);
269 
270  nsCOMPtr<nsIFile> libraryFile;
271  if(aDeviceDatabaseURI) {
272  //Use preferred database location.
273  nsCOMPtr<nsIFileURL> furl = do_QueryInterface(aDeviceDatabaseURI, &rv);
274  NS_ENSURE_SUCCESS(rv, rv);
275 
276  rv = furl->GetFile(getter_AddRefs(libraryFile));
277  NS_ENSURE_SUCCESS(rv, rv);
278  }
279  else {
280  //No preferred database location, fetch default location.
281  rv = GetDefaultDeviceLibraryDatabaseFile(aDeviceIdentifier,
282  getter_AddRefs(libraryFile));
283  NS_ENSURE_SUCCESS(rv, rv);
284  }
285 
286  rv = libraryProps->SetPropertyAsInterface(NS_LITERAL_STRING("databaseFile"),
287  libraryFile);
288  NS_ENSURE_SUCCESS(rv, rv);
289 
290 #ifdef PR_LOGGING
291  {
292  nsCAutoString str;
293  if(NS_SUCCEEDED(libraryFile->GetNativePath(str))) {
294  LOG(("Attempting to create device library with file path %s", str.get()));
295  }
296  }
297 #endif
298 
299  rv = libraryFactory->CreateLibrary(libraryProps,
300  getter_AddRefs(mDeviceLibrary));
301  NS_ENSURE_SUCCESS(rv, rv);
302 
303  // Store our guid in the inner device library
304  nsString deviceLibraryGuid;
305  rv = this->GetGuid(deviceLibraryGuid);
306  NS_ENSURE_SUCCESS(rv, rv);
307 
308  rv = mDeviceLibrary->SetProperty
309  (NS_LITERAL_STRING(SB_PROPERTY_DEVICE_LIBRARY_GUID),
310  deviceLibraryGuid);
311  NS_ENSURE_SUCCESS(rv, rv);
312 
313  // Don't allow writing metadata back to device media files. Let the device
314  // component handle property updates.
315  rv = this->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_DONT_WRITE_METADATA),
316  NS_LITERAL_STRING("1"));
317  NS_ENSURE_SUCCESS(rv, rv);
318 
319  nsCOMPtr<sbIDeviceLibrarySyncSettings> syncSettings;
320  rv = GetSyncSettings(getter_AddRefs(syncSettings));
321  NS_ENSURE_SUCCESS(rv, rv);
322 
323  nsCOMPtr<sbIMediaList> list;
324  list = do_QueryInterface(mDeviceLibrary, &rv);
325  NS_ENSURE_SUCCESS(rv, rv);
326 
327  // hook up listeners
328  rv = list->AddListener(this,
329  PR_FALSE,
336  nsnull);
337  NS_ENSURE_SUCCESS(rv, rv);
338 
339  nsCOMPtr<sbILibrary> mainLib;
340  rv = GetMainLibrary(getter_AddRefs(mainLib));
341  NS_ENSURE_SUCCESS(rv, rv);
342 
343  // add a device event listener to listen for changes to the is synced locally
344  // state
345  nsCOMPtr<sbIDeviceEventTarget>
346  deviceEventTarget = do_QueryInterface(mDevice, &rv);
347  NS_ENSURE_SUCCESS(rv, rv);
348  rv = deviceEventTarget->AddEventListener(this);
349  NS_ENSURE_SUCCESS(rv, rv);
350 
351  // hook up the listener now if we need to
352  mMainLibraryListener =
353  new sbLibraryUpdateListener(mDeviceLibrary,
354  PR_TRUE,
355  mDevice);
356  NS_ENSURE_TRUE(mMainLibraryListener, NS_ERROR_OUT_OF_MEMORY);
357 
358  mMainLibraryListenerFilter = do_CreateInstance
360  NS_ENSURE_SUCCESS(rv, rv);
361  nsAutoString voidString;
362  voidString.SetIsVoid(PR_TRUE);
363  nsAutoString propertyID;
364  PRUint32 propertyCount =
366  for (PRUint32 i = 0; i < propertyCount; i++) {
367  propertyID.AssignLiteral(sbDeviceLibrarySyncUpdatePropertyTable[i]);
368  rv = mMainLibraryListenerFilter->AppendProperty(propertyID, voidString);
369  NS_ENSURE_SUCCESS(rv, rv);
370  }
371 
372  // update the main library listeners
373  rv = UpdateMainLibraryListeners(syncSettings);
374  NS_ENSURE_SUCCESS(rv, rv);
375 
376  nsCOMPtr<sbILocalDatabaseSimpleMediaList> simpleList;
377  simpleList = do_QueryInterface(list, &rv);
378 
379  if(NS_SUCCEEDED(rv)) {
380  rv = simpleList->SetCopyListener(this);
381  NS_ENSURE_SUCCESS(rv, rv);
382  }
383  else {
384  NS_WARN_IF_FALSE(rv,
385  "Failed to get sbILocalDatabaseSimpleMediaList interface. Copy Listener disabled.");
386  }
387 
388  // update the library is read-only property
389  rv = UpdateIsReadOnly();
390  NS_ENSURE_SUCCESS(rv, rv);
391 
392  rv = RegisterDeviceLibrary();
393  NS_ENSURE_SUCCESS(rv, rv);
394 
395  return NS_OK;
396 }
397 
398 nsresult
399 sbDeviceLibrary::RegisterDeviceLibrary()
400 {
401 
402  nsresult rv;
403  nsCOMPtr<sbILibraryManager> libraryManager;
404  libraryManager =
405  do_GetService("@songbirdnest.com/Songbird/library/Manager;1", &rv);
406  NS_ENSURE_SUCCESS(rv, rv);
407 
408  return libraryManager->RegisterLibrary(this, PR_FALSE);
409 }
410 
411 nsresult
412 sbDeviceLibrary::UnregisterDeviceLibrary()
413 {
414  nsresult rv;
415  nsCOMPtr<sbILibraryManager> libraryManager;
416  libraryManager =
417  do_GetService("@songbirdnest.com/Songbird/library/Manager;1", &rv);
418  NS_ENSURE_SUCCESS(rv, rv);
419 
420  return libraryManager->UnregisterLibrary(this);
421 }
422 
423 /* static */ nsresult
425  (const nsAString& aDeviceIdentifier,
426  nsIFile** aDBFile)
427 {
428  NS_ENSURE_ARG_POINTER(aDBFile);
429 
430  nsresult rv;
431 
432  // Fetch default device library database file location.
433  nsCOMPtr<nsIFile> libraryFile;
434  rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
435  getter_AddRefs(libraryFile));
436  NS_ENSURE_SUCCESS(rv, rv);
437 
438  rv = libraryFile->Append(NS_LITERAL_STRING("db"));
439  NS_ENSURE_SUCCESS(rv, rv);
440 
441  PRBool exists = PR_FALSE;
442  rv = libraryFile->Exists(&exists);
443  NS_ENSURE_SUCCESS(rv, rv);
444  if(!exists) {
445  rv = libraryFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
446  NS_ENSURE_SUCCESS(rv, rv);
447  }
448 
449  nsAutoString filename(aDeviceIdentifier);
450  filename.AppendLiteral(".db");
451 
452  rv = libraryFile->Append(filename);
453  NS_ENSURE_SUCCESS(rv, rv);
454 
455  libraryFile.forget(aDBFile);
456 
457  return NS_OK;
458 }
459 
460 nsresult
461 sbDeviceLibrary::GetIsMgmtTypeSyncList(PRBool* aIsMgmtTypeSyncList)
462 {
463  NS_ASSERTION(aIsMgmtTypeSyncList, "aIsMgmtTypeSyncList is null");
464  nsresult rv;
465 
466  nsCOMPtr<sbIDeviceLibrarySyncSettings> syncSettings;
467  rv = GetSyncSettings(getter_AddRefs(syncSettings));
468  NS_ENSURE_SUCCESS(rv, rv);
469 
470  PRBool isSyncList = PR_FALSE;
471  PRUint32 mgmtType;
472  for (PRUint32 mediaType = 0;
474  ++mediaType) {
475  // Ignore management type for images, it is always semi-manual
476  if (mediaType == sbIDeviceLibrary::MEDIATYPE_IMAGE)
477  continue;
478 
479  nsCOMPtr<sbIDeviceLibraryMediaSyncSettings> mediaSyncSettings;
480  rv = syncSettings->GetMediaSettings(mediaType,
481  getter_AddRefs(mediaSyncSettings));
482  NS_ENSURE_SUCCESS(rv, rv);
483 
484  rv = mediaSyncSettings->GetMgmtType(&mgmtType);
485  NS_ENSURE_SUCCESS(rv, rv);
486 
487  // Manual mode.
489  break;
490  }
491 
492  // Sync playlist mode.
494  isSyncList = PR_TRUE;
495  break;
496  }
497  }
498 
499  *aIsMgmtTypeSyncList = isSyncList;
500  return NS_OK;
501 }
502 
503 nsresult
504 sbDeviceLibrary::GetIsMgmtTypeSyncAll(PRBool* aIsMgmtTypeSyncAll)
505 {
506  NS_ASSERTION(aIsMgmtTypeSyncAll, "aIsMgmtTypeSyncAll is null");
507  nsresult rv;
508 
509  nsCOMPtr<sbIDeviceLibrarySyncSettings> syncSettings;
510  rv = GetSyncSettings(getter_AddRefs(syncSettings));
511  NS_ENSURE_SUCCESS(rv, rv);
512 
513  nsCOMPtr<sbIDeviceLibraryMediaSyncSettings> mediaSyncSettings;
514  rv = syncSettings->GetMediaSettings(sbIDeviceLibrary::MEDIATYPE_AUDIO,
515  getter_AddRefs(mediaSyncSettings));
516  NS_ENSURE_SUCCESS(rv, rv);
517 
518  // This is a hack for now, since we don't support video all yet.
519  PRUint32 mgmtType;
520  rv = mediaSyncSettings->GetMgmtType(&mgmtType);
521  NS_ENSURE_SUCCESS(rv, rv);
522 
524  *aIsMgmtTypeSyncAll = PR_TRUE;
525  }
526  else {
527  *aIsMgmtTypeSyncAll = PR_FALSE;
528  }
529 
530  return NS_OK;
531 }
532 
533 nsresult
534 sbDeviceLibrary::UpdateMainLibraryListeners(
535  sbIDeviceLibrarySyncSettings * aSyncSettings)
536 {
537  NS_ENSURE_STATE(mDevice);
538 
539  nsresult rv;
540 
541  nsCOMPtr<sbILibrary> mainLib;
542  rv = GetMainLibrary(getter_AddRefs(mainLib));
543  NS_ENSURE_SUCCESS(rv, rv);
544 
545  // TODO: XXX This code will probably need to be updated with the device
546  // listeners bug 23188
547  // hook up the metadata updating listener
548  rv = mainLib->AddListener(mMainLibraryListener,
549  PR_FALSE,
554  mMainLibraryListenerFilter);
555  NS_ENSURE_SUCCESS(rv, rv);
556 
557  return NS_OK;
558 }
559 
560 nsresult
561 sbDeviceLibrary::UpdateIsReadOnly()
562 {
563  nsresult rv;
564 
565  // Get the device properties.
566  nsCOMPtr<sbIDeviceProperties> baseDeviceProperties;
567  nsCOMPtr<nsIPropertyBag2> deviceProperties;
568  rv = mDevice->GetProperties(getter_AddRefs(baseDeviceProperties));
569  NS_ENSURE_SUCCESS(rv, rv);
570  rv = baseDeviceProperties->GetProperties(getter_AddRefs(deviceProperties));
571  NS_ENSURE_SUCCESS(rv, rv);
572 
573  // Get the access compatibility.
574  nsAutoString accessCompatibility;
575  rv = deviceProperties->GetPropertyAsAString
576  (NS_LITERAL_STRING(SB_DEVICE_PROPERTY_ACCESS_COMPATIBILITY),
577  accessCompatibility);
578  if (NS_FAILED(rv))
579  accessCompatibility.Truncate();
580 
581  // If device is read-only, mark library as such and return.
582  if (accessCompatibility.Equals(NS_LITERAL_STRING("ro"))) {
583  rv = this->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_ISREADONLY),
584  NS_LITERAL_STRING("1"));
585  NS_ENSURE_SUCCESS(rv, rv);
586  return NS_OK;
587  }
588 
589  // Mark library as read-write (TODO: XXX Not sure if we still need to do this
590  // but leaving it in as it doesn't hurt anything)
591  nsString str;
592  str.SetIsVoid(PR_TRUE);
593  rv = this->SetProperty(NS_LITERAL_STRING(SB_PROPERTY_ISREADONLY), str);
594  NS_ENSURE_SUCCESS(rv, rv);
595 
596  return NS_OK;
597 }
598 
600 sbDeviceLibrary::CreateSyncSettings()
601 {
602  nsresult rv;
603 
604  nsString guid;
605  rv = GetGuid(guid);
606  NS_ENSURE_SUCCESS(rv, nsnull);
607 
608  nsID* deviceID;
609  rv = mDevice->GetId(&deviceID);
610  NS_ENSURE_SUCCESS(rv, nsnull);
611  sbAutoNSMemPtr autoDeviceID(deviceID);
612 
613  return sbDeviceLibrarySyncSettings::New(*deviceID, guid);
614 }
619 NS_IMETHODIMP
620 sbDeviceLibrary::GetSyncSettings(sbIDeviceLibrarySyncSettings ** aSyncSettings)
621 {
622  NS_ENSURE_ARG_POINTER(aSyncSettings);
623 
624  nsresult rv;
625 
626  nsAutoMonitor lock(mMonitor);
627  if (!mSyncSettings) {
628  mSyncSettings = CreateSyncSettings();
629  NS_ENSURE_TRUE(mSyncSettings, NS_ERROR_OUT_OF_MEMORY);
630 
631  rv = mSyncSettings->Read(mDevice, this);
632  NS_ENSURE_SUCCESS(rv, rv);
633  }
634 
635  rv = CallQueryInterface(mSyncSettings.get(), aSyncSettings);
636  NS_ENSURE_SUCCESS(rv, rv);
637 
638  return NS_OK;
639 }
640 
641 nsresult
642 sbDeviceLibrary::GetSyncListsPrefKey(PRUint32 aContentType,
643  nsAString& aPrefKey)
644 {
645  NS_ENSURE_ARG_RANGE(aContentType,
648  NS_ENSURE_STATE(mDeviceLibrary);
649 
650  // Get the device library GUID
651  nsString guid;
652  nsresult rv = mDeviceLibrary->GetGuid(guid);
653  NS_ENSURE_SUCCESS(rv, rv);
654 
655  // Get the preference key
656  aPrefKey.Assign(NS_LITERAL_STRING(PREF_SYNC_PREFIX));
657  aPrefKey.Append(guid);
658  aPrefKey.AppendLiteral(PREF_SYNC_BRANCH);
659  aPrefKey.AppendLiteral(PREF_SYNC_LISTS);
660  aPrefKey.AppendLiteral(gMediaType[aContentType]);
661 
662  return NS_OK;
663 }
664 
665 #define SB_NOTIFY_LISTENERS(call) \
666  nsCOMArray<sbIDeviceLibraryListener> listeners; \
667  { \
668  nsAutoMonitor monitor(mMonitor); \
669  mListeners.EnumerateRead(AddListenersToCOMArrayCallback, &listeners); \
670  } \
671  \
672  PRInt32 count = listeners.Count(); \
673  for (PRInt32 index = 0; index < count; index++) { \
674  nsCOMPtr<sbIDeviceLibraryListener> listener = listeners.ObjectAt(index); \
675  NS_ASSERTION(listener, "Null listener!"); \
676  listener->call; \
677  } \
678 
679 // SB_NOTIFY_LISTENERS sets a return value according to the return value of the
680 // last listener call. This allows a single listener to suppress batch
681 // notifications to all other listeners. Use SB_NOTIFY_LISTENERS_RETURN_FALSE
682 // to prevent erroneous suppression of notifications.
683 #define SB_NOTIFY_LISTENERS_RETURN_FALSE(call) \
684  SB_NOTIFY_LISTENERS(call) \
685  *aNoMoreForBatch = PR_FALSE; \
686 
687 #define SB_NOTIFY_LISTENERS_ASK_PERMISSION(call) \
688  PRBool mShouldProcceed = PR_TRUE; \
689  PRBool mPerformAction = PR_TRUE; \
690  \
691  nsCOMArray<sbIDeviceLibraryListener> listeners; \
692  { \
693  nsAutoMonitor monitor(mMonitor); \
694  mListeners.EnumerateRead(AddListenersToCOMArrayCallback, &listeners); \
695  } \
696  \
697  PRInt32 count = listeners.Count(); \
698  for (PRInt32 index = 0; index < count; index++) { \
699  nsCOMPtr<sbIDeviceLibraryListener> listener = listeners.ObjectAt(index); \
700  NS_ASSERTION(listener, "Null listener!"); \
701  listener->call/*(param, ..., &mShouldProcceed)*/; \
702  if (!mShouldProcceed) { \
703  /* Abort as soon as one returns false */ \
704  mPerformAction = PR_FALSE; \
705  break; \
706  } \
707  } \
708 
709 
710 NS_IMETHODIMP
711 sbDeviceLibrary::SetSyncSettings(sbIDeviceLibrarySyncSettings * aSyncSettings)
712 {
713  NS_ENSURE_ARG_POINTER(aSyncSettings);
714 
715  nsresult rv = SetSyncSettingsNoLock(aSyncSettings);
716  NS_ENSURE_SUCCESS(rv, rv);
717 
718  // update the library is read-only property
719  rv = UpdateIsReadOnly();
720  NS_ENSURE_SUCCESS(rv, rv);
721 
722  // update the main library listeners
723  rv = UpdateMainLibraryListeners(mSyncSettings);
724  NS_ENSURE_SUCCESS(rv, rv);
725 
726  return NS_OK;
727 }
728 
729 nsresult
730 sbDeviceLibrary::SetSyncSettingsNoLock(
731  sbIDeviceLibrarySyncSettings * aSyncSettings)
732 {
733  NS_ENSURE_ARG_POINTER(aSyncSettings);
734 
735  nsresult rv;
736 
737  // A bit of a hack, we can get away with this since there will
738  // never be a tearoff of this simple object.
739  sbDeviceLibrarySyncSettings * syncSettings =
740  static_cast<sbDeviceLibrarySyncSettings*>(aSyncSettings);
741 
742  // Lock for both assignment and the reading the aSyncSettings object
743  nsAutoMonitor monitor(mMonitor);
744 
745  nsAutoLock lock(syncSettings->GetLock());
746 
747  if (mSyncSettings) {
748  rv = mSyncSettings->Assign(syncSettings);
749  NS_ENSURE_SUCCESS(rv, rv);
750  }
751  else {
752  rv = syncSettings->CreateCopy(getter_AddRefs(mSyncSettings));
753  NS_ENSURE_SUCCESS(rv, rv);
754  }
755 
756  // Create a copy of sync settings for Write. We don't want to hold the lock
757  // while writing as it can dispatch device EVENT_DEVICE_PREFS_CHANGED event.
758  nsRefPtr<sbDeviceLibrarySyncSettings> copiedSyncSettings;
759  rv = mSyncSettings->CreateCopy(getter_AddRefs(copiedSyncSettings));
760  NS_ENSURE_SUCCESS(rv, rv);
761 
762  // Release the lock before dispatching sync settings change event
763  lock.unlock();
764  monitor.Exit();
765 
766  rv = copiedSyncSettings->Write(mDevice);
767  NS_ENSURE_SUCCESS(rv, rv);
768 
769  return NS_OK;
770 }
771 
772 NS_IMETHODIMP
773 sbDeviceLibrary::GetSyncFolderListByType(PRUint32 aContentType,
774  nsIArray **_retval)
775 {
776  NS_ENSURE_ARG_POINTER(_retval);
777  NS_ENSURE_ARG_RANGE(aContentType,
780  NS_ENSURE_TRUE(aContentType == sbIDeviceLibrary::MEDIATYPE_IMAGE,
781  NS_ERROR_NOT_IMPLEMENTED);
782  nsresult rv;
783 
784  // Create an array for the result
785  nsCOMPtr<nsIMutableArray> array =
786  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
787  NS_ENSURE_SUCCESS(rv, rv);
788 
789  nsCOMPtr<sbIDeviceLibraryMediaSyncSettings> mediaSyncSettings;
792  getter_AddRefs(mediaSyncSettings));
793  NS_ENSURE_SUCCESS(rv, rv);
794 
795  PRUint32 mgmtType;
796  rv = mediaSyncSettings->GetMgmtType(&mgmtType);
797  NS_ENSURE_SUCCESS(rv, rv);
798 
799  // If all items, simply add the root folder to the list
801  nsCOMPtr<nsIFile> rootFolder;
802  rv = mediaSyncSettings->GetSyncFromFolder(getter_AddRefs(rootFolder));
803  NS_ENSURE_SUCCESS(rv, rv);
804 
805  if (rootFolder) {
806  rv = array->AppendElement(rootFolder, PR_FALSE);
807  NS_ENSURE_SUCCESS(rv, rv);
808  }
809  }
811  // Get the preference
812  nsString prefKey;
813  rv = GetSyncListsPrefKey(aContentType, prefKey);
814  NS_ENSURE_SUCCESS(rv, rv);
815 
816  nsCOMPtr<nsIVariant> var;
817  rv = mDevice->GetPreference(prefKey, getter_AddRefs(var));
818  NS_ENSURE_SUCCESS(rv, rv);
819 
820  nsAutoString foldersDSV;
821  rv = var->GetAsAString(foldersDSV);
822  NS_ENSURE_SUCCESS(rv, rv);
823 
824  // Scan folder list DSV for folder paths and add them to the array
825  PRInt32 start = 0;
826  PRInt32 end = foldersDSV.FindChar('\1', start);
827  if (end < 0) {
828  end = foldersDSV.Length();
829  }
830  while (end > start) {
831  // Extract the folder path
832  nsDependentSubstring folderPath = Substring(foldersDSV, start, end - start);
833 
834  nsCOMPtr<nsILocalFile> folder;
835  rv = NS_NewLocalFile(folderPath, PR_TRUE, getter_AddRefs(folder));
836  if (NS_FAILED(rv)) // Invalid path, skip
837  continue;
838 
839  rv = array->AppendElement(folder, PR_FALSE);
840  NS_ENSURE_SUCCESS(rv, rv);
841 
842  // Scan for the next folder path
843  start = end + 1;
844  end = foldersDSV.FindChar('\1', start);
845  if (end < 0)
846  end = foldersDSV.Length();
847  }
848  }
849 
850  NS_ADDREF(*_retval = array);
851 
852  return NS_OK;
853 }
854 
855 NS_IMETHODIMP
856 sbDeviceLibrary::SetSyncFolderListByType(PRUint32 aContentType,
857  nsIArray *aFolderList)
858 {
859  NS_ENSURE_ARG_POINTER(aFolderList);
860  NS_ENSURE_ARG_RANGE(aContentType,
863  NS_ENSURE_TRUE(aContentType == sbIDeviceLibrary::MEDIATYPE_IMAGE,
864  NS_ERROR_NOT_IMPLEMENTED);
865  nsresult rv;
866 
867  // Get the number of sync folders
868  PRUint32 length;
869  rv = aFolderList->GetLength(&length);
870  NS_ENSURE_SUCCESS(rv, rv);
871 
872  // Produce the sync folder list DSV
873  nsAutoString foldersDSV;
874  for (PRUint32 i = 0; i < length; i++) {
875  // Get the next sync folder
876  nsCOMPtr<nsIFile> folder = do_QueryElementAt(aFolderList, i, &rv);
877  NS_ENSURE_SUCCESS(rv, rv);
878 
879  // Get the folder path
880  nsAutoString folderPath;
881  rv = folder->GetPath(folderPath);
882  NS_ENSURE_SUCCESS(rv, rv);
883 
884  // Add the folder to the list of sync folders
885  if (i > 0)
886  foldersDSV.AppendLiteral("\1");
887  foldersDSV.Append(folderPath);
888  }
889 
890  // Get the preference key
891  nsString prefKey;
892  rv = GetSyncListsPrefKey(aContentType, prefKey);
893  NS_ENSURE_SUCCESS(rv, rv);
894 
895  // Write the preference
896  rv = mDevice->SetPreference(prefKey, sbNewVariant(foldersDSV));
897  NS_ENSURE_SUCCESS(rv, rv);
898 
899  return NS_OK;
900 }
901 
902 NS_IMETHODIMP
903 sbDeviceLibrary::Sync()
904 {
905  nsresult rv;
906 
907  nsCOMPtr<sbIDevice> device;
908  rv = GetDevice(getter_AddRefs(device));
909  NS_ENSURE_SUCCESS(rv, rv);
910  NS_ASSERTION(device,
911  "sbDeviceLibrary::GetDevice returned success with no device");
912 
913  nsCOMPtr<sbILibraryManager> libraryManager =
914  do_GetService("@songbirdnest.com/Songbird/library/Manager;1", &rv);
915  NS_ENSURE_SUCCESS(rv, rv);
916 
917  nsCOMPtr<sbILibrary> mainLib;
918  rv = libraryManager->GetMainLibrary(getter_AddRefs(mainLib));
919  NS_ENSURE_SUCCESS(rv, rv);
920 
921  #if DEBUG
922  // sanity check that we're using the right device
923  { /* scope */
924  nsCOMPtr<sbIDeviceContent> content;
925  rv = device->GetContent(getter_AddRefs(content));
926  NS_ENSURE_SUCCESS(rv, rv);
927 
928  nsCOMPtr<nsIArray> libraries;
929  rv = content->GetLibraries(getter_AddRefs(libraries));
930  NS_ENSURE_SUCCESS(rv, rv);
931 
932  PRUint32 libraryCount;
933  rv = libraries->GetLength(&libraryCount);
934  NS_ENSURE_SUCCESS(rv, rv);
935 
936  PRBool found = PR_FALSE;
937  for (PRUint32 index = 0; index < libraryCount; ++index) {
938  nsCOMPtr<sbIDeviceLibrary> library =
939  do_QueryElementAt(libraries, index, &rv);
940  NS_ENSURE_SUCCESS(rv, rv);
941 
942  if (SameCOMIdentity(NS_ISUPPORTS_CAST(sbILibrary*, this), library)) {
943  found = PR_TRUE;
944  break;
945  }
946  }
947  NS_ASSERTION(found,
948  "sbDeviceLibrary has device that doesn't hold this library");
949  }
950  #endif /* DEBUG */
951 
952  nsCOMPtr<nsIWritablePropertyBag2> requestParams =
953  do_CreateInstance(NS_HASH_PROPERTY_BAG_CONTRACTID, &rv);
954  NS_ENSURE_SUCCESS(rv, rv);
955 
956  rv = requestParams->SetPropertyAsInterface(NS_LITERAL_STRING("item"),
957  mainLib);
958  NS_ENSURE_SUCCESS(rv, rv);
959 
960  rv = requestParams->SetPropertyAsInterface(NS_LITERAL_STRING("list"),
961  NS_ISUPPORTS_CAST(sbIMediaList*, this));
962  NS_ENSURE_SUCCESS(rv, rv);
963 
964  rv = device->SubmitRequest(sbIDevice::REQUEST_SYNC, requestParams);
965  NS_ENSURE_SUCCESS(rv, rv);
966 
967  // update the library is read-only property
968  rv = UpdateIsReadOnly();
969  NS_ENSURE_SUCCESS(rv, rv);
970 
971  // TODO: XXX For bug 23188 would we need to update listeners. We used to,
972  // but I don't think it's necessary.
973  return NS_OK;
974 }
975 
976 NS_IMETHODIMP
977 sbDeviceLibrary::AddDeviceLibraryListener(sbIDeviceLibraryListener* aListener)
978 {
979  TRACE(("sbDeviceLibrary[0x%x] - AddListener", this));
980  NS_ENSURE_ARG_POINTER(aListener);
981 
982  {
983  nsAutoMonitor monitor(mMonitor);
984 
985  if (mListeners.Get(aListener, nsnull)) {
986  NS_WARNING("Trying to add a listener twice!");
987  return NS_OK;
988  }
989  }
990 
991  // Make a proxy for the listener that will always send callbacks to the
992  // current thread.
993  nsCOMPtr<sbIDeviceLibraryListener> proxy;
994  nsresult rv = do_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD,
995  NS_GET_IID(sbIDeviceLibraryListener),
996  aListener,
997  NS_PROXY_SYNC | NS_PROXY_ALWAYS,
998  getter_AddRefs(proxy));
999  NS_ENSURE_SUCCESS(rv, rv);
1000 
1001  nsAutoMonitor monitor(mMonitor);
1002 
1003  // Add the proxy to the hash table, using the listener as the key.
1004  PRBool success = mListeners.Put(aListener, proxy);
1005  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1006 
1007  return NS_OK;
1008 }
1009 
1010 NS_IMETHODIMP
1011 sbDeviceLibrary::RemoveDeviceLibraryListener(sbIDeviceLibraryListener* aListener)
1012 {
1013  TRACE(("sbLibraryManager[0x%x] - RemoveListener", this));
1014  NS_ENSURE_ARG_POINTER(aListener);
1015 
1016  nsAutoMonitor monitor(mMonitor);
1017 
1018  #ifdef DEBUG
1019  if (!mListeners.Get(aListener, nsnull)) {
1020  NS_WARNING("Trying to remove a listener that was never added!");
1021  }
1022  #endif
1023  mListeners.Remove(aListener);
1024 
1025  return NS_OK;
1026 }
1027 
1038 /* static */ PLDHashOperator PR_CALLBACK
1039 sbDeviceLibrary::AddListenersToCOMArrayCallback(nsISupportsHashKey::KeyType aKey,
1040  sbIDeviceLibraryListener* aEntry,
1041  void* aUserData)
1042 {
1043  NS_ASSERTION(aKey, "Null key in hashtable!");
1044  NS_ASSERTION(aEntry, "Null entry in hashtable!");
1045 
1046  nsCOMArray<sbIDeviceLibraryListener>* array =
1047  static_cast<nsCOMArray<sbIDeviceLibraryListener>*>(aUserData);
1048 
1049  PRBool success = array->AppendObject(aEntry);
1050  NS_ENSURE_TRUE(success, PL_DHASH_STOP);
1051 
1052  return PL_DHASH_NEXT;
1053 }
1054 
1055 NS_IMETHODIMP
1056 sbDeviceLibrary::OnBatchBegin(sbIMediaList* aMediaList)
1057 {
1058  TRACE(("sbDeviceLibrary[0x%x] - OnBatchBegin", this));
1059 
1060  SB_NOTIFY_LISTENERS(OnBatchBegin(aMediaList));
1061  return NS_OK;
1062 }
1063 
1064 NS_IMETHODIMP
1065 sbDeviceLibrary::OnBatchEnd(sbIMediaList* aMediaList)
1066 {
1067  TRACE(("sbDeviceLibrary[0x%x] - OnBatchEnd", this));
1068 
1069  SB_NOTIFY_LISTENERS(OnBatchEnd(aMediaList));
1070  return NS_OK;
1071 }
1072 
1073 NS_IMETHODIMP
1074 sbDeviceLibrary::OnItemAdded(sbIMediaList* aMediaList,
1075  sbIMediaItem* aMediaItem,
1076  PRUint32 aIndex,
1077  PRBool* aNoMoreForBatch)
1078 {
1079  TRACE(("sbDeviceLibrary[0x%x] - OnItemAdded", this));
1080 
1081  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnItemAdded(aMediaList,
1082  aMediaItem,
1083  aIndex,
1084  aNoMoreForBatch));
1085 
1086  return NS_OK;
1087 }
1088 
1089 NS_IMETHODIMP
1090 sbDeviceLibrary::OnBeforeItemRemoved(sbIMediaList* aMediaList,
1091  sbIMediaItem* aMediaItem,
1092  PRUint32 aIndex,
1093  PRBool* aNoMoreForBatch)
1094 {
1095  TRACE(("sbDeviceLibrary[0x%x] - OnBeforeItemRemoved", this));
1096 
1097  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnBeforeItemRemoved(aMediaList,
1098  aMediaItem,
1099  aIndex,
1100  aNoMoreForBatch));
1101  return NS_OK;
1102 }
1103 
1104 NS_IMETHODIMP
1105 sbDeviceLibrary::OnAfterItemRemoved(sbIMediaList* aMediaList,
1106  sbIMediaItem* aMediaItem,
1107  PRUint32 aIndex,
1108  PRBool* aNoMoreForBatch)
1109 {
1110  TRACE(("sbDeviceLibrary[0x%x] - OnAfterItemRemoved", this));
1111 
1112  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnAfterItemRemoved(aMediaList,
1113  aMediaItem,
1114  aIndex,
1115  aNoMoreForBatch));
1116  return NS_OK;
1117 }
1118 
1119 NS_IMETHODIMP
1120 sbDeviceLibrary::OnItemUpdated(sbIMediaList *aMediaList,
1121  sbIMediaItem *aMediaItem,
1122  sbIPropertyArray* aProperties,
1123  PRBool* aNoMoreForBatch)
1124 {
1125  TRACE(("sbDeviceLibrary[0x%x] - OnItemUpdated", this));
1126 
1127  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnItemUpdated(aMediaList,
1128  aMediaItem,
1129  aProperties,
1130  aNoMoreForBatch));
1131  return NS_OK;
1132 }
1133 
1134 NS_IMETHODIMP
1135 sbDeviceLibrary::OnItemMoved(sbIMediaList *aMediaList,
1136  PRUint32 aFromIndex,
1137  PRUint32 aToIndex,
1138  PRBool* aNoMoreForBatch)
1139 {
1140  TRACE(("sbDeviceLibrary[0x%x] - OnItemMoved", this));
1141 
1142  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnItemMoved(aMediaList,
1143  aFromIndex,
1144  aToIndex,
1145  aNoMoreForBatch));
1146  return NS_OK;
1147 }
1148 
1149 NS_IMETHODIMP
1150 sbDeviceLibrary::OnBeforeListCleared(sbIMediaList *aMediaList,
1151  PRBool aExcludeLists,
1152  PRBool* aNoMoreForBatch)
1153 {
1154  TRACE(("sbDeviceLibrary[0x%x] - OnListCleared", this));
1155 
1156  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnBeforeListCleared(aMediaList,
1157  aExcludeLists,
1158  aNoMoreForBatch));
1159  return NS_OK;
1160 }
1161 
1162 NS_IMETHODIMP
1163 sbDeviceLibrary::OnListCleared(sbIMediaList *aMediaList,
1164  PRBool aExcludeLists,
1165  PRBool* aNoMoreForBatch)
1166 {
1167  TRACE(("sbDeviceLibrary[0x%x] - OnListCleared", this));
1168 
1169  SB_NOTIFY_LISTENERS_RETURN_FALSE(OnListCleared(aMediaList,
1170  aExcludeLists,
1171  aNoMoreForBatch));
1172  return NS_OK;
1173 }
1174 
1175 NS_IMETHODIMP
1176 sbDeviceLibrary::OnItemCopied(sbIMediaItem *aSourceItem,
1177  sbIMediaItem *aDestItem)
1178 {
1179  TRACE(("sbDeviceLibrary[0x%x] - OnItemCopied", this));
1180 
1181  SB_NOTIFY_LISTENERS(OnItemCopied(aSourceItem, aDestItem));
1182 
1183  return NS_OK;
1184 }
1185 
1186 NS_IMETHODIMP sbDeviceLibrary::OnDeviceEvent(sbIDeviceEvent* aEvent)
1187 {
1188  nsresult rv;
1189 
1190  // get the event type.
1191  PRUint32 type;
1192  rv = aEvent->GetType(&type);
1193  NS_ENSURE_SUCCESS(rv, rv);
1194 
1195  return NS_OK;
1196 }
1197 
1198 /*
1199  * See sbILibrary
1200  */
1201 NS_IMETHODIMP
1203  sbIPropertyArray *aProperties,
1204  PRBool aAllowDuplicates,
1205  sbIMediaItem **_retval)
1206 {
1207  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1208  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeCreateMediaItem(aContentUri,
1209  aProperties,
1210  aAllowDuplicates,
1211  &mShouldProcceed));
1212  if (mPerformAction) {
1213  nsresult rv;
1214  rv = mDeviceLibrary->CreateMediaItem(aContentUri,
1215  aProperties,
1216  aAllowDuplicates,
1217  _retval);
1218  NS_ENSURE_SUCCESS(rv, rv);
1219  }
1220  return NS_OK;
1221 }
1222 
1223 /*
1224  * See sbILibrary
1225  */
1226 NS_IMETHODIMP
1228  sbIPropertyArray *aProperties,
1229  sbIMediaItem **aResultItem,
1230  PRBool *_retval)
1231 {
1232  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1233  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeCreateMediaItem(aContentUri,
1234  aProperties,
1235  PR_FALSE,
1236  &mShouldProcceed));
1237  if (mPerformAction) {
1238  nsresult rv;
1239  rv = mDeviceLibrary->CreateMediaItemIfNotExist(aContentUri,
1240  aProperties,
1241  aResultItem,
1242  _retval);
1243  NS_ENSURE_SUCCESS(rv, rv);
1244  }
1245  return NS_OK;
1246 }
1247 
1248 /*
1249  * See sbILibrary
1250  */
1251 NS_IMETHODIMP
1252 sbDeviceLibrary::CreateMediaList(const nsAString & aType,
1253  sbIPropertyArray *aProperties,
1254  sbIMediaList **_retval)
1255 {
1256  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1257  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeCreateMediaList(aType,
1258  aProperties,
1259  &mShouldProcceed));
1260  if (mPerformAction) {
1261  return mDeviceLibrary->CreateMediaList(aType, aProperties, _retval);
1262  } else {
1263  return NS_OK;
1264  }
1265 }
1266 
1267 /*
1268  * See sbILibrary
1269  */
1270 NS_IMETHODIMP
1272 {
1273  NS_ENSURE_ARG_POINTER(aDevice);
1274  NS_IF_ADDREF(*aDevice = mDevice);
1275  return *aDevice ? NS_OK : NS_ERROR_UNEXPECTED;
1276 }
1277 
1278 /*
1279  * See sbILibrary
1280  */
1281 NS_IMETHODIMP
1283 {
1284  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1285  return mDeviceLibrary->ClearItems();
1286 }
1287 
1291 NS_IMETHODIMP
1292 sbDeviceLibrary::ClearItemsByType(const nsAString &aContentType)
1293 {
1294  NS_ASSERTION(mDeviceLibrary, "mDevice library is null, call init first.");
1295  return mDeviceLibrary->ClearItemsByType(aContentType);
1296 }
1297 
1298 /*
1299  * See sbIMediaList
1300  */
1301 NS_IMETHODIMP
1302 sbDeviceLibrary::Add(sbIMediaItem *aMediaItem)
1303 {
1304  return AddItem(aMediaItem, nsnull);
1305 }
1306 
1307 /*
1308  * See sbIMediaList
1309  */
1310 NS_IMETHODIMP
1311 sbDeviceLibrary::AddItem(sbIMediaItem *aMediaItem,
1312  sbIMediaItem ** aNewMediaItem)
1313 {
1314  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1315  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeAdd(aMediaItem,
1316  &mShouldProcceed));
1317 
1318  if (mPerformAction) {
1319  return mDeviceLibrary->AddItem(aMediaItem, aNewMediaItem);
1320  } else {
1321  return NS_OK;
1322  }
1323 }
1324 
1325 /*
1326  * See sbIMediaList
1327  */
1328 NS_IMETHODIMP
1329 sbDeviceLibrary::AddAll(sbIMediaList *aMediaList)
1330 {
1331  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1332  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeAddAll(aMediaList,
1333  &mShouldProcceed));
1334  if (mPerformAction) {
1335  // XXX: not implemented!
1336  return mDeviceLibrary->AddAll(aMediaList);
1337  } else {
1338  return NS_OK;
1339  }
1340 }
1341 
1342 NS_IMETHODIMP
1344 {
1345  // Forward to the new API
1346  return AddMediaItems(aMediaItems, nsnull, PR_FALSE);
1347 }
1348 
1349 /*
1350  * See sbIMediaList
1351  */
1352 NS_IMETHODIMP
1354  sbIAddMediaItemsListener * aListener,
1355  PRBool aAsync)
1356 {
1357  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1358  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeAddSome(aMediaItems,
1359  &mShouldProcceed));
1360 
1361  nsresult rv = NS_ERROR_UNEXPECTED;
1362 
1363  if (mPerformAction) {
1364  rv = mDeviceLibrary->AddMediaItems(aMediaItems, aListener, aAsync);
1365  NS_ENSURE_SUCCESS(rv, rv);
1366  }
1367 
1368  return NS_OK;
1369 }
1370 
1371 /*
1372  * See sbIMediaList
1373  */
1374 NS_IMETHODIMP
1376 {
1377  NS_ASSERTION(mDeviceLibrary, "mDeviceLibrary is null, call init first.");
1378  SB_NOTIFY_LISTENERS_ASK_PERMISSION(OnBeforeClear(&mShouldProcceed));
1379  if (mPerformAction) {
1380  return mDeviceLibrary->Clear();
1381  } else {
1382  return NS_OK;
1383  }
1384 }
function start(ch)
#define SB_PROPERTY_TOTALDISCS
#define SB_NOTIFY_LISTENERS_ASK_PERMISSION(call)
nsresult CreateCopy(sbDeviceLibrarySyncSettings **aSettings)
NS_DECL_ISUPPORTS NS_DECL_NSICLASSINFO NS_DECL_SBIDEVICELIBRARY NS_DECL_SBIMEDIALISTLISTENER NS_DECL_SBILOCALDATABASEMEDIALISTCOPYLISTENER NS_DECL_SBIDEVICEEVENTLISTENER sbDeviceLibrary(sbIDevice *aDevice)
const NS_APP_USER_PROFILE_50_DIR
NS_IMETHOD CreateMediaList(const nsAString &aType, sbIPropertyArray *aProperties, sbIMediaList **_retval)
return NS_OK
#define SB_PROPERTY_MEDIALISTNAME
#define SB_PROPERTY_PLAYCOUNT
const unsigned long REQUEST_SYNC
Definition: sbIDevice.idl:265
#define SB_PROPERTY_SAMPLERATE
NS_IMETHOD AddAll(sbIMediaList *aMediaList)
#define SB_PROPERTY_LYRICS
readonly attribute sbIDevice device
Reference to the device that this library is stored on.
Definition: sbILibrary.idl:87
inArray array
function succeeded(ch, cx, status, data)
#define SB_NOTIFY_LISTENERS_RETURN_FALSE(call)
#define PREF_SYNC_PREFIX
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define SB_PROPERTY_ALBUMARTISTNAME
#define PREF_SYNC_LISTS
#define SB_PROPERTY_RATING
virtual ~sbDeviceLibrary()
#define SB_DEVICE_PROPERTY_ACCESS_COMPATIBILITY
NS_IMETHOD Add(sbIMediaItem *aMediaItem)
#define SB_PROPERTY_CONDUCTORNAME
readonly attribute sbILibrary library
The library that this media item is contained in.
#define SB_PROPERTY_HIDDEN
NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER6(sbDeviceLibrary, nsIClassInfo, sbIDeviceLibrary, sbILibrary, sbIMediaList, sbIMediaItem, sbILibraryResource) sbDeviceLibrary
NS_IMPL_THREADSAFE_CI(sbMediaListEnumeratorWrapper)
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
#define SB_PROPERTY_LYRICISTNAME
nsresult do_GetProxyForObject(nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
#define LOG(args)
Songbird Variant Utility Definitions.
#define SB_PROPERTY_LASTPLAYTIME
#define SB_PROPERTY_TOTALTRACKS
const unsigned long LISTENER_FLAGS_BEFOREITEMREMOVED
A brief description of the contents of this interface.
Interface used to listen to changes to a device library.
#define PREF_SYNC_BRANCH
const unsigned long MEDIATYPE_AUDIO
NS_IMPL_THREADSAFE_RELEASE(sbRequestItem)
#define SB_PROPERTY_BITRATE
const unsigned long MEDIATYPE_IMAGE
NS_IMETHOD Clear(void)
NS_IMPL_THREADSAFE_ADDREF(sbRequestItem)
readonly attribute AString guid
The guid of this resource.
#define SB_PROPERTY_DONT_WRITE_METADATA
readonly attribute AString type
The type of media list (eg "simple")
const unsigned long LISTENER_FLAGS_BATCHEND
#define SB_PROPERTY_CONTENTLENGTH
Interface used to listen to changes to a media list.
#define SB_LOCALDATABASE_LIBRARYFACTORY_CONTRACTID
readonly attribute unsigned long length
Returns the length of the list.
NS_IMETHOD CreateMediaItem(nsIURI *aContentUri, sbIPropertyArray *aProperties, PRBool aAllowDuplicates, sbIMediaItem **_retval)
#define SB_PROPERTY_GENRE
#define SB_PROPERTY_CONTENTTYPE
const unsigned long LISTENER_FLAGS_BEFORELISTCLEARED
const unsigned long LISTENER_FLAGS_BATCHBEGIN
static sbDeviceLibrarySyncSettings * New(nsID const &aDeviceID, nsAString const &aDeviceLibraryGuid)
General interface to data resources.
const unsigned long LISTENER_FLAGS_AFTERITEMREMOVED
#define SB_PROPERTY_SOFTWAREVENDOR
#define SB_PROPERTY_KEY
#define SB_PROPERTY_DURATION
var libraryManager
#define SB_PROPERTY_ISREADONLY
#define SB_PROPERTY_COPYRIGHT
#define SB_PROPERTY_DISCNUMBER
#define TRACE(args)
#define SB_PROPERTY_DEVICE_LIBRARY_GUID
NS_IMETHOD AddMediaItems(nsISimpleEnumerator *aMediaItems, sbIAddMediaItemsListener *aListener, PRBool aAsync)
Media library abstraction.
Definition: sbILibrary.idl:82
#define SB_PROPERTY_ARTISTNAME
attribute sbIDeviceLibrarySyncSettings syncSettings
static const char * sbDeviceLibrarySyncUpdatePropertyTable[]
static nsresult GetDefaultDeviceLibraryDatabaseFile(const nsAString &aDeviceIdentifier, nsIFile **aDBFile)
#define SB_PROPERTY_BPM
NS_IMETHOD ClearItems()
#define SB_PROPERTY_RECORDLABELNAME
const unsigned long LISTENER_FLAGS_ITEMADDED
#define SB_PROPERTY_ALBUMNAME
char const *const gMediaType[]
#define SB_PROPERTY_LANGUAGE
sbIJobCancelable NS_DECL_CLASSINFO(sbGstreamerMediaInspector)
#define SB_PROPERTY_COMPOSERNAME
#define SB_PROPERTY_YEAR
#define SB_PROPERTY_PRODUCERNAME
#define SB_PROPERTY_LASTSKIPTIME
nsresult GetMainLibrary(sbILibrary **aMainLibrary)
Interface that defines a single item of media in the system.
static nsresult GetMediaSettings(sbIDeviceLibrary *aDevLib, PRUint32 aMediaType, sbIDeviceLibraryMediaSyncSettings **aMediaSettings)
#define SB_PROPERTY_TRACKNAME
NS_IMETHOD AddSome(nsISimpleEnumerator *aMediaItems)
#define SB_NOTIFY_LISTENERS(call)
#define SB_PROPERTY_COMMENT
const unsigned long LISTENER_FLAGS_ITEMUPDATED
#define SB_PROPERTY_COPYRIGHTURL
NS_IMETHOD GetDevice(sbIDevice **aDevice)
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
#define SB_PROPERTY_SUBTITLE
_getSelectedPageStyle s i
const unsigned long MEDIATYPE_COUNT
#define SB_PROPERTY_SKIPCOUNT
NS_IMETHOD ClearItemsByType(const nsAString &aContentType)
NS_IMETHOD AddItem(sbIMediaItem *aMediaItem, sbIMediaItem **aNewMediaItem)
NS_IMETHOD CreateMediaItemIfNotExist(nsIURI *aContentUri, sbIPropertyArray *aProperties, sbIMediaItem **aResultItem, PRBool *_retval)
#define SB_PROPERTY_TRACKNUMBER
#define SB_PROPERTY_ISPARTOFCOMPILATION