sbMediaListViewMap.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://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 
31 #include "sbMediaListViewMap.h"
32 
33 #include <sbILibraryManager.h>
34 
35 #include <nsIAppStartupNotifier.h>
36 #include <nsICategoryManager.h>
37 #include <nsIGenericFactory.h>
38 #include <nsIObserver.h>
39 #include <nsIObserverService.h>
40 #include <nsISimpleEnumerator.h>
41 #include <nsISupportsPrimitives.h>
42 
43 #include <nsArrayEnumerator.h>
44 #include <nsAutoLock.h>
45 #include <nsCOMArray.h>
46 #include <nsComponentManagerUtils.h>
47 #include <nsEnumeratorUtils.h>
48 #include <nsServiceManagerUtils.h>
49 #include <nsThreadUtils.h>
50 #include <prlog.h>
51 #include <rdf.h>
52 
57 #ifdef PR_LOGGING
58 static PRLogModuleInfo* gMediaListViewMapLog = nsnull;
59 #define TRACE(args) PR_LOG(gMediaListViewMapLog, PR_LOG_DEBUG, args)
60 #define LOG(args) PR_LOG(gMediaListViewMapLog, PR_LOG_WARN, args)
61 #else
62 #define TRACE(args) /* nothing */
63 #define LOG(args) /* nothing */
64 #endif
65 
69 
71 {
72  MOZ_COUNT_CTOR(sbMediaListViewMap);
73 #ifdef PR_LOGGING
74  if (!gMediaListViewMapLog)
75  gMediaListViewMapLog = PR_NewLogModule("sbMediaListViewMap");
76 #endif
77 
78  TRACE(("sbMediaListViewMap[0x%x] - Created", this));
79 
80  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
81 }
82 
83 sbMediaListViewMap::~sbMediaListViewMap()
84 {
85  TRACE(("MediaListViewMap[0x%x] - Destroyed", this));
86  MOZ_COUNT_DTOR(sbMediaListViewMap);
87 }
88 
89 /* static */ NS_METHOD
90 sbMediaListViewMap::RegisterSelf(nsIComponentManager* aCompMgr,
91  nsIFile* aPath,
92  const char* aLoaderStr,
93  const char* aType,
94  const nsModuleComponentInfo *aInfo)
95 {
96  nsresult rv;
97  nsCOMPtr<nsICategoryManager> categoryManager =
98  do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
99  NS_ENSURE_SUCCESS(rv, rv);
100 
101  rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY,
104  PR_TRUE, PR_TRUE, nsnull);
105  NS_ENSURE_SUCCESS(rv, rv);
106 
107  return rv;
108 }
109 
113 nsresult
115 {
116  TRACE(("sbMediaListViewMap[0x%x] - Init", this));
117  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
118 
119  nsresult rv;
120  nsCOMPtr<nsIObserverService> observerService =
121  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
122  NS_ENSURE_SUCCESS(rv, rv);
123 
124  rv = observerService->AddObserver(this, SB_LIBRARY_MANAGER_READY_TOPIC,
125  PR_TRUE);
126  NS_ENSURE_SUCCESS(rv, rv);
127 
128  rv = observerService->AddObserver(this, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC,
129  PR_TRUE);
130  NS_ENSURE_SUCCESS(rv, rv);
131 
132  return NS_OK;
133 }
134 
135 /* sbIMediaListView getView (in nsISupports aParentKey, in nsISupports aPageKey); */
136 NS_IMETHODIMP
137 sbMediaListViewMap::GetView(nsISupports *aParentKey,
138  nsISupports *aPageKey,
139  sbIMediaListView **_retval)
140 {
141  TRACE(("sbMediaListViewMap[0x%x] - GetView", this));
142 
143  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
144  NS_ENSURE_ARG_POINTER( aParentKey );
145  NS_ENSURE_ARG_POINTER( aPageKey );
146  NS_ENSURE_ARG_POINTER( _retval );
147  sbViewMapInner *innerMap = nsnull;
148  sbViewStateInfo *innerValue = nsnull;
149  *_retval = nsnull;
150  if ( mViewMap.Get( aParentKey, &innerMap ) && innerMap && innerMap->Get( aPageKey, &innerValue ) )
151  {
152 #ifdef DEBUG
153  {
154  nsString buff;
155  innerValue->state->ToString(buff);
156  TRACE(("sbMediaListViewMap[0x%x] - Restoring view %s %s %s", this,
157  NS_LossyConvertUTF16toASCII(innerValue->libraryGuid).get(),
158  NS_LossyConvertUTF16toASCII(innerValue->libraryGuid).get(),
159  NS_LossyConvertUTF16toASCII(buff).get()));
160  }
161 #endif
162 
163  nsresult rv;
164  nsCOMPtr<sbILibraryManager> lm =
165  do_GetService( "@songbirdnest.com/Songbird/library/Manager;1", &rv );
166  NS_ENSURE_SUCCESS( rv, rv );
167 
168  nsCOMPtr<sbILibrary> library;
169  rv = lm->GetLibrary( innerValue->libraryGuid, getter_AddRefs(library) );
170  if ( rv == NS_ERROR_NOT_AVAILABLE ) {
171  return NS_OK;
172  }
173  NS_ENSURE_SUCCESS( rv, rv );
174 
175  nsCOMPtr<sbIMediaItem> item;
176  rv = library->GetItemByGuid( innerValue->listGuid, getter_AddRefs(item) );
177  if ( rv == NS_ERROR_NOT_AVAILABLE ) {
178  return NS_OK;
179  }
180  NS_ENSURE_SUCCESS( rv, rv );
181 
182  nsCOMPtr<sbIMediaList> list = do_QueryInterface(item, &rv);
183  NS_ENSURE_SUCCESS( rv, rv );
184 
185  rv = list->CreateView(innerValue->state, _retval);
186  NS_ENSURE_SUCCESS( rv, rv );
187  }
188 
189  // It's okay to return null on failure.
190  return NS_OK;
191 }
192 
193 /* void setView (in nsISupports aParentKey, in nsISupports aPageKey, in sbIMediaListView aView); */
194 NS_IMETHODIMP
195 sbMediaListViewMap::SetView(nsISupports *aParentKey,
196  nsISupports *aPageKey,
197  sbIMediaListView *aView)
198 {
199  TRACE(("sbMediaListViewMap[0x%x] - SetView", this));
200 
201  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
202  NS_ENSURE_ARG_POINTER( aParentKey );
203  NS_ENSURE_ARG_POINTER( aPageKey );
204  NS_ENSURE_ARG_POINTER( aView );
205 
206  nsresult rv;
207  PRBool success;
208  sbViewMapInner *innerMap = nsnull;
209 
210  // If our inner map does not yet exist, create and stash it
211  if ( ! mViewMap.Get( aParentKey, &innerMap ) )
212  {
213  innerMap = new sbViewMapInner;
214  NS_ENSURE_TRUE(innerMap, NS_ERROR_OUT_OF_MEMORY);
215  success = innerMap->Init();
216  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
217  success = mViewMap.Put( aParentKey, innerMap ); // Takes over memory management for innerMap
218  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
219  }
220 
221  nsCOMPtr<sbIMediaList> list;
222  nsString listGuid;
223  rv = aView->GetMediaList(getter_AddRefs(list));
224  NS_ENSURE_SUCCESS(rv, rv);
225  rv = list->GetGuid(listGuid);
226  NS_ENSURE_SUCCESS(rv, rv);
227 
228  nsCOMPtr<sbILibrary> library;
229  nsString libraryGuid;
230  rv = list->GetLibrary(getter_AddRefs(library));
231  NS_ENSURE_SUCCESS(rv, rv);
232  rv = library->GetGuid(libraryGuid);
233  NS_ENSURE_SUCCESS(rv, rv);
234 
235  nsCOMPtr<sbIMediaListViewState> state;
236  rv = aView->GetState(getter_AddRefs(state));
237  NS_ENSURE_SUCCESS(rv, rv);
238 
239 #ifdef DEBUG
240  {
241  nsString buff;
242  state->ToString(buff);
243  TRACE(("sbMediaListViewMap[0x%x] - Saving view %s %s %s", this,
244  NS_LossyConvertUTF16toASCII(libraryGuid).get(),
245  NS_LossyConvertUTF16toASCII(libraryGuid).get(),
246  NS_LossyConvertUTF16toASCII(buff).get()));
247  }
248 #endif
249 
250  nsAutoPtr<sbViewStateInfo> si(
251  new sbViewStateInfo(libraryGuid, listGuid, state));
252  NS_ENSURE_TRUE(si, NS_ERROR_OUT_OF_MEMORY);
253 
254  // Put the view into the inner map
255  success = innerMap->Put( aPageKey, si );
256  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
257 
258  si.forget();
259 
260  return NS_OK;
261 }
262 
263 /* void releaseViews (in nsISupports aParentKey); */
264 NS_IMETHODIMP sbMediaListViewMap::ReleaseViews(nsISupports *aParentKey)
265 {
266  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
267  if ( ! aParentKey ) // If NULL, release all.
268  {
269  // Supposedly, this will release everything. If it doesn't, blame Ben!
270  mViewMap.Clear();
271  }
272  else
273  {
274  sbViewMapInner *innerMap = nsnull;
275  if ( mViewMap.Get( aParentKey, &innerMap ) )
276  {
277  // Then release the entire branch of the primary map.
278  mViewMap.Remove( aParentKey ); // This line deletes the innerMap, automatically clearing it. Supposedly.
279  }
280  }
281  return NS_OK; // If it's not actually there, we don't care.
282 }
283 
287 NS_IMETHODIMP
288 sbMediaListViewMap::Observe(nsISupports* aSubject,
289  const char* aTopic,
290  const PRUnichar* aData)
291 {
292  TRACE(("sbMediaListViewMap[0x%x] - Observe: %s", this, aTopic));
293 
294  nsresult rv;
295  nsCOMPtr<nsIObserverService> observerService =
296  do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
297 
298  if (strcmp(aTopic, APPSTARTUP_TOPIC) == 0) {
299  return NS_OK; // ???
300  }
301  else if (strcmp(aTopic, SB_LIBRARY_MANAGER_READY_TOPIC) == 0) {
302 
303  // Remove ourselves from the observer service.
304  if (NS_SUCCEEDED(rv)) {
305  observerService->RemoveObserver(this, SB_LIBRARY_MANAGER_READY_TOPIC);
306  }
307 
308  // Startup
309  mViewMap.Init();
310 
311  return NS_OK;
312  }
313  else if (strcmp(aTopic, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC) == 0) {
314 
315  // Remove ourselves from the observer service.
316  if (NS_SUCCEEDED(rv)) {
317  observerService->RemoveObserver(this, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC);
318  }
319 
320  // Shutdown
321  ReleaseViews( nsnull );
322 
323  return NS_OK;
324  }
325 
326  NS_NOTREACHED("Observing a topic that wasn't handled!");
327  return NS_OK;
328 }
NS_IMPL_THREADSAFE_ISUPPORTS3(sbMediaListViewMap, nsIObserver, nsISupportsWeakReference, sbIMediaListViewMap) sbMediaListViewMap
return NS_OK
_updateCookies aPath
const SB_LIBRARY_MANAGER_READY_TOPIC
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
#define SONGBIRD_MEDIALISTVIEWMAP_DESCRIPTION
A distinct view on a given media list.
#define TRACE(args)
A mapping from nsISupports objects to save sbIMediaListView states.
#define SONGBIRD_MEDIALISTVIEWMAP_CONTRACTID
nsresult Init()
Register with the Observer Service.
static NS_METHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
Songbird Library Manager Definition.
const SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC
_updateTextAndScrollDataForFrame aData