PlaylistCommandsManager.cpp
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2010 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
31 #include "nscore.h"
32 
33 #include "nspr.h"
34 #include "nsCOMPtr.h"
35 #include "rdf.h"
36 
37 #include "nsIInterfaceRequestor.h"
38 #include "nsIComponentManager.h"
39 #include "nsIServiceManager.h"
40 #include "nsIComponentManager.h"
41 
42 #include "nsITimer.h"
43 
44 #include "nsComponentManagerUtils.h"
45 #include "nsServiceManagerUtils.h"
46 #include "nsCOMArray.h"
47 #include "nsIMutableArray.h"
48 #include "nsEnumeratorUtils.h"
49 #include "nsArrayUtils.h"
50 #include "nsArrayEnumerator.h"
51 
52 #include "nsCRTGlue.h"
53 #include <nsStringGlue.h>
54 
55 #include <sbStringUtils.h>
56 #include <sbStandardProperties.h>
57 #include <sbIMediaList.h>
58 #include <sbILibrary.h>
59 #include <sbILibraryManager.h>
60 
61 #define MODULE_SHORTCIRCUIT 0
62 
63 #if MODULE_SHORTCIRCUIT
64 # define METHOD_SHORTCIRCUIT return NS_OK;
65 # define VMETHOD_SHORTCIRCUIT return;
66 #else
67 # define METHOD_SHORTCIRCUIT
68 # define VMETHOD_SHORTCIRCUIT
69 #endif
70 
72 
73 //-----------------------------------------------------------------------------
75 {
76 } //ctor
77 
78 //-----------------------------------------------------------------------------
80 {
81 } //dtor
82 
83 //-----------------------------------------------------------------------------
84 nsresult
85 CPlaylistCommandsManager::FindOrCreateRootCommand(commandobjmap_t *map,
86  const nsAString &aSearchString,
88 {
89  NS_ENSURE_ARG_POINTER(map);
90  NS_ENSURE_ARG_POINTER(_retval);
91 
92  nsresult rv;
93  nsString searchString(aSearchString);
94  nsCOMPtr<sbIPlaylistCommandsBuilder> rootCommand;
95  commandobjmap_t::iterator iter = map->find(searchString);
96  if (iter != map->end()) {
97  // if we find a root playlistCommands object, return it
98  rootCommand = iter->second;
99  }
100  else {
101  // if we can't find a root playlistCommands object, make one
102  rootCommand = do_CreateInstance
103  ("@songbirdnest.com/Songbird/PlaylistCommandsBuilder;1", &rv);
104  NS_ENSURE_SUCCESS(rv, rv);
105 
106  // initialize the new playlistcommand with an id of the search param
107  rv = rootCommand->Init(searchString);
108  NS_ENSURE_SUCCESS(rv, rv);
109  (*map)[searchString] = rootCommand;
110 
111  // Check if there are listeners waiting for this root command to be created.
112  // If there are, add the listeners to the newly created command.
113  listenermap_t::iterator it;
114  it = m_ListenerMap.find(searchString);
115  if (it != m_ListenerMap.end())
116  {
117  nsCOMArray<sbIPlaylistCommandsListener> listeners = it->second;
118  PRUint32 length = listeners.Count();
119  for (PRUint32 i=0; i < length; i++)
120  {
121  rv = rootCommand->AddListener(listeners[i]);
122  NS_ENSURE_SUCCESS(rv, rv);
123  }
124  }
125  }
126  NS_ADDREF(*_retval = rootCommand);
127  return NS_OK;
128 }
129 
130 //-----------------------------------------------------------------------------
131 NS_IMETHODIMP
134  const nsAString &aContextGUID,
135  const nsAString &aPlaylistType,
136  sbIPlaylistCommands *aCommandObj)
137 {
138  NS_ENSURE_ARG_POINTER(map);
139  NS_ENSURE_ARG_POINTER(aCommandObj);
140 
142 
143  nsString key(aContextGUID);
144  nsString type(aPlaylistType);
145  nsString id;
146 
147  nsresult rv = aCommandObj->GetId(id);
148  if ( !NS_SUCCEEDED(rv) || id.IsEmpty() )
149  {
150  NS_ERROR("PlaylistCommandsManager::Cannot register a playlist command without an id");
151  return NS_ERROR_INVALID_ARG;
152  }
153  nsCOMPtr<sbIPlaylistCommandsBuilder> rootCommand;
154 
155  // check if the caller gave a type
156  if (!type.IsEmpty()) {
157  rv = FindOrCreateRootCommand(map, type, getter_AddRefs(rootCommand));
158  NS_ENSURE_SUCCESS(rv, rv);
159 
160  rv = rootCommand->AddCommandObject(aCommandObj);
161  NS_ENSURE_SUCCESS(rv, rv);
162  }
163 
164  // check if the caller gave a guid
165  if (!key.IsEmpty()) {
166  rv = FindOrCreateRootCommand(map, key, getter_AddRefs(rootCommand));
167  NS_ENSURE_SUCCESS(rv, rv);
168 
169  rv = rootCommand->AddCommandObject(aCommandObj);
170  NS_ENSURE_SUCCESS(rv, rv);
171  }
172 
173  return NS_OK;
174 }
175 
176 //-----------------------------------------------------------------------------
177 NS_IMETHODIMP
180  const nsAString &aContextGUID,
181  const nsAString &aPlaylistType,
182  sbIPlaylistCommands *aCommandObj)
183 {
184  NS_ENSURE_ARG_POINTER(map);
185  NS_ENSURE_ARG_POINTER(aCommandObj);
186  nsresult rv;
187 
189 
190  nsString key(aContextGUID);
191  nsString type(aPlaylistType);
192 
193  nsCOMPtr<sbIPlaylistCommands> rootCommand;
194 
195  if (!type.IsEmpty()) {
196  commandobjmap_t::iterator iter = map->find(type);
197  if (iter != map->end()) {
198  rootCommand = iter->second;
199  rv = rootCommand->RemoveCommandObject(aCommandObj);
200  NS_ENSURE_SUCCESS(rv, rv);
201 
202  PRInt32 numCommands;
203  rv = rootCommand->GetNumCommands(SBVoidString(),
204  SBVoidString(),
205  &numCommands);
206  NS_ENSURE_SUCCESS(rv, rv);
207 
208  if (numCommands == 0) {
209  rv = rootCommand->ShutdownCommands();
210  NS_ENSURE_SUCCESS(rv, rv);
211 
212  map->erase(iter);
213  }
214  }
215  }
216 
217  if (!key.IsEmpty()) {
218  commandobjmap_t::iterator iter = map->find(key);
219  if (iter != map->end()) {
220  rootCommand = iter->second;
221  rv = rootCommand->RemoveCommandObject(aCommandObj);
222  NS_ENSURE_SUCCESS(rv, rv);
223 
224  PRInt32 numCommands;
225  rv = rootCommand->GetNumCommands(SBVoidString(),
226  SBVoidString(),
227  &numCommands);
228  NS_ENSURE_SUCCESS(rv, rv);
229 
230  if (numCommands == 0) {
231  rv = rootCommand->ShutdownCommands();
232  NS_ENSURE_SUCCESS(rv, rv);
233 
234  map->erase(iter);
235  }
236  }
237  }
238 
239  return NS_OK;
240 }
241 
242 //-----------------------------------------------------------------------------
243 NS_IMETHODIMP
244 CPlaylistCommandsManager::GetPlaylistCommands(commandobjmap_t *map,
245  const nsAString &aContextGUID,
246  const nsAString &aPlaylistType,
247  sbIPlaylistCommands **_retval)
248 {
249  NS_ENSURE_ARG_POINTER(map);
250  NS_ENSURE_ARG_POINTER(_retval);
251 
253 
254  nsString key(aContextGUID);
255  nsString type(aPlaylistType);
256 
257  nsCOMPtr<sbIPlaylistCommands> rootCommand;
258 
259  commandobjmap_t::iterator iterGUID = map->find(key);
260  if (iterGUID != map->end())
261  {
262  // if we find the rootCommand for the guid, return it
263  NS_ADDREF(*_retval = iterGUID->second);
264  return NS_OK;
265  }
266 
267  commandobjmap_t::iterator iterType = map->find(type);
268  if (iterType != map->end())
269  {
270  // if we find the rootCommand for the type, return it
271  NS_ADDREF(*_retval = iterType->second);
272  return NS_OK;
273  }
274 
275  *_retval = nsnull;
276  return NS_OK;
277 }
278 
279 //-----------------------------------------------------------------------------
282 
284  (CPlaylistCommandsManager* aCmdMgr)
285 {
286  m_CmdMgr = aCmdMgr;
287 }
288 
290 {
291 }
292 
293 /* A utility method to retrieve the saved commands in aSavedCommandsMap
294  * and add or remove them to the appropriate location for the medialist
295  * described by aListGuid.
296  * The location for registration/unregistration is determined by the
297  * commandobjmap_t passed in as aRegistrationMap and whether registration or
298  * unregistration is performed is determined by aIsRegistering */
299 nsresult
300 LibraryPlaylistCommandsListener::HandleSavedLibraryCommands
301  (PRBool aIsRegistering,
302  libraryGuidToCommandsMap_t *aSavedCommandsMap,
303  commandobjmap_t *aRegistrationMap,
304  const nsAString &aLibraryGUID,
305  const nsAString &aListGUID)
306 {
307  NS_ENSURE_ARG_POINTER(aSavedCommandsMap);
308  NS_ENSURE_ARG_POINTER(aRegistrationMap);
309  nsresult rv;
310 
311  nsString libGuid(aLibraryGUID);
312 
313  // Search the saved commands for any registered to our library
314  libraryGuidToCommandsMap_t::iterator searchCmdsIter =
315  aSavedCommandsMap->find(libGuid);
316 
317  /* If we find some registered commands, we'll need to handle them*/
318  if (searchCmdsIter != aSavedCommandsMap->end()) {
319 
320  // Get the commands registered for this library
321  nsCOMArray<sbIPlaylistCommands> *registeredCommands =
322  &searchCmdsIter->second;
323 
324  // Add or remove all of the commands from the list
325  PRUint32 length = registeredCommands->Count();
326  for (PRUint32 i = 0; i < length; i++) {
327  nsCOMPtr<sbIPlaylistCommands> command = (*registeredCommands)[i];
328 
329  if (aIsRegistering) {
330  rv = m_CmdMgr->RegisterPlaylistCommands
331  (aRegistrationMap,
332  aListGUID,
333  SBVoidString(),
334  command);
335  NS_ENSURE_SUCCESS(rv, rv);
336  }
337  else {
338  rv = m_CmdMgr->UnregisterPlaylistCommands
339  (aRegistrationMap,
340  aListGUID,
341  SBVoidString(),
342  command);
343  NS_ENSURE_SUCCESS(rv, rv);
344 
345  }
346  }
347  }
348 
349  return NS_OK;
350 }
351 
352 nsresult
353 LibraryPlaylistCommandsListener::RegisterSavedLibraryCommands
354  (libraryGuidToCommandsMap_t *aSavedCommandsMap,
355  commandobjmap_t *aRegistrationMap,
356  const nsAString &aLibraryGUID,
357  const nsAString &aListGUID)
358 {
359  NS_ENSURE_ARG_POINTER(aSavedCommandsMap);
360  NS_ENSURE_ARG_POINTER(aRegistrationMap);
361 
362  return HandleSavedLibraryCommands(PR_TRUE,
363  aSavedCommandsMap,
364  aRegistrationMap,
365  aLibraryGUID,
366  aListGUID);
367 }
368 
369 nsresult
370 LibraryPlaylistCommandsListener::UnregisterSavedLibraryCommands
371  (libraryGuidToCommandsMap_t *aSavedCommandsMap,
372  commandobjmap_t *aRegistrationMap,
373  const nsAString &aLibraryGUID,
374  const nsAString &aListGUID)
375 {
376  NS_ENSURE_ARG_POINTER(aSavedCommandsMap);
377  NS_ENSURE_ARG_POINTER(aRegistrationMap);
378 
379  return HandleSavedLibraryCommands(PR_FALSE,
380  aSavedCommandsMap,
381  aRegistrationMap,
382  aLibraryGUID,
383  aListGUID);
384 }
385 
386 NS_IMETHODIMP
387 LibraryPlaylistCommandsListener::OnItemAdded(sbIMediaList *aMediaList,
388  sbIMediaItem *aMediaItem,
389  PRUint32 aIndex,
390  PRBool *_retval)
391 {
392  NS_ENSURE_ARG_POINTER(aMediaList);
393  NS_ENSURE_ARG_POINTER(aMediaItem);
394  nsresult rv;
395 
396  // Check if the added item is a list
397  nsCOMPtr<sbIMediaList> list = do_QueryInterface(aMediaItem, &rv);
398  if (NS_FAILED(rv) || !list) {
399  // we are only concerned with added lists so stop for anything else
400  return NS_OK;
401  }
402 
403  nsString listGuid;
404  rv = aMediaItem->GetGuid(listGuid);
405  NS_ENSURE_SUCCESS(rv, rv);
406 
407  // Get the added item's library and library guid
408  nsCOMPtr<sbILibrary> library;
409  rv = aMediaItem->GetLibrary(getter_AddRefs(library));
410  NS_ENSURE_SUCCESS(rv, rv);
411 
412  nsString libGuid;
413  rv = library->GetGuid(libGuid);
414  NS_ENSURE_SUCCESS(rv, rv);
415 
416  // Register any saved service pane commands that would apply to this new list
417  rv = RegisterSavedLibraryCommands
419  &m_CmdMgr->m_ServicePaneCommandObjMap,
420  libGuid,
421  listGuid);
422  NS_ENSURE_SUCCESS(rv, rv);
423 
424  // Register any saved mediaitem context menu or toolbar commands that
425  // would apply to this new list
426  rv = RegisterSavedLibraryCommands
428  &m_CmdMgr->m_PlaylistCommandObjMap,
429  libGuid,
430  listGuid);
431  NS_ENSURE_SUCCESS(rv, rv);
432 
433  return NS_OK;
434 }
435 
436 NS_IMETHODIMP
437 LibraryPlaylistCommandsListener::OnBeforeItemRemoved(sbIMediaList *aMediaList,
438  sbIMediaItem *aMediaItem,
439  PRUint32 aIndex,
440  PRBool *_retval)
441 {
442  NS_ENSURE_ARG_POINTER(aMediaList);
443  NS_ENSURE_ARG_POINTER(aMediaItem);
444 
445  nsresult rv;
446 
447  // Check if the item being removed is a list
448  nsCOMPtr<sbIMediaList> list = do_QueryInterface(aMediaItem, &rv);
449  if (NS_FAILED(rv) || !list) {
450  // we are only concerned with medialists, this isn't one so we're done
451  return NS_OK;
452  }
453 
454  nsString listGuid;
455  rv = aMediaItem->GetGuid(listGuid);
456  NS_ENSURE_SUCCESS(rv, rv);
457 
458  // Get the removed item's library and library guid
459  nsCOMPtr<sbILibrary> library;
460  rv = aMediaItem->GetLibrary(getter_AddRefs(library));
461  NS_ENSURE_SUCCESS(rv, rv);
462 
463  nsString libGuid;
464  rv = library->GetGuid(libGuid);
465  NS_ENSURE_SUCCESS(rv, rv);
466 
467  // Unregister any saved service pane commands that applied to the list being
468  // deleted
469  rv = UnregisterSavedLibraryCommands
471  &m_CmdMgr->m_ServicePaneCommandObjMap,
472  libGuid,
473  listGuid);
474  NS_ENSURE_SUCCESS(rv, rv);
475 
476  // Unregister any saved mediaitem context menu or toolbar commands that
477  // applied to the list being deleted
478  rv = UnregisterSavedLibraryCommands
480  &m_CmdMgr->m_PlaylistCommandObjMap,
481  libGuid,
482  listGuid);
483  NS_ENSURE_SUCCESS(rv, rv);
484 
485  return NS_OK;
486 }
487 
488 // Listener methods that we don't need
489 NS_IMETHODIMP
490 LibraryPlaylistCommandsListener::OnAfterItemRemoved(sbIMediaList *aMediaList,
491  sbIMediaItem *aMediaItem,
492  PRUint32 aIndex,
493  PRBool *_retval)
494 { return NS_OK; }
495 
496 NS_IMETHODIMP
497 LibraryPlaylistCommandsListener::OnItemUpdated(sbIMediaList *aMediaList,
498  sbIMediaItem *aMediaItem,
499  sbIPropertyArray *aProperties,
500  PRBool *aRetVal)
501 { return NS_OK; }
502 
503 NS_IMETHODIMP
504 LibraryPlaylistCommandsListener::OnItemMoved(sbIMediaList *aMediaList,
505  PRUint32 aFromIndex,
506  PRUint32 aToIndex,
507  PRBool *aRetVal)
508 { return NS_OK; }
509 
510 NS_IMETHODIMP
511 LibraryPlaylistCommandsListener::OnBeforeListCleared(sbIMediaList *aMediaList,
512  PRBool aExcludeLists,
513  PRBool *aRetVal)
514 { return NS_OK; }
515 
516 NS_IMETHODIMP
517 LibraryPlaylistCommandsListener::OnListCleared(sbIMediaList *aMediaList,
518  PRBool aExcludeLists,
519  PRBool *aRetVal)
520 { return NS_OK; }
521 
522 NS_IMETHODIMP
523 LibraryPlaylistCommandsListener::OnBatchBegin(sbIMediaList *aMediaList)
524 { return NS_OK; }
525 
526 NS_IMETHODIMP
527 LibraryPlaylistCommandsListener::OnBatchEnd(sbIMediaList *aMediaList)
528 { return NS_OK; }
529 
530 //-----------------------------------------------------------------------------
531 nsresult
532 CPlaylistCommandsManager::GetAllMediaListsForLibrary
533  (sbILibrary *aLibrary,
534  nsIArray **_retval)
535 {
536  NS_ENSURE_ARG_POINTER(aLibrary);
537  NS_ENSURE_ARG_POINTER(_retval);
538  nsresult rv;
539 
540  // Get the lists in the library
541  nsCOMPtr<nsIArray> mediaLists;
542  rv = aLibrary->GetItemsByProperty(NS_LITERAL_STRING(SB_PROPERTY_ISLIST),
543  NS_LITERAL_STRING("1"),
544  getter_AddRefs(mediaLists));
545  if (rv == NS_ERROR_NOT_AVAILABLE) {
546  // This library doesn't have any medialists
547  mediaLists =
548  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
549 
550  }
551  NS_ENSURE_SUCCESS(rv, rv);
552 
553  // Add the library itself as another list
554  nsCOMPtr<sbIMediaList> libAsList( do_QueryInterface(aLibrary, &rv) );
555  NS_ENSURE_SUCCESS(rv, rv);
556 
557  nsCOMPtr<nsIMutableArray> mutMediaLists( do_QueryInterface(mediaLists, &rv) );
558  NS_ENSURE_SUCCESS(rv, rv);
559 
560  rv = mutMediaLists->AppendElement(libAsList, PR_FALSE);
561  NS_ENSURE_SUCCESS(rv, rv);
562 
563  NS_ADDREF(*_retval = mutMediaLists);
564 
565  return NS_OK;
566 }
567 
568 //-----------------------------------------------------------------------------
569 NS_IMETHODIMP
570 CPlaylistCommandsManager::RegisterPlaylistCommandsForLibrary
571  (PRBool aTargetServicePane,
572  sbILibrary *aLibrary,
573  sbIPlaylistCommands *aCommandObj)
574 {
575  NS_ENSURE_ARG_POINTER(aLibrary);
576  NS_ENSURE_ARG_POINTER(aCommandObj);
577  nsresult rv;
578 
579  // Get all the medialists for that library, including the library itself
580  nsCOMPtr<nsIArray> mediaLists;
581  rv = GetAllMediaListsForLibrary(aLibrary,
582  getter_AddRefs(mediaLists));
583  NS_ENSURE_SUCCESS(rv, rv);
584 
585  // Determine which map to register the new command in
586  commandobjmap_t* targetMap = (aTargetServicePane ?
589 
590  // Register aCommandObj to the appropriate map for each of the mediaLists
591  PRUint32 length;
592  rv = mediaLists->GetLength(&length);
593  NS_ENSURE_SUCCESS(rv, rv);
594  for (PRUint32 i = 0; i < length; i++) {
595  nsCOMPtr<sbIMediaList> currList = do_QueryElementAt(mediaLists, i, &rv);
596  NS_ENSURE_SUCCESS(rv, rv);
597 
598  nsString guid;
599  rv = currList->GetGuid(guid);
600  NS_ENSURE_SUCCESS(rv, rv);
601 
602  rv = RegisterPlaylistCommands(targetMap,
603  guid,
604  SBVoidString(),
605  aCommandObj);
606  NS_ENSURE_SUCCESS(rv, rv);
607  }
608 
609  /* Save a reference to aCommandObj so that we can retrieve it when a new
610  * mediaList is added to the library we are registering this command to */
611  // Save the command in a map depending on where it is registered
612  libraryGuidToCommandsMap_t *libraryToPlaylistCommandsMap =
613  (aTargetServicePane ? &m_LibraryGuidToServicePaneCommandsMap :
615 
616  nsString libGuid;
617  rv = aLibrary->GetGuid(libGuid);
618  NS_ENSURE_SUCCESS(rv, rv);
619 
620  /* See if we already have any commands registered in this location for this
621  * library */
622  libraryGuidToCommandsMap_t::iterator registeredCommandsIter =
623  libraryToPlaylistCommandsMap->find(libGuid);
624 
625  if (registeredCommandsIter == libraryToPlaylistCommandsMap->end()) {
626  // There are no commands in this location registered to this library yet.
627  // Save the command object to a new nsCOMArray in the saved command map.
628  (*libraryToPlaylistCommandsMap)[libGuid].AppendObject(aCommandObj);
629 
630  /* Add a listener to the library so that we can detect if a new medialist
631  * is added or if one is removed */
632  nsCOMPtr<LibraryPlaylistCommandsListener> listener =
634  NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
635 
636  rv = aLibrary->AddListener(listener,
637  PR_FALSE,
640  nsnull);
641  NS_ENSURE_SUCCESS(rv, rv);
642 
643  // And save a reference to this listener in case we need to unregister
645  }
646  else {
647  // There are other commands registered to this library already.
648  // Retrieve the array of registered commands and add aCommandObj.
649  nsCOMArray<sbIPlaylistCommands> *registeredCommands = &registeredCommandsIter->second;
650  registeredCommands->AppendObject(aCommandObj);
651  }
652 
653  return NS_OK;
654 }
655 
656 //-----------------------------------------------------------------------------
657 NS_IMETHODIMP
658 CPlaylistCommandsManager::UnregisterPlaylistCommandsForLibrary
659  (PRBool aTargetServicePane,
660  sbILibrary *aLibrary,
661  sbIPlaylistCommands *aCommandObj)
662 {
663  NS_ENSURE_ARG_POINTER(aLibrary);
664  NS_ENSURE_ARG_POINTER(aCommandObj);
665  nsresult rv;
666 
667  // Get all medialists in that library, including the library itself
668  nsCOMPtr<nsIArray> mediaLists;
669  rv = GetAllMediaListsForLibrary(aLibrary,
670  getter_AddRefs(mediaLists));
671  NS_ENSURE_SUCCESS(rv, rv);
672 
673  // Determine which map to unregister the new command from
674  commandobjmap_t* targetMap = (aTargetServicePane ?
677 
678  // For each medialist in the library, unregister aCommandObj from it
679  PRUint32 length;
680  rv = mediaLists->GetLength(&length);
681  NS_ENSURE_SUCCESS(rv, rv);
682 
683  bool unregisterFailure = false;
684  for (PRUint32 i = 0; i < length; i++) {
685  nsCOMPtr<sbIMediaList> currList = do_QueryElementAt(mediaLists, i, &rv);
686  if (NS_FAILED(rv)) {
687  unregisterFailure = true;
688  continue;
689  }
690 
691  nsString guid;
692  rv = currList->GetGuid(guid);
693  if (NS_FAILED(rv)) {
694  unregisterFailure = true;
695  continue;
696  }
697 
698  rv = UnregisterPlaylistCommands(targetMap,
699  guid,
700  SBVoidString(),
701  aCommandObj);
702  if (NS_FAILED(rv)) {
703  unregisterFailure = true;
704  }
705  }
706 
707  nsString libGuid;
708  rv = aLibrary->GetGuid(libGuid);
709  NS_ENSURE_SUCCESS(rv, rv);
710 
711  // Finally remove the listener from the library
712  rv = aLibrary->RemoveListener(m_LibraryGuidToLibraryListenerMap[libGuid]);
713  if (NS_FAILED(rv)) {
714  unregisterFailure = true;
715  }
716 
717  if (unregisterFailure) {
718  NS_ERROR("Error while unregistering playlist commands from a library");
719  }
720 
721  return NS_OK;
722 }
723 
724 //-----------------------------------------------------------------------------
725 NS_IMETHODIMP
726 CPlaylistCommandsManager::RegisterPlaylistCommandsMediaList
727  (const nsAString &aContextGUID,
728  const nsAString &aPlaylistType,
729  sbIPlaylistCommands *aCommandObj)
730 {
732  aContextGUID,
733  aPlaylistType,
734  aCommandObj);
735 }
736 
737 //-----------------------------------------------------------------------------
738 NS_IMETHODIMP
739 CPlaylistCommandsManager::UnregisterPlaylistCommandsMediaList
740  (const nsAString &aContextGUID,
741  const nsAString &aPlaylistType,
742  sbIPlaylistCommands *aCommandObj)
743 {
745  aContextGUID,
746  aPlaylistType,
747  aCommandObj);
748 }
749 
750 //-----------------------------------------------------------------------------
751 NS_IMETHODIMP
752 CPlaylistCommandsManager::GetPlaylistCommandsMediaList
753  (const nsAString &aContextGUID,
754  const nsAString &aPlaylistType,
755  sbIPlaylistCommands **_retval)
756 {
757  return GetPlaylistCommands(&m_ServicePaneCommandObjMap,
758  aContextGUID,
759  aPlaylistType,
760  _retval);
761 }
762 
763 //-----------------------------------------------------------------------------
764 NS_IMETHODIMP
765 CPlaylistCommandsManager::RegisterPlaylistCommandsMediaItem
766  (const nsAString &aContextGUID,
767  const nsAString &aPlaylistType,
768  sbIPlaylistCommands *aCommandObj)
769 {
771  aContextGUID,
772  aPlaylistType,
773  aCommandObj);
774 }
775 
776 //-----------------------------------------------------------------------------
777 NS_IMETHODIMP
778 CPlaylistCommandsManager::UnregisterPlaylistCommandsMediaItem
779  (const nsAString &aContextGUID,
780  const nsAString &aPlaylistType,
781  sbIPlaylistCommands *aCommandObj)
782 {
784  aContextGUID,
785  aPlaylistType,
786  aCommandObj);
787 }
788 
789 //-----------------------------------------------------------------------------
790 NS_IMETHODIMP
791 CPlaylistCommandsManager::GetPlaylistCommandsMediaItem
792  (const nsAString &aContextGUID,
793  const nsAString &aPlaylistType,
794  sbIPlaylistCommands **_retval)
795 {
796  return GetPlaylistCommands(&m_PlaylistCommandObjMap,
797  aContextGUID,
798  aPlaylistType,
799  _retval);
800 }
801 
802 //-----------------------------------------------------------------------------
803 nsresult
804 CPlaylistCommandsManager::FindAllRootCommands(const nsAString &aContextGUID,
805  const nsAString &aContextType,
806  nsISimpleEnumerator **_retval)
807 {
808  NS_ENSURE_ARG_POINTER(_retval);
809 
810  nsresult rv;
811  nsString guid(aContextGUID);
812  nsString type(aContextType);
813  nsCOMArray<sbIPlaylistCommands> array;
814  nsCOMPtr<sbIPlaylistCommands> rootCommand;
815 
816  // check if we got a guid to search for
817  if (!guid.IsEmpty())
818  {
819  // check if a root command exists in the medialist map for the guid
820  rv = GetPlaylistCommandsMediaList(guid,
821  SBVoidString(),
822  getter_AddRefs(rootCommand));
823  NS_ENSURE_SUCCESS(rv, rv);
824 
825  if (rootCommand)
826  {
827  // if we find a root command, add it to the array and we'll return it
828  array.AppendObject(rootCommand);
829  }
830 
831  // check if a root command exists in the mediaitem map for the guid
832  rv = GetPlaylistCommandsMediaItem(guid,
833  SBVoidString(),
834  getter_AddRefs(rootCommand));
835  NS_ENSURE_SUCCESS(rv, rv);
836  if (rootCommand)
837  {
838  // if we find a root command, add it to the array and we'll return it
839  array.AppendObject(rootCommand);
840  }
841  }
842 
843  // check if we got a type to search for
844  if (!type.IsEmpty())
845  {
846  // check if a root command exists in the medialist map for the type
847  rv = GetPlaylistCommandsMediaList(SBVoidString(),
848  type,
849  getter_AddRefs(rootCommand));
850  NS_ENSURE_SUCCESS(rv, rv);
851 
852  if (rootCommand)
853  {
854  // if we find a root command, add it to the array and we'll return it
855  array.AppendObject(rootCommand);
856  }
857 
858  // check if a root command exists in the mediaitem map for the type
859  rv = GetPlaylistCommandsMediaItem(SBVoidString(),
860  type,
861  getter_AddRefs(rootCommand));
862  NS_ENSURE_SUCCESS(rv, rv);
863 
864  if (rootCommand)
865  {
866  // if we find a root command, add it to the array and we'll return it
867  array.AppendObject(rootCommand);
868  }
869  }
870 
871  return NS_NewArrayEnumerator(_retval, array);
872 }
873 
874 //-----------------------------------------------------------------------------
875 NS_IMETHODIMP
876 CPlaylistCommandsManager::AddListenerForMediaList(sbIMediaList *aMediaList,
877  sbIPlaylistCommandsListener *aListener)
878 {
879  NS_ENSURE_ARG_POINTER(aMediaList);
880  NS_ENSURE_ARG_POINTER(aListener);
881 
882  nsresult rv;
883  nsString guid;
884  nsString type;
885 
886  rv = aMediaList->GetGuid(guid);
887  NS_ENSURE_SUCCESS(rv, rv);
888 
889  rv = aMediaList->GetType(type);
890  NS_ENSURE_SUCCESS(rv, rv);
891 
892  /* Add listeners to the listener map for guid and type. This map ensures that
893  * if a root command does not exist during this function call, the saved
894  * listeners will be added when the root command is created in
895  * FindOrCreateRootCommand. */
896  m_ListenerMap[guid].AppendObject(aListener);
897  m_ListenerMap[type].AppendObject(aListener);
898 
899  /* Get all the root commands that are registered for this medialist's
900  * guid and type. This function searches both the mediaitem and medialist
901  * maps and returns the found root commands in an enumerator */
902  nsCOMPtr<nsISimpleEnumerator> cmdEnum;
903  rv = FindAllRootCommands(guid, type, getter_AddRefs(cmdEnum));
904  NS_ENSURE_SUCCESS(rv, rv);
905 
906  // for each root command that we found, add the listener
907  PRBool hasMore;
908  while (NS_SUCCEEDED(cmdEnum->HasMoreElements(&hasMore)) && hasMore)
909  {
910  nsCOMPtr<sbIPlaylistCommands> rootCommand;
911  if (NS_SUCCEEDED(cmdEnum->GetNext(getter_AddRefs(rootCommand))) && rootCommand)
912  {
913  // add the param listener to the found root commands
914  rv = rootCommand->AddListener(aListener);
915  NS_ENSURE_SUCCESS(rv, rv);
916  }
917  }
918 
919  return NS_OK;
920 }
921 
922 //-----------------------------------------------------------------------------
923 nsresult
924 CPlaylistCommandsManager::RemoveListenerFromRootCommands
925  (const nsString &aContextGUID,
926  const nsString &aPlaylistType,
927  sbIPlaylistCommandsListener *aListener)
928 {
929  NS_ENSURE_ARG_POINTER(aListener);
930 
931  // get all of the root sbIPlaylistCommands that fit the param guid and/or type
932  nsCOMPtr<nsISimpleEnumerator> rootCmdEnum;
933  nsresult rv = FindAllRootCommands(aContextGUID, aPlaylistType, getter_AddRefs(rootCmdEnum));
934  NS_ENSURE_SUCCESS(rv, rv);
935 
936  // for each root command found, remove the param aListener
937  PRBool hasMore;
938  while (NS_SUCCEEDED(rootCmdEnum->HasMoreElements(&hasMore)) && hasMore)
939  {
940  nsCOMPtr<sbIPlaylistCommands> rootCommand;
941  if (NS_SUCCEEDED(rootCmdEnum->GetNext(getter_AddRefs(rootCommand))) && rootCommand)
942  {
943  rv = rootCommand->RemoveListener(aListener);
944  NS_ENSURE_SUCCESS(rv, rv);
945  }
946  }
947  return NS_OK;
948 }
949 
950 nsresult
951 CPlaylistCommandsManager::RemoveListenerInListenerMap
952  (const nsString &aSearchString,
953  sbIPlaylistCommandsListener *aListener)
954 {
955  NS_ENSURE_ARG_POINTER(aListener);
956 
957  listenermap_t::iterator foundListeners;
958  // get the vector of listeners saved for aSearchString
959  foundListeners = m_ListenerMap.find(aSearchString);
960 
961  // make sure there are listeners saved for the search string
962  if (foundListeners != m_ListenerMap.end())
963  {
964  // the m_ListenerMap stores an nsCOMArray of listeners that we need to scan
965  // to find the listener that we want to remove
966  nsCOMArray<sbIPlaylistCommandsListener> *listeners = &foundListeners->second;
967  PRUint32 length = listeners->Count();
968  for (PRUint32 i=0; i < length; i++)
969  {
970  if ((*listeners)[i] == aListener)
971  {
972  listeners->RemoveObjectAt(i);
973  i--;
974  length--;
975 
976  // Check if we removed the last element in that array of listeners.
977  // If we did, remove that array from the map.
978  if (length == 0)
979  {
980  m_ListenerMap.erase(foundListeners);
981  return NS_OK;
982  }
983  }
984  }
985  }
986  return NS_OK;
987 }
988 
989 NS_IMETHODIMP
990 CPlaylistCommandsManager::RemoveListenerForMediaList(sbIMediaList *aMediaList,
991  sbIPlaylistCommandsListener *aListener)
992 {
993  NS_ENSURE_ARG_POINTER(aMediaList);
994  NS_ENSURE_ARG_POINTER(aListener);
995 
996  nsresult rv;
997  nsString guid;
998  nsString type;
999 
1000  rv = aMediaList->GetGuid(guid);
1001  NS_ENSURE_SUCCESS(rv, rv);
1002 
1003  rv = aMediaList->GetType(type);
1004  NS_ENSURE_SUCCESS(rv, rv);
1005 
1006  /* first remove the listener from the m_ListenerMap. It was saved for both
1007  * the medialist's guid and type, so it needs to be removed for both */
1008  rv = RemoveListenerInListenerMap(guid, aListener);
1009  NS_ENSURE_SUCCESS(rv, rv);
1010 
1011  rv = RemoveListenerInListenerMap(type, aListener);
1012  NS_ENSURE_SUCCESS(rv, rv);
1013 
1014  // remove the listener from any root commands that it was attached to
1015  rv = RemoveListenerFromRootCommands(guid, type, aListener);
1016  NS_ENSURE_SUCCESS(rv, rv);
1017 
1018  return NS_OK;
1019 }
1020 
1021 //-----------------------------------------------------------------------------
1022 NS_IMETHODIMP
1023 CPlaylistCommandsManager::Publish(const nsAString &aCommandsGUID,
1024  sbIPlaylistCommands *aCommandObj)
1025 {
1026  NS_ENSURE_ARG_POINTER(aCommandObj);
1027  nsString guid(aCommandsGUID);
1028  if (m_publishedCommands[guid]) return NS_ERROR_FAILURE;
1029  m_publishedCommands[guid] = aCommandObj;
1030  return NS_OK;
1031 }
1032 
1033 //-----------------------------------------------------------------------------
1034 NS_IMETHODIMP
1035 CPlaylistCommandsManager::Withdraw(const nsAString &aCommandsGUID,
1036  sbIPlaylistCommands *aCommandObj)
1037 {
1038  NS_ENSURE_ARG_POINTER(aCommandObj);
1039  nsString guid(aCommandsGUID);
1040  if (m_publishedCommands[guid] != aCommandObj) return NS_ERROR_FAILURE;
1041  m_publishedCommands.erase(guid);
1042  return NS_OK;
1043 }
1044 
1045 //-----------------------------------------------------------------------------
1046 NS_IMETHODIMP
1047 CPlaylistCommandsManager::Request(const nsAString &aCommandsGUID,
1048  sbIPlaylistCommands **_retval)
1049 {
1050  nsString guid(aCommandsGUID);
1051  sbIPlaylistCommands *dup = NULL;
1052  sbIPlaylistCommands *cmds;
1053  cmds = m_publishedCommands[guid];
1054  if (cmds) cmds->Duplicate(&dup);
1055  *_retval = dup;
1056  return NS_OK;
1057 }
A helper used to construct sbIPlaylistCommands interfaces.
NS_IMETHODIMP RegisterPlaylistCommands(commandobjmap_t *map, const nsAString &aContextGUID, const nsAString &aPlaylistType, sbIPlaylistCommands *aCommandObj)
return NS_OK
libraryGuidToCommandsMap_t m_LibraryGuidToServicePaneCommandsMap
menuItem id
Definition: FeedWriter.js:971
The interface for receiving notices when a Command Object is added to or removed from another Command...
NS_DECL_ISUPPORTS NS_DECL_SBIPLAYLISTCOMMANDSMANAGER CPlaylistCommandsManager()
inArray array
std::map< nsString, nsCOMPtr< sbIPlaylistCommandsBuilder > > commandobjmap_t
#define METHOD_SHORTCIRCUIT
const unsigned long LISTENER_FLAGS_BEFOREITEMREMOVED
A brief description of the contents of this interface.
Interface used to listen to changes to a media list.
Browser Request
NS_IMPL_ISUPPORTS1(CPlaylistCommandsManager, sbIPlaylistCommandsManager)
commandobjmap_t m_ServicePaneCommandObjMap
libraryGuidToCommandsMap_t m_LibraryGuidToMenuOrToolbarCommandsMap
Songbird PlaylistCommandsManager Component Definition.
NS_IMETHODIMP UnregisterPlaylistCommands(commandobjmap_t *map, const nsAString &aContextGUID, const nsAString &aPlaylistType, sbIPlaylistCommands *aCommandObj)
Media library abstraction.
Definition: sbILibrary.idl:82
An interface that represents the set of command buttons and context menu items available on a display...
StringArrayEnumerator prototype hasMore
const unsigned long LISTENER_FLAGS_ITEMADDED
libraryGuidToLibraryListenerMap_t m_LibraryGuidToLibraryListenerMap
NS_IMPL_THREADSAFE_ISUPPORTS1(LibraryPlaylistCommandsListener, sbIMediaListListener) LibraryPlaylistCommandsListener
Interface that defines a single item of media in the system.
#define SB_PROPERTY_ISLIST
std::map< nsString, nsCOMPtr< sbIPlaylistCommands > > m_publishedCommands
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
std::map< nsString, nsCOMArray< sbIPlaylistCommands > > libraryGuidToCommandsMap_t
_getSelectedPageStyle s i
The service used to register, unregister, and list playlist commands for a particular playlist guid o...