32 #include <nsIAppStartupNotifier.h>
33 #include <nsICategoryManager.h>
34 #include <nsIObserverService.h>
35 #include <nsIPrefBranch.h>
36 #include <nsIPrefService.h>
37 #include <nsIStringBundle.h>
38 #include <nsIVariant.h>
39 #include <nsServiceManagerUtils.h>
40 #include <nsStringGlue.h>
41 #include <nsThreadUtils.h>
43 #include <sbIDataRemote.h>
44 #include <sbILibraryManager.h>
45 #include <sbILocalDatabaseLibrary.h>
46 #include <sbIMediacoreEventTarget.h>
47 #include <sbIMediacoreSequencer.h>
48 #include <sbIMediacoreStatus.h>
49 #include <sbIMediaListView.h>
50 #include <sbIOrderableMediaList.h>
62 #define SB_NAMEKEY_PLAYQUEUE_LIST \
63 "&chrome://songbird/locale/songbird.properties#playqueue.pane.title"
68 #define SB_PLAYQUEUE_DEFAULTCOLUMNSPEC \
69 NS_LL("http://songbirdnest.com/data/1.0#ordinal 30 ") \
70 NS_LL("http://songbirdnest.com/data/1.0#trackName 130")
72 #define SB_DATAREMOTE_FACEPLATE_STATUS \
73 NS_LITERAL_STRING("faceplate.status.override.text")
75 #define SB_BUNDLE_URL "chrome://songbird/locale/songbird.properties"
77 #define SB_PLAYQUEUE_PANE_TITLE NS_LITERAL_STRING("playqueue.pane.title")
78 #define SB_LIBRARY_TRACKSADDED NS_LITERAL_STRING("library.tracksadded")
85 static PRLogModuleInfo* gPlayQueueServiceLog = nsnull;
86 #define TRACE(args) PR_LOG(gPlayQueueServiceLog, PR_LOG_DEBUG, args)
87 #define LOG(args) PR_LOG(gPlayQueueServiceLog, PR_LOG_WARN, args)
89 #define __FUNCTION__ __PRETTY_FUNCTION__
116 do_CreateInstance(
"@songbirdnest.com/Songbird/DataRemote;1", &rv);
117 NS_ENSURE_SUCCESS(rv, rv);
120 NS_ENSURE_SUCCESS(rv, rv);
122 nsCOMPtr<nsIStringBundleService> stringBundleService =
123 do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
124 NS_ENSURE_SUCCESS(rv, rv);
127 getter_AddRefs(mBundle));
128 NS_ENSURE_SUCCESS(rv, rv);
131 getter_Copies(mQueueName));
132 NS_ENSURE_SUCCESS(rv, rv);
138 sbPlayQueueAsyncListener::Finalize()
143 rv = mDataRemote->Unbind();
144 NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to unbind face plate data remote");
155 sbPlayQueueAsyncListener::OnProgress(PRUint32 aItemsProcessed, PRBool aComplete)
162 const PRUnichar*
strings[2] = { processed.get(), mQueueName.get() };
166 getter_Copies(message));
171 rv = mDataRemote->SetStringValue(message);
172 NS_ENSURE_SUCCESS(rv, rv);
175 rv = mService->NotifyQueueOperationCompleted();
176 NS_ENSURE_SUCCESS(rv, rv);
185 sbPlayQueueAsyncListener::OnItemAdded(
sbIMediaItem * aMediaItem)
191 sbPlayQueueAsyncListener::OnComplete()
204 : mMediaList(nsnull),
208 mExplicitStop(PR_FALSE),
209 mBatchRemovalIndex(0),
210 mBatchBeginAllHistory(PR_FALSE),
211 mIgnoreListListener(PR_FALSE),
212 mSequencerOnQueue(PR_FALSE),
213 mSequencerPlayingOrPaused(PR_FALSE),
214 mOperationInProgress(PR_FALSE),
215 mLibraryListener(nsnull),
216 mWeakMediacoreManager(nsnull),
217 mAsyncListener(nsnull)
220 if (!gPlayQueueServiceLog) {
221 gPlayQueueServiceLog = PR_NewLogModule(
"sbPlayQueueService");
224 TRACE((
"%s[%p]", __FUNCTION__,
this));
229 TRACE((
"%s[%p]", __FUNCTION__,
this));
236 TRACE((
"%s[%p]", __FUNCTION__,
this));
240 do_GetService(
"@mozilla.org/observer-service;1", &rv);
241 NS_ENSURE_SUCCESS(rv, rv);
244 rv = observerService->AddObserver(
this,
247 NS_ENSURE_SUCCESS(rv, rv);
249 rv = observerService->AddObserver(
this,
252 NS_ENSURE_SUCCESS(rv, rv);
254 PRBool success = mListeners.Init();
255 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
258 NS_ENSURE_TRUE(mAsyncListener, NS_ERROR_OUT_OF_MEMORY);
260 rv = mAsyncListener->Init();
261 NS_ENSURE_SUCCESS(rv, rv);
267 sbPlayQueueService::Finalize()
269 TRACE((
"%s[%p]", __FUNCTION__,
this));
273 mMediaList->RemoveListener(
this);
277 if (mLibraryListener && mLibrary) {
278 mLibrary->RemoveListener(mLibraryListener);
279 mLibraryListener = nsnull;
282 nsCOMPtr<sbILocalDatabaseLibrary> localDBLibrary = do_QueryInterface(mLibrary, &rv);
283 if (NS_SUCCEEDED(rv)) {
284 rv = localDBLibrary->RemoveCopyListener(
this);
285 NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to remove copy listener");
289 if (mExternalListener) {
290 mExternalListener->RemoveListeners();
291 mExternalListener = nsnull;
294 if (mWeakMediacoreManager) {
295 nsCOMPtr<sbIMediacoreEventTarget>
target =
296 do_QueryReferent(mWeakMediacoreManager, &rv);
297 if (NS_SUCCEEDED(rv)) {
298 rv = target->RemoveListener(
this);
299 NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to remove mediacore listener");
301 mWeakMediacoreManager = nsnull;
304 mRemovedItemGUIDs.Clear();
308 do_GetService(
"@mozilla.org/observer-service;1", &rv);
310 if (NS_SUCCEEDED(rv)) {
311 observerService->RemoveObserver(
this,
318 mInitialized = PR_FALSE;
328 sbPlayQueueService::GetMediaList(
sbIMediaList** aMediaList)
330 TRACE((
"%s[%p]", __FUNCTION__,
this));
332 NS_ASSERTION(NS_IsMainThread(),
333 "GetMediaList() must be called from the main thread");
334 NS_ENSURE_ARG_POINTER(aMediaList);
335 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
337 NS_IF_ADDREF(*aMediaList = mMediaList);
342 sbPlayQueueService::GetIndex(PRUint32* aIndex)
344 TRACE((
"%s[%p]", __FUNCTION__,
this));
346 NS_ASSERTION(NS_IsMainThread(),
347 "GetIndex() must be called from the main thread");
348 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
349 NS_ENSURE_ARG_POINTER(aIndex);
356 sbPlayQueueService::SetIndex(PRUint32 aIndex)
358 TRACE((
"%s[%p]", __FUNCTION__,
this));
360 NS_ASSERTION(NS_IsMainThread(),
361 "SetIndex() must be called from the main thread");
362 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
365 nsresult rv = mMediaList->GetLength(&length);
366 NS_ENSURE_SUCCESS(rv, rv);
369 PRUint32 oldIndex = mIndex;
372 if (aIndex > length) {
379 if (mIndex != oldIndex)
380 mListeners.EnumerateEntries(OnIndexUpdatedCallback, &mIndex);
386 sbPlayQueueService::GetOperationInProgress(PRBool *aOperationInProgress)
388 TRACE((
"%s[%p]", __FUNCTION__,
this));
390 NS_ENSURE_ARG_POINTER(aOperationInProgress);
392 *aOperationInProgress = mOperationInProgress;
400 TRACE((
"%s[%p]", __FUNCTION__,
this));
402 NS_ASSERTION(NS_IsMainThread(),
403 "QueueNext() must be called from the main thread");
404 NS_ASSERTION(!mOperationInProgress,
405 "QueueNext() should not be called while an async operation is in progress");
406 NS_ENSURE_ARG_POINTER(aMediaItem);
407 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
410 mIgnoreListListener = PR_TRUE;
420 PRUint32 insertBeforeIndex =
421 (mSequencerOnQueue && mSequencerPlayingOrPaused) ? mIndex + 1 : mIndex;
426 rv = mMediaList->GetLength(&length);
427 NS_ENSURE_SUCCESS(rv, rv);
429 PRBool callQueueLast = (insertBeforeIndex >= length);
431 nsCOMPtr<sbIMediaList> itemAsList = do_QueryInterface(aMediaItem, &rv);
432 if (NS_SUCCEEDED(rv)) {
435 rv = QueueLastInternal(itemAsList);
437 rv = QueueNextInternal(itemAsList, insertBeforeIndex);
442 rv = QueueLastInternal(aMediaItem);
444 rv = QueueNextInternal(aMediaItem, insertBeforeIndex);
447 NS_ENSURE_SUCCESS(rv, rv);
449 mIgnoreListListener = PR_FALSE;
457 TRACE((
"%s[%p]", __FUNCTION__,
this));
459 NS_ASSERTION(NS_IsMainThread(),
460 "QueueLast() must be called from the main thread");
461 NS_ASSERTION(!mOperationInProgress,
462 "QueueLast() should not be called while an async operation is in progress");
463 NS_ENSURE_ARG_POINTER(aMediaItem);
464 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
467 mIgnoreListListener = PR_TRUE;
472 nsCOMPtr<sbIMediaList> itemAsList = do_QueryInterface(aMediaItem, &rv);
473 if (NS_SUCCEEDED(rv)) {
475 rv = QueueLastInternal(itemAsList);
477 rv = QueueLastInternal(aMediaItem);
479 NS_ENSURE_SUCCESS(rv, rv);
481 mIgnoreListListener = PR_FALSE;
487 sbPlayQueueService::QueueSomeBefore(PRUint32 aIndex,
490 TRACE((
"%s[%p]", __FUNCTION__,
this));
492 NS_ASSERTION(NS_IsMainThread(),
493 "QueueSomeBefore() must be called from the main thread");
494 NS_ASSERTION(!mOperationInProgress,
495 "QueueSomeBefore() should not be called while an async operation is in progress");
496 NS_ENSURE_ARG_POINTER(aMediaItems);
497 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
502 rv = mMediaList->GetLength(&length);
503 NS_ENSURE_SUCCESS(rv, rv);
505 NS_ENSURE_ARG_RANGE(aIndex, 0, length - 1);
511 mIgnoreListListener = PR_TRUE;
513 rv = NotifyQueueOperationStarted();
514 NS_ENSURE_SUCCESS(rv, rv);
516 nsCOMPtr<sbIOrderableMediaList> orderedList =
517 do_QueryInterface(mMediaList, &rv);
518 NS_ENSURE_SUCCESS(rv, rv);
520 rv = orderedList->InsertSomeBeforeAsync(aIndex,
523 NS_ENSURE_SUCCESS(rv, rv);
531 TRACE((
"%s[%p]", __FUNCTION__,
this));
533 NS_ASSERTION(NS_IsMainThread(),
534 "QueueSomeNext() must be called from the main thread");
535 NS_ASSERTION(!mOperationInProgress,
536 "QueueSomeNext() should not be called while an async operation is in progress");
537 NS_ENSURE_ARG_POINTER(aMediaItems);
538 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
541 mIgnoreListListener = PR_TRUE;
543 rv = NotifyQueueOperationStarted();
544 NS_ENSURE_SUCCESS(rv, rv);
547 PRUint32 insertBeforeIndex =
548 (mSequencerOnQueue && mSequencerPlayingOrPaused) ? mIndex + 1 : mIndex;
551 rv = mMediaList->GetLength(&length);
552 NS_ENSURE_SUCCESS(rv, rv);
554 if (insertBeforeIndex >= length) {
555 rv = mMediaList->AddMediaItems(aMediaItems, mAsyncListener,
true);
556 NS_ENSURE_SUCCESS(rv, rv);
558 nsCOMPtr<sbIOrderableMediaList> orderedList =
559 do_QueryInterface(mMediaList, &rv);
560 NS_ENSURE_SUCCESS(rv, rv);
562 rv = orderedList->InsertSomeBeforeAsync(insertBeforeIndex,
565 NS_ENSURE_SUCCESS(rv, rv);
574 TRACE((
"%s[%p]", __FUNCTION__,
this));
576 NS_ASSERTION(NS_IsMainThread(),
577 "QueueSomeLast() must be called from the main thread");
578 NS_ASSERTION(!mOperationInProgress,
579 "QueueSomeLast() should not be called while an async operation is in progress");
580 NS_ENSURE_ARG_POINTER(aMediaItems);
581 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
584 mIgnoreListListener = PR_TRUE;
586 rv = NotifyQueueOperationStarted();
587 NS_ENSURE_SUCCESS(rv, rv);
589 rv = mMediaList->AddMediaItems(aMediaItems, mAsyncListener,
true);
590 NS_ENSURE_SUCCESS(rv, rv);
596 sbPlayQueueService::ClearAll()
598 TRACE((
"%s[%p]", __FUNCTION__,
this));
600 NS_ASSERTION(NS_IsMainThread(),
601 "ClearAll() must be called from the main thread");
602 NS_ASSERTION(!mOperationInProgress,
603 "ClearAll() should not be called while an async operation is in progress");
604 NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
606 mIgnoreListListener = PR_TRUE;
609 nsresult rv = mLibrary->ClearItems();
610 NS_ENSURE_SUCCESS(rv, rv);
614 mIgnoreListListener = PR_FALSE;
620 sbPlayQueueService::ClearHistory()
622 TRACE((
"%s[%p]", __FUNCTION__,
this));
624 NS_ASSERTION(NS_IsMainThread(),
625 "ClearHistory() must be called from the main thread");
626 NS_ASSERTION(!mOperationInProgress,
627 "ClearHistory() should not be called while an async operation is in progress");
641 nsCOMPtr<nsIMutableArray> historyItems =
642 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
643 NS_ENSURE_SUCCESS(rv, rv);
645 for (PRUint32
i = 0;
i < mIndex; ++
i) {
646 nsCOMPtr<sbIMediaItem> item;
647 rv = mMediaList->GetItemByIndex(
i, getter_AddRefs(item));
648 NS_ENSURE_SUCCESS(rv, rv);
650 rv = historyItems->AppendElement(item, PR_FALSE);
651 NS_ENSURE_SUCCESS(rv, rv);
654 nsCOMPtr<nsISimpleEnumerator> historyEnumerator;
655 rv = historyItems->Enumerate(getter_AddRefs(historyEnumerator));
656 NS_ENSURE_SUCCESS(rv, rv);
660 rv = mMediaList->RemoveSome(historyEnumerator);
661 NS_ENSURE_SUCCESS(rv, rv);
667 sbPlayQueueService::QueueNextInternal(
sbIMediaItem* aMediaItem,
668 PRUint32 aInsertBeforeIndex)
670 TRACE((
"%s[%p]", __FUNCTION__,
this));
671 NS_ENSURE_ARG_POINTER(aMediaItem);
675 nsCOMPtr<sbIOrderableMediaList> orderedList =
676 do_QueryInterface(mMediaList, &rv);
677 NS_ENSURE_SUCCESS(rv, rv);
679 rv = orderedList->InsertBefore(aInsertBeforeIndex, aMediaItem);
680 NS_ENSURE_SUCCESS(rv, rv);
686 sbPlayQueueService::QueueNextInternal(
sbIMediaList* aMediaList,
687 PRUint32 aInsertBeforeIndex)
689 TRACE((
"%s[%p]", __FUNCTION__,
this));
690 NS_ENSURE_ARG_POINTER(aMediaList);
694 nsCOMPtr<sbIOrderableMediaList> orderedList =
695 do_QueryInterface(mMediaList, &rv);
696 NS_ENSURE_SUCCESS(rv, rv);
698 rv = orderedList->InsertAllBefore(aInsertBeforeIndex, aMediaList);
699 NS_ENSURE_SUCCESS(rv, rv);
705 sbPlayQueueService::QueueLastInternal(
sbIMediaItem* aMediaItem)
707 TRACE((
"%s[%p]", __FUNCTION__,
this));
708 NS_ENSURE_ARG_POINTER(aMediaItem);
711 nsresult rv = mMediaList->Add(aMediaItem);
712 NS_ENSURE_SUCCESS(rv, rv);
718 sbPlayQueueService::QueueLastInternal(
sbIMediaList* aMediaList)
720 TRACE((
"%s[%p]", __FUNCTION__,
this));
721 NS_ENSURE_ARG_POINTER(aMediaList);
724 nsresult rv = mMediaList->AddAll(aMediaList);
725 NS_ENSURE_SUCCESS(rv, rv);
731 sbPlayQueueService::CreateMediaList()
733 TRACE((
"%s[%p]", __FUNCTION__,
this));
735 NS_ENSURE_STATE(mLibrary);
738 rv = mLibrary->CreateMediaList(NS_LITERAL_STRING(
"simple"),
740 getter_AddRefs(mMediaList));
741 NS_ENSURE_SUCCESS(rv, rv);
744 nsAutoString listGUID;
745 rv = mMediaList->GetGuid(listGUID);
746 NS_ENSURE_SUCCESS(rv, rv);
749 rv = mLibrary->SetProperty(
752 NS_ENSURE_SUCCESS(rv, rv);
755 NS_ENSURE_SUCCESS(rv, rv);
761 NS_LITERAL_STRING(
"0"));
762 NS_ENSURE_SUCCESS(rv, rv);
768 sbPlayQueueService::InitLibrary()
770 TRACE((
"%s[%p]", __FUNCTION__,
this));
775 nsCOMPtr<nsIPrefBranch> prefBranch =
777 NS_ENSURE_SUCCESS(rv, rv);
779 nsCOMPtr<nsISupportsString> supportsString;
783 getter_AddRefs(supportsString));
784 NS_ENSURE_SUCCESS(rv, rv);
786 rv = supportsString->GetData(guid);
787 NS_ENSURE_SUCCESS(rv, rv);
791 do_GetService(
"@songbirdnest.com/Songbird/library/Manager;1", &rv);
792 NS_ENSURE_SUCCESS(rv, rv);
794 rv = libraryManager->GetLibrary(guid, getter_AddRefs(mLibrary));
795 NS_ENSURE_SUCCESS(rv, rv);
799 NS_ENSURE_TRUE(mExternalListener, NS_ERROR_OUT_OF_MEMORY);
800 rv = mExternalListener->SetMasterLibrary(mLibrary);
801 NS_ENSURE_SUCCESS(rv, rv);
803 nsCOMPtr<nsISimpleEnumerator> libEnum;
804 rv = libraryManager->GetStartupLibraries(getter_AddRefs(libEnum));
805 NS_ENSURE_SUCCESS(rv, rv);
808 while (NS_SUCCEEDED(libEnum->HasMoreElements(&hasMore)) && hasMore) {
809 nsCOMPtr<nsISupports>
next;
810 if (NS_SUCCEEDED(libEnum->GetNext(getter_AddRefs(next))) && next) {
811 nsCOMPtr<sbILibrary> library(do_QueryInterface(next, &rv));
812 if (NS_SUCCEEDED(rv) && library && library != mLibrary) {
813 rv = mExternalListener->AddExternalLibrary(library);
814 NS_ENSURE_SUCCESS(rv, rv);
819 nsCOMPtr<sbILocalDatabaseLibrary> localDBLibrary = do_QueryInterface(mLibrary, &rv);
820 NS_ENSURE_SUCCESS(rv, rv);
821 localDBLibrary->AddCopyListener(
this);
827 sbPlayQueueService::InitMediaList()
829 TRACE((
"%s[%p]", __FUNCTION__,
this));
831 NS_ENSURE_STATE(mLibrary);
835 nsAutoString listGUID;
836 rv = mLibrary->GetProperty(
839 NS_ENSURE_SUCCESS(rv, rv);
841 if (!listGUID.IsEmpty()) {
843 nsCOMPtr<sbIMediaItem> listAsItem;
844 rv = mLibrary->GetMediaItem(listGUID, getter_AddRefs(listAsItem));
845 if (NS_SUCCEEDED(rv)) {
846 mMediaList = do_QueryInterface(listAsItem, &rv);
847 NS_ENSURE_SUCCESS(rv, rv);
859 rv = mLibrary->Clear();
860 NS_ENSURE_SUCCESS(rv, rv);
862 rv = CreateMediaList();
863 NS_ENSURE_SUCCESS(rv, rv);
869 sbPlayQueueService::SetIndexToPlayingTrack()
871 TRACE((
"%s[%p]", __FUNCTION__,
this));
874 if (mSequencerOnQueue) {
875 nsCOMPtr<sbIMediacoreManager> manager =
876 do_QueryReferent(mWeakMediacoreManager, &rv);
877 NS_ENSURE_SUCCESS(rv, rv);
879 nsCOMPtr<sbIMediacoreSequencer> sequencer;
880 rv = manager->GetSequencer(getter_AddRefs(sequencer));
881 NS_ENSURE_SUCCESS(rv, rv);
883 nsCOMPtr<sbIMediaListView> view;
884 rv = sequencer->GetView(getter_AddRefs(view));
885 NS_ENSURE_SUCCESS(rv, rv);
887 PRUint32 filteredIndex;
888 rv = sequencer->GetViewPosition(&filteredIndex);
889 NS_ENSURE_SUCCESS(rv, rv);
891 PRUint32 unfilteredIndex;
892 rv = view->GetUnfilteredIndex(filteredIndex, &unfilteredIndex);
894 if (NS_SUCCEEDED(rv)) {
895 SetIndex(unfilteredIndex);
927 sbPlayQueueService::OnBatchBegin(
sbIMediaList* aMediaList)
929 TRACE((
"%s[%p]", __FUNCTION__,
this));
932 mBatchRemovalIndex = mIndex;
936 mRemovedItemGUIDs.Clear();
941 nsresult rv = mMediaList->GetLength(&length);
942 NS_ENSURE_SUCCESS(rv, rv);
944 mBatchBeginAllHistory = length == mIndex;
947 mBatchHelper.
Begin();
953 sbPlayQueueService::OnBatchEnd(
sbIMediaList* aMediaList)
955 TRACE((
"%s[%p]", __FUNCTION__,
this));
963 PRUint32 removedCount = mRemovedItemGUIDs.Length();
964 LOG((
"removed count %u", removedCount));
966 if (removedCount == 0) {
971 for (PRUint32
i = 0;
i < removedCount; ++
i) {
973 nsCOMPtr<sbIMediaItem> item;
974 rv = mLibrary->GetMediaItem(mRemovedItemGUIDs[
i], getter_AddRefs(item));
975 if (NS_FAILED(rv) || ! item) {
980 rv = mMediaList->Contains(item, &contains);
986 rv = mLibrary->Remove(item);
987 NS_ENSURE_SUCCESS(rv, rv);
991 mRemovedItemGUIDs.Clear();
992 LOG((
"Changing index from %i to %i", mIndex, mBatchRemovalIndex));
993 SetIndex(mBatchRemovalIndex);
1000 sbPlayQueueService::OnItemAdded(
sbIMediaList* aMediaList,
1003 PRBool* aNoMoreForBatch)
1005 TRACE((
"%s[%p]", __FUNCTION__,
this));
1009 nsCOMPtr<sbIMutablePropertyArray> props =
1012 NS_LITERAL_STRING(
"1"));
1013 NS_ENSURE_SUCCESS(rv, rv);
1014 rv = mExternalListener->SetPropertiesNoSync(aMediaItem, props);
1015 NS_ENSURE_SUCCESS(rv, rv);
1017 if (mIgnoreListListener ||
1018 (mSequencerOnQueue && mSequencerPlayingOrPaused) ||
1019 mLibraryListener->ShouldIgnore())
1027 PRBool wasAllHistory;
1029 wasAllHistory = mBatchBeginAllHistory;
1032 rv = mMediaList->GetLength(&length);
1033 NS_ENSURE_SUCCESS(rv, rv);
1037 wasAllHistory = length == mIndex + 1;
1044 if (aIndex <= mIndex && !(wasAllHistory && aIndex == mIndex)) {
1045 SetIndex(mIndex + 1);
1048 LOG((
"Added item at index %u, current index is now %i", aIndex, mIndex));
1053 sbPlayQueueService::OnBeforeItemRemoved(
sbIMediaList* aMediaList,
1056 PRBool* aNoMoreForBatch)
1058 TRACE((
"%s[%p]", __FUNCTION__,
this));
1059 NS_ENSURE_ARG_POINTER(aMediaItem);
1062 if (mIgnoreListListener || mLibraryListener->ShouldIgnore())
1068 LOG((
"Removing item at index %u", aIndex));
1071 rv = aMediaItem->GetGuid(guid);
1072 NS_ENSURE_SUCCESS(rv, rv);
1074 LOG((
"Removed item guid: %s",
1075 NS_ConvertUTF16toUTF8(guid).BeginReading()));
1077 if (mRemovedItemGUIDs.IndexOf(guid) == mRemovedItemGUIDs.NoIndex) {
1078 nsString* success = mRemovedItemGUIDs.AppendElement(guid);
1079 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1085 if (aIndex < mIndex) {
1086 mBatchRemovalIndex--;
1090 if (aNoMoreForBatch) {
1091 *aNoMoreForBatch = PR_FALSE;
1098 sbPlayQueueService::OnAfterItemRemoved(
sbIMediaList* aMediaList,
1101 PRBool* aNoMoreForBatch)
1103 TRACE((
"%s[%p]", __FUNCTION__,
this));
1104 NS_ENSURE_ARG_POINTER(aMediaList);
1105 NS_ENSURE_ARG_POINTER(aMediaItem);
1108 if (mIgnoreListListener ||
1109 (mSequencerOnQueue && mSequencerPlayingOrPaused) ||
1110 mLibraryListener->ShouldIgnore())
1118 LOG((
"Non batch item removed from index %u", aIndex));
1119 LOG((
"aIndex %u, mIndex %u", aIndex, mIndex));
1120 if (aIndex < mIndex) {
1121 SetIndex(mIndex - 1);
1125 rv = mMediaList->Contains(aMediaItem, &contains);
1126 NS_ENSURE_SUCCESS(rv, rv);
1129 LOG((
"Removing the item from the library"));
1130 rv = mLibrary->Remove(aMediaItem);
1131 NS_ENSURE_SUCCESS(rv, rv);
1140 sbPlayQueueService::OnItemUpdated(
sbIMediaList* aMediaList,
1143 PRBool* aNoMoreForBatch)
1145 TRACE((
"%s[%p]", __FUNCTION__,
this));
1153 sbPlayQueueService::OnItemMoved(
sbIMediaList* aMediaList,
1154 PRUint32 aFromIndex,
1156 PRBool* aNoMoreForBatch)
1158 TRACE((
"%s[%p]", __FUNCTION__,
this));
1160 if (mIgnoreListListener ||
1161 (mSequencerOnQueue && mSequencerPlayingOrPaused) ||
1162 mLibraryListener->ShouldIgnore())
1171 if (aFromIndex == mIndex) {
1173 }
else if (aFromIndex < mIndex && aToIndex >= mIndex) {
1174 SetIndex(mIndex - 1);
1175 }
else if (aFromIndex > mIndex && aToIndex <= mIndex) {
1176 SetIndex(mIndex + 1);
1179 LOG((
"Item was moved from %u to %u, new index: %i", aFromIndex, aToIndex, mIndex));
1185 sbPlayQueueService::OnBeforeListCleared(
sbIMediaList* aMediaList,
1186 PRBool aExcludeLists,
1187 PRBool* aNoMoreForBatch)
1189 TRACE((
"%s[%p]", __FUNCTION__,
this));
1191 if (mIgnoreListListener || mLibraryListener->ShouldIgnore()) {
1195 if (aNoMoreForBatch) {
1196 *aNoMoreForBatch = PR_FALSE;
1202 sbPlayQueueService::OnListCleared(
sbIMediaList* aMediaList,
1203 PRBool aExcludeLists,
1204 PRBool* aNoMoreForBatch)
1206 TRACE((
"%s[%p]", __FUNCTION__,
this));
1208 if (mIgnoreListListener || mLibraryListener->ShouldIgnore()) {
1212 LOG((
"Clearing all items, but not lists, from queue library"));
1213 nsresult rv = mLibrary->ClearItems();
1214 NS_ENSURE_SUCCESS(rv, rv);
1230 TRACE((
"%s[%p]", __FUNCTION__,
this));
1232 NS_ENSURE_ARG_POINTER(aEvent);
1236 rv = aEvent->GetType(&eventType);
1237 NS_ENSURE_SUCCESS(rv, rv);
1239 LOG((
"Event type 0x%x", eventType));
1242 nsCOMPtr<sbIMediacoreManager> manager =
1243 do_QueryReferent(mWeakMediacoreManager, &rv);
1244 NS_ENSURE_SUCCESS(rv, rv);
1246 nsCOMPtr<sbIMediacoreSequencer> sequencer;
1247 rv = manager->GetSequencer(getter_AddRefs(sequencer));
1248 NS_ENSURE_SUCCESS(rv, rv);
1250 nsCOMPtr<sbIMediacoreStatus> status = do_QueryInterface(sequencer, &rv);
1251 NS_ENSURE_SUCCESS(rv, rv);
1254 rv = status->GetState(&state);
1255 NS_ENSURE_SUCCESS(rv, rv);
1263 rv = OnViewChange(aEvent);
1264 NS_ENSURE_SUCCESS(rv, rv);
1270 if (!mSequencerOnQueue) {
1274 switch (eventType) {
1277 mExplicitStop = PR_TRUE;
1284 if (!mExplicitStop) {
1286 rv = SetIndex(mIndex + 1);
1287 NS_ENSURE_SUCCESS(rv, rv);
1289 mExplicitStop = PR_FALSE;
1294 rv = OnTrackChange(aEvent);
1295 NS_ENSURE_SUCCESS(rv, rv);
1299 rv = OnTrackIndexChange(aEvent);
1300 NS_ENSURE_SUCCESS(rv, rv);
1313 TRACE((
"%s[%p]", __FUNCTION__,
this));
1314 NS_ENSURE_ARG_POINTER(aEvent);
1319 nsCOMPtr<nsIVariant> variant;
1320 rv = aEvent->GetData(getter_AddRefs(variant));
1321 NS_ENSURE_SUCCESS(rv, rv);
1323 nsCOMPtr<nsISupports> supports;
1324 rv = variant->GetAsISupports(getter_AddRefs(supports));
1325 NS_ENSURE_SUCCESS(rv, rv);
1327 nsCOMPtr<sbIMediaListView> view = do_QueryInterface(supports, &rv);
1328 NS_ENSURE_SUCCESS(rv, rv);
1330 nsCOMPtr<sbIMediaList> viewList;
1331 rv = view->GetMediaList(getter_AddRefs(viewList));
1332 NS_ENSURE_SUCCESS(rv, rv);
1335 rv = viewList->Equals(mMediaList, &onQueue);
1336 NS_ENSURE_SUCCESS(rv, rv);
1337 LOG((
"Is the view change a view of our list? %i", onQueue));
1339 mSequencerOnQueue = onQueue;
1347 TRACE((
"%s[%p]", __FUNCTION__,
this));
1348 NS_ENSURE_ARG_POINTER(aEvent);
1350 nsresult rv = SetIndexToPlayingTrack();
1351 NS_ENSURE_SUCCESS(rv, rv);
1359 TRACE((
"%s[%p]", __FUNCTION__,
this));
1360 NS_ENSURE_ARG_POINTER(aEvent);
1362 if (mSequencerPlayingOrPaused) {
1363 nsresult rv = SetIndexToPlayingTrack();
1364 NS_ENSURE_SUCCESS(rv, rv);
1377 sbPlayQueueService::OnItemCopied(
sbIMediaItem* aSourceItem,
1380 TRACE((
"%s[%p]", __FUNCTION__,
this));
1383 nsCOMPtr<sbIMutablePropertyArray> props =
1386 NS_LITERAL_STRING(
"0"));
1387 NS_ENSURE_SUCCESS(rv, rv);
1389 NS_ENSURE_STATE(mExternalListener);
1390 rv = mExternalListener->SetPropertiesNoSync(aDestinationItem, props);
1391 NS_ENSURE_SUCCESS(rv, rv);
1403 sbPlayQueueService::Observe(
nsISupports* aSubject,
1405 const PRUnichar*
aData)
1408 NS_ENSURE_ARG_POINTER(aTopic);
1411 TRACE((
"%s[%p]: Observing %s", __FUNCTION__,
this, aTopic));
1413 nsCOMPtr<nsIObserverService> observerService =
1414 do_GetService(
"@mozilla.org/observer-service;1", &rv);
1415 NS_ENSURE_SUCCESS(rv, rv);
1418 rv = observerService->RemoveObserver(
this, aTopic);
1419 NS_ENSURE_SUCCESS(rv, rv);
1422 nsCOMPtr<nsISupportsWeakReference> weak =
1424 NS_ENSURE_SUCCESS(rv, rv);
1426 rv = weak->GetWeakReference(getter_AddRefs(mWeakMediacoreManager));
1427 NS_ENSURE_SUCCESS(rv, rv);
1430 nsCOMPtr<sbIMediacoreEventTarget> target =
1431 do_QueryReferent(mWeakMediacoreManager, &rv);
1432 NS_ENSURE_SUCCESS(rv, rv);
1434 rv = target->AddListener(
this);
1435 NS_ENSURE_SUCCESS(rv, rv);
1438 nsresult rv = InitLibrary();
1439 NS_ENSURE_SUCCESS(rv, rv);
1442 rv = InitMediaList();
1443 NS_ENSURE_SUCCESS(rv, rv);
1445 NS_ENSURE_STATE(mMediaList);
1449 rv = mMediaList->AddListener(
this,
1460 NS_ENSURE_SUCCESS(rv, rv);
1464 NS_ENSURE_TRUE(mLibraryListener, NS_ERROR_OUT_OF_MEMORY);
1466 rv = mLibrary->AddListener(mLibraryListener,
1471 NS_ENSURE_SUCCESS(rv, rv);
1473 mInitialized = PR_TRUE;
1485 TRACE((
"%s[%p]", __FUNCTION__,
this));
1486 nsISupportsHashKey* success = mListeners.PutEntry(aListener);
1487 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1495 TRACE((
"%s[%p]", __FUNCTION__,
this));
1496 mListeners.RemoveEntry(aListener);
1501 PLDHashOperator PR_CALLBACK
1502 sbPlayQueueService::OnIndexUpdatedCallback(nsISupportsHashKey* aKey,
1505 TRACE((
"%s[static]", __FUNCTION__));
1506 NS_ASSERTION(aKey && aUserData,
"Args should not be null!");
1509 nsCOMPtr<sbIPlayQueueServiceListener>
listener =
1510 do_QueryInterface(aKey->GetKey(), &rv);
1512 if (NS_SUCCEEDED(rv)) {
1513 PRUint32*
index =
static_cast<PRUint32*
>(aUserData);
1514 rv = listener->OnIndexUpdated(*index);
1515 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
1516 "OnIndexUpdated returned a failure code");
1518 return PL_DHASH_NEXT;
1522 sbPlayQueueService::NotifyQueueOperationStarted() {
1523 TRACE((
"%s[%p]", __FUNCTION__,
this));
1525 NS_ASSERTION(NS_IsMainThread(),
1526 "NotifyQueueOperationStarted() must be called from the main thread");
1528 mOperationInProgress = PR_TRUE;
1529 return mListeners.EnumerateEntries(OnQueueStartedCallback, nsnull);
1533 sbPlayQueueService::NotifyQueueOperationCompleted() {
1534 TRACE((
"%s[%p]", __FUNCTION__,
this));
1536 NS_ASSERTION(NS_IsMainThread(),
1537 "NotifyQueueOperationCompleted() must be called from the main thread");
1539 mListeners.EnumerateEntries(OnQueueCompletedCallback, nsnull);
1540 mOperationInProgress = PR_FALSE;
1545 PLDHashOperator PR_CALLBACK
1546 sbPlayQueueService::OnQueueStartedCallback(nsISupportsHashKey* aKey,
1549 TRACE((
"%s[static]", __FUNCTION__));
1550 NS_ASSERTION(aKey,
"aKey should not be null!");
1553 nsCOMPtr<sbIPlayQueueServiceListener> listener =
1554 do_QueryInterface(aKey->GetKey(), &rv);
1556 if (NS_SUCCEEDED(rv)) {
1557 listener->OnQueueOperationStarted();
1559 return PL_DHASH_NEXT;
1562 PLDHashOperator PR_CALLBACK
1563 sbPlayQueueService::OnQueueCompletedCallback(nsISupportsHashKey* aKey,
1566 TRACE((
"%s[static]", __FUNCTION__));
1567 NS_ASSERTION(aKey,
"Args should not be null!");
1570 nsCOMPtr<sbIPlayQueueServiceListener> listener =
1571 do_QueryInterface(aKey->GetKey(), &rv);
1573 if (NS_SUCCEEDED(rv)) {
1574 listener->OnQueueOperationCompleted();
1576 return PL_DHASH_NEXT;
1588 const char *aLoaderStr,
1590 const nsModuleComponentInfo *aInfo)
1592 NS_ENSURE_ARG_POINTER(aCompMgr);
1593 NS_ENSURE_ARG_POINTER(aPath);
1594 NS_ENSURE_ARG_POINTER(aLoaderStr);
1595 NS_ENSURE_ARG_POINTER(aType);
1596 NS_ENSURE_ARG_POINTER(aInfo);
1598 nsresult rv = NS_ERROR_UNEXPECTED;
1599 nsCOMPtr<nsICategoryManager> catMgr =
1600 do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
1601 NS_ENSURE_SUCCESS(rv, rv);
1603 rv = catMgr->AddCategoryEntry(APPSTARTUP_CATEGORY,
1610 NS_ENSURE_SUCCESS(rv, rv);
attribute unsigned long index
Index of the current track in the Play Queue.
static NS_METHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
const SB_LIBRARY_MANAGER_READY_TOPIC
static nsCOMPtr< nsIObserverService > observerService
void SetIgnoreListListener(PRBool aIgnore)
const NS_PREFSERVICE_CONTRACTID
Songbird Library Manager Definition.
Interface used to listen for items being copied from a library.
#define SB_PLAYQUEUESERVICE_CONTRACTID
friend class sbPlayQueueAsyncListener
Class to allow items in a "master" internal library to stay in sync with duplicates in other librarie...
#define SB_PROPERTY_ISSORTABLE
#define SB_LIBRARY_TRACKSADDED
Songbird Play Queue Service Component Definition.
#define SB_PROPERTY_PLAYQUEUE_MEDIALIST_GUID
Listener for the Play Queue service.
#define SB_PLAYQUEUESERVICE_CLASSNAME
#define SB_PLAYQUEUE_DEFAULTCOLUMNSPEC
#define SB_PREF_PLAYQUEUE_LIBRARY
NS_IMPL_THREADSAFE_ISUPPORTS2(sbPlayQueueAsyncListener, sbIAddMediaItemsListener, sbIMediaListAsyncListener)
#define SB_PROPERTY_ISREADONLY
#define SB_PROPERTY_DEFAULTCOLUMNSPEC
#define SB_NAMEKEY_PLAYQUEUE_LIST
#define SB_PLAYQUEUE_PANE_TITLE
virtual ~sbPlayQueueService()
#define SB_DATAREMOTE_FACEPLATE_STATUS
StringArrayEnumerator prototype hasMore
Service for interacting with the Play Queue.
NS_IMPL_ISUPPORTS5(sbPlayQueueService, sbIPlayQueueService, sbIMediaListListener, sbIMediacoreEventListener, sbILocalDatabaseLibraryCopyListener, nsIObserver) sbPlayQueueService
NS_DECL_ISUPPORTS NS_DECL_SBIADDMEDIAITEMSLISTENER sbPlayQueueAsyncListener(sbPlayQueueService *aService)
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
virtual ~sbPlayQueueAsyncListener()
_getSelectedPageStyle s i
const SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC
_updateTextAndScrollDataForFrame aData