sbLocalDatabaseSimpleMediaList.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-2010 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 
27 
28 #include <nsIArray.h>
29 #include <nsIClassInfoImpl.h>
30 #include <nsIMutableArray.h>
31 #include <nsIProgrammingLanguage.h>
32 #include <nsISimpleEnumerator.h>
33 #include <nsIURI.h>
34 #include <sbIDatabaseQuery.h>
35 #include <sbIDatabaseResult.h>
36 #include <sbILibrary.h>
37 #include <sbILocalDatabaseGUIDArray.h>
38 #include <sbILocalDatabasePropertyCache.h>
39 #include <sbIMediaListView.h>
40 #include <sbISQLBuilder.h>
41 
42 #include "sbLocalDatabaseCID.h"
43 #include "sbLocalDatabaseLibrary.h"
46 
47 #include <DatabaseQuery.h>
48 #include <nsArrayUtils.h>
49 #include <nsAutoLock.h>
50 #include <nsAutoPtr.h>
51 #include <nsCOMPtr.h>
52 #include <nsComponentManagerUtils.h>
53 #include <nsMemory.h>
54 #include <nsXPCOMCID.h>
55 #include <pratom.h>
57 #include <sbStandardProperties.h>
58 #include <sbStringUtils.h>
59 #include <sbSQLBuilderCID.h>
60 
61 #define DEFAULT_SORT_PROPERTY NS_LITERAL_STRING(SB_PROPERTY_ORDINAL)
62 #define DEFAULT_FETCH_SIZE 1000
63 
68 #ifdef PR_LOGGING
69 static PRLogModuleInfo* gLocalDatabaseSimpleMediaListLog = nsnull;
70 #endif /* PR_LOGGING */
71 
72 #define TRACE(args) PR_LOG(gLocalDatabaseSimpleMediaListLog, PR_LOG_DEBUG, args)
73 #define LOG(args) PR_LOG(gLocalDatabaseSimpleMediaListLog, PR_LOG_WARN, args)
74 
75 #ifdef DEBUG
76 #define ASSERT_LIST_IS_LIBRARY(_mediaList) \
77  PR_BEGIN_MACRO \
78  nsresult rv; \
79  nsCOMPtr<sbILibrary> library = do_QueryInterface(mLibrary, &rv); \
80  NS_ASSERTION(NS_SUCCEEDED(rv), "Library won't QI to sbILibrary!"); \
81  \
82  if (NS_SUCCEEDED(rv)) { \
83  PRBool listIsLibrary; \
84  rv = library->Equals(_mediaList, &listIsLibrary); \
85  NS_ASSERTION(NS_SUCCEEDED(rv), "Equals failed!"); \
86  \
87  if (NS_SUCCEEDED(rv)) { \
88  NS_ASSERTION(listIsLibrary, "Watching the wrong list!"); \
89  } \
90  } \
91  PR_END_MACRO
92 #else /* DEBUG */
93 #define ASSERT_LIST_IS_LIBRARY(_mediaList) \
94  PR_BEGIN_MACRO /* nothing */ PR_END_MACRO
95 #endif /* DEBUG */
96 
97 #define SB_ENSURE_INDEX_BEGIN \
98  PR_BEGIN_MACRO \
99  nsresult rv; \
100  PRUint32 length; \
101  rv = GetArray()->GetLength(&length); \
102  NS_ENSURE_SUCCESS(rv, rv);
103 
104 #define SB_ENSURE_INDEX_END \
105  PR_END_MACRO
106 
107 #define SB_ENSURE_INDEX1(_index) \
108  SB_ENSURE_INDEX_BEGIN \
109  NS_ENSURE_ARG_MAX(_index, length - 1); \
110  SB_ENSURE_INDEX_END
111 
112 #define SB_ENSURE_INDEX2(_index1, _index2) \
113  SB_ENSURE_INDEX_BEGIN \
114  NS_ENSURE_ARG_MAX(_index1, length - 1); \
115  NS_ENSURE_ARG_MAX(_index2, length - 1); \
116  SB_ENSURE_INDEX_END
117 
119 {
120 public:
122  NS_DECL_SBIADDMEDIAITEMSLISTENER
123 
125  nsIArray * aItemsToAdd,
126  nsInterfaceHashtable<nsISupportsHashKey, sbIMediaItem> & aForeignItems):
127  mItemsToAdd(aItemsToAdd),
128  mForeignItems(aForeignItems),
129  mIndex(0)
130  {
131  }
132 private:
133  nsIArray * mItemsToAdd;
134  nsInterfaceHashtable<nsISupportsHashKey, sbIMediaItem> & mForeignItems;
135  PRUint32 mIndex;
136 };
137 
140 
141 NS_IMETHODIMP
142 sbAddSomeEnumListener::OnItemAdded(sbIMediaItem * aMediaItem)
143 {
144  nsresult rv;
145  NS_ENSURE_ARG_POINTER(aMediaItem);
146 
147  nsCOMPtr<sbIMediaItem> existingItem = do_QueryElementAt(mItemsToAdd,
148  mIndex++,
149  &rv);
150  NS_ENSURE_SUCCESS(rv, rv);
151 
152  NS_ASSERTION(mForeignItems.Get(existingItem, nsnull),
153  "The old item should be in the hashtable!");
154 
155  PRBool success = mForeignItems.Put(existingItem, aMediaItem);
156  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
157 
158  return NS_OK;
159 }
160 
161 NS_IMETHODIMP
162 sbAddSomeEnumListener::OnComplete()
163 {
164  return NS_OK;
165 }
166 
167 NS_IMETHODIMP
168 sbAddSomeEnumListener::OnProgress(PRUint32 aItemsCompleted, PRBool aCompleted)
169 {
170  return NS_OK;
171 }
172 
178 {
179 public:
181 
183  sbLocalDatabaseSimpleMediaList* aLocalDatabaseSimpleMediaList,
184  nsISimpleEnumerator* aMediaItems,
185  nsISupports * aListener,
186  PRUint32 aStartingIndex,
187  const nsAString& aStartingOrdinal)
188  : mLocalDatabaseSimpleMediaList(aLocalDatabaseSimpleMediaList)
189  , mListener(aListener)
190  , mMediaItems(aMediaItems)
191  , mStartingIndex(aStartingIndex)
192  , mStartingOrdinal(aStartingOrdinal) {}
193  NS_IMETHOD Run() {
194  nsresult rv =
195  mLocalDatabaseSimpleMediaList->AddSomeAsyncInternal(mMediaItems,
196  mListener,
197  mStartingIndex,
198  mStartingOrdinal);
199  NS_ENSURE_SUCCESS(rv, rv);
200  return NS_OK;
201  }
202 
203 private:
204  nsRefPtr<sbLocalDatabaseSimpleMediaList> mLocalDatabaseSimpleMediaList;
205  nsCOMPtr<nsISupports> mListener;
206  nsCOMPtr<nsISimpleEnumerator> mMediaItems;
207  PRUint32 mStartingIndex;
208  nsString mStartingOrdinal;
209 };
210 
212  nsIRunnable);
213 
214 // This class is stack-only but needs to act like an XPCOM object. Add dummy
215 // AddRef/Release methods so the ref count is always 1
216 NS_IMETHODIMP_(nsrefcnt)
218 {
219  return (nsrefcnt)1;
220 }
221 
222 NS_IMETHODIMP_(nsrefcnt)
224 {
225  return (nsrefcnt)1;
226 }
227 
230 
231 
234 NS_IMETHODIMP
235 sbSimpleMediaListInsertingEnumerationListener::OnEnumerationBegin(sbIMediaList* aMediaList,
236  PRUint16* _retval)
237 {
238  NS_ENSURE_ARG_POINTER(_retval);
239 
240  NS_ASSERTION(aMediaList != mFriendList,
241  "Can't enumerate our friend media list!");
242 
243  PRBool success = mItemsToCreateOrAdd.Init();
244  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
245 
246  nsresult rv = mFriendList->GetLibrary(getter_AddRefs(mListLibrary));
247  NS_ENSURE_SUCCESS(rv, rv);
248 
249  // All good for enumerating.
251 
252  return NS_OK;
253 }
254 
258 NS_IMETHODIMP
259 sbSimpleMediaListInsertingEnumerationListener::OnEnumeratedItem(sbIMediaList* aMediaList,
260  sbIMediaItem* aMediaItem,
261  PRUint16* _retval)
262 {
263  NS_ENSURE_ARG_POINTER(aMediaItem);
264  NS_ENSURE_ARG_POINTER(_retval);
265 
266  NS_ASSERTION(aMediaList != mFriendList,
267  "Can't enumerate our friend media list!");
268 
269  nsCOMPtr<sbILibrary> itemLibrary;
270  nsresult rv = aMediaItem->GetLibrary(getter_AddRefs(itemLibrary));
271  NS_ENSURE_SUCCESS(rv, rv);
272 
273  PRBool sameLibrary;
274  rv = itemLibrary->Equals(mListLibrary, &sameLibrary);
275  NS_ENSURE_SUCCESS(rv, rv);
276 
277  const PRBool itemIsInMainLibrary = sbIsMainLibrary(itemLibrary);
278 
279  nsString listLibGuid;
280  rv = mListLibrary->GetGuid(listLibGuid);
281  NS_ENSURE_SUCCESS(rv, rv);
282 
283  nsCOMPtr<sbIMediaItem> foundItem;
284 
285  PRBool success;
286  NS_NAMED_LITERAL_STRING(PROP_LIBRARY, SB_PROPERTY_ORIGINLIBRARYGUID);
287  NS_NAMED_LITERAL_STRING(PROP_ITEM, SB_PROPERTY_ORIGINITEMGUID);
288  if (!sameLibrary && !mItemsToCreateOrAdd.Get(aMediaItem, nsnull)) {
289  // This item comes from another library so we'll need to add it to our
290  // library before it can be used.
291 
292  // but first check if we have an existing item that is close enough
293  // Use the origin guids if present, but not if the item is in the main
294  // library, as they may point back to an item that no longer exists.
295  nsString originLibGuid, originItemGuid;
296  rv = aMediaItem->GetProperty(PROP_LIBRARY, originLibGuid);
297  NS_ENSURE_SUCCESS(rv, rv);
298  if (originLibGuid.IsEmpty() || itemIsInMainLibrary) {
299  rv = itemLibrary->GetGuid(originLibGuid);
300  NS_ENSURE_SUCCESS(rv, rv);
301  }
302  rv = aMediaItem->GetProperty(PROP_ITEM, originItemGuid);
303  NS_ENSURE_SUCCESS(rv, rv);
304  if (originItemGuid.IsEmpty() || itemIsInMainLibrary) {
305  rv = aMediaItem->GetGuid(originItemGuid);
306  NS_ENSURE_SUCCESS(rv, rv);
307  }
308 
309  // if the origin library is this library, just look for the item
310  if (listLibGuid.Equals(originLibGuid)) {
311  // the origin item was from this library
312  rv = mListLibrary->GetMediaItem(originItemGuid, getter_AddRefs(foundItem));
313  if (NS_FAILED(rv)) {
314  // didn't find it
315  foundItem = nsnull;
316  }
317  } else {
318  nsCOMPtr<sbIMutablePropertyArray> originGuidArray =
319  do_CreateInstance(SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv);
320  NS_ENSURE_SUCCESS(rv, rv);
321 
322  rv = originGuidArray->AppendProperty(PROP_LIBRARY, originLibGuid);
323  NS_ENSURE_SUCCESS(rv, rv);
324 
325  rv = originGuidArray->AppendProperty(PROP_ITEM, originItemGuid);
326  NS_ENSURE_SUCCESS(rv, rv);
327 
328  nsRefPtr<sbMediaListEnumSingleItemHelper> guidCheckHelper =
330  NS_ENSURE_TRUE(guidCheckHelper, NS_ERROR_OUT_OF_MEMORY);
331 
332  rv = mListLibrary->EnumerateItemsByProperties(originGuidArray,
333  guidCheckHelper,
335  NS_ENSURE_SUCCESS(rv, rv);
336 
337  foundItem = guidCheckHelper->GetItem(); /* null if not found */
338  }
339  // At this point we've either found a corresponding media item or not in
340  // which case we'll map to null
341  success = mItemsToCreateOrAdd.Put(aMediaItem, foundItem);
342  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
343  }
344 
345  // Capture all the media items we see in the order found so we can
346  // properly add them in the correct order. We need to use the found item if
347  // there is one since that's the one we'll want to add.
348  success = mItemList.AppendObject(foundItem ? foundItem.get() : aMediaItem);
349  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
350 
352 
353  return NS_OK;
354 }
355 
356 nsresult
357 sbSimpleMediaListInsertingEnumerationListener::UpdateItemsInForeignLib(
358  nsIArray * aExistingItems,
359  nsIArray * aNewItems)
360 {
361  NS_ENSURE_ARG_POINTER(aExistingItems);
362  NS_ENSURE_ARG_POINTER(aNewItems);
363 
364  nsresult rv;
365 
366  PRUint32 existingItemsCount;
367  rv = aExistingItems->GetLength(&existingItemsCount);
368  NS_ENSURE_SUCCESS(rv, rv);
369 
370  PRUint32 newItemsCount;
371  rv = aNewItems->GetLength(&newItemsCount);
372  NS_ENSURE_SUCCESS(rv, rv);
373 
374  NS_ASSERTION(existingItemsCount == newItemsCount,
375  "The number of existing items much match the number of new items");
376  // For each new item that was created, update the mItemsInForeignLib
377  for (PRUint32 index = 0; index < existingItemsCount; index++) {
378  nsCOMPtr<sbIMediaItem> existingItem = do_QueryElementAt(aExistingItems,
379  index,
380  &rv);
381  NS_ENSURE_SUCCESS(rv, rv);
382 
383  nsCOMPtr<sbIMediaItem> newItem = do_QueryElementAt(aNewItems, index, &rv);
384  NS_ENSURE_SUCCESS(rv, rv);
385 
386  NS_ASSERTION(mItemsToCreateOrAdd.Get(existingItem, nsnull),
387  "The old item should be in the hashtable!");
388 
389  PRBool success = mItemsToCreateOrAdd.Put(existingItem, newItem);
390  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
391  }
392 
393  return NS_OK;
394 }
395 
399 NS_IMETHODIMP
400 sbSimpleMediaListInsertingEnumerationListener::OnEnumerationEnd(sbIMediaList* aMediaList,
401  nsresult aStatusCode)
402 {
403  TRACE(("LocalDatabaseSimpleMediaList[0x%.8x] - "
404  "InsertingEnumerator::OnEnumerationEnd", this));
405 
406  NS_ASSERTION(aMediaList != mFriendList,
407  "Can't enumerate our friend media list!");
408 
409  const PRUint32 itemCount = mItemList.Count();
410  if (!itemCount) {
411  NS_WARNING("OnEnumerationEnd called with no items enumerated");
412  return NS_OK;
413  }
414 
415  nsresult rv;
416 
417  // This will be the collection of items that will need to be created
418  nsCOMPtr<nsIMutableArray> itemsToAdd =
419  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
420  NS_ENSURE_SUCCESS(rv, rv);
421 
422  // This will be the collection of items that will need to be created
423  nsCOMPtr<nsIMutableArray> itemsToCreate =
424  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
425  NS_ENSURE_SUCCESS(rv, rv);
426 
427  // This will be the collection of URI's for the itemsToCreate above
428  nsCOMPtr<nsIMutableArray> itemsToCreateURIs =
429  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
430  NS_ENSURE_SUCCESS(rv, rv);
431 
432  // This traverses mItemList looking for items that need to be created
433  // meaning there is a corresponding entry in mItemsInForeignLib but the
434  // value is null.
435  PRUint32 numItems = mItemList.Count();
436  for (PRUint32 i = 0; i < numItems; i++) {
437  sbIMediaItem * const item = mItemList[i];
438 
439  nsCOMPtr<sbIMediaItem> existing;
440  // See if this item needs to be created or added. There are three cases:
441  // 1. The item is not in mItemsToCreateOrAdd which means it's already in the
442  // target library
443  // 2. The item is in mItemsToCreateOrAdd but the value is null. This means
444  // the item needs to be created.
445  // 3. The item is in mItemsToCreateOrAdd and has a value. This means the
446  // item exists in the main library and needs to be added to the target
447  const PRBool found = mItemsToCreateOrAdd.Get(item,
448  getter_AddRefs(existing));
449  if (found) {
450  if (existing) {
451  rv = itemsToAdd->AppendElement(existing, PR_FALSE);
452  NS_ENSURE_SUCCESS(rv, rv);
453  }
454  else {
455  nsCOMPtr<nsIURI> uri;
456  rv = item->GetContentSrc(getter_AddRefs(uri));
457  NS_ENSURE_SUCCESS(rv, rv);
458 
459  rv = itemsToCreate->AppendElement(item, PR_FALSE);
460  NS_ENSURE_SUCCESS(rv, rv);
461 
462  rv = itemsToCreateURIs->AppendElement(uri, PR_FALSE);
463  NS_ENSURE_SUCCESS(rv, rv);
464  }
465  }
466  }
467 
468  PRUint32 itemsToCreateCount;
469  rv = itemsToCreate->GetLength(&itemsToCreateCount);
470  NS_ENSURE_SUCCESS(rv, rv);
471 
472  // Skip the following if there are no items to add
473  if (itemsToCreateCount) {
474 
475  nsCOMPtr<nsIMutableArray> propertyArrayArray =
476  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
477  NS_ENSURE_SUCCESS(rv, rv);
478 
479  for (PRUint32 i = 0; i < itemsToCreateCount; i++) {
480  nsCOMPtr<sbIMediaItem> item = do_QueryElementAt(itemsToCreate, i, &rv);
481  NS_ENSURE_SUCCESS(rv, rv);
482 
483  nsCOMPtr<sbIPropertyArray> properties;
484  rv = item->GetProperties(nsnull, getter_AddRefs(properties));
485  NS_ENSURE_SUCCESS(rv, rv);
486 
487  nsCOMPtr<sbIPropertyArray> filteredProperties;
488  rv = mFriendList->GetFilteredPropertiesForNewItem(properties,
489  getter_AddRefs(filteredProperties));
490  NS_ENSURE_SUCCESS(rv, rv);
491 
492  nsCOMPtr<sbIMutablePropertyArray> mutableProperties =
493  do_QueryInterface(filteredProperties, &rv);
494  NS_ENSURE_SUCCESS(rv, rv);
495 
496  // keep track of the library/item guid that we just copied from
497  rv = mFriendList->GetOriginProperties(item, mutableProperties);
498  NS_ENSURE_SUCCESS(rv, rv);
499 
500  rv = propertyArrayArray->AppendElement(filteredProperties, PR_FALSE);
501  NS_ENSURE_SUCCESS(rv, rv);
502  }
503 
504  // Creating the items, we shouldn't have to look for dupes since
505  // that's been done previously.
506  nsCOMPtr<nsIArray> newItems;
507  rv = mListLibrary->BatchCreateMediaItems(itemsToCreateURIs,
508  propertyArrayArray,
509  PR_TRUE,
510  getter_AddRefs(newItems));
511  NS_ENSURE_SUCCESS(rv, rv);
512 
513  PRUint32 newItemCount;
514  rv = newItems->GetLength(&newItemCount);
515  NS_ENSURE_SUCCESS(rv, rv);
516 
517 #ifdef DEBUG
518  PRUint32 itemsToCreateCount;
519  rv = itemsToCreateURIs->GetLength(&itemsToCreateCount);
520  NS_ASSERTION(NS_SUCCEEDED(rv) && newItemCount == itemsToCreateCount,
521  "BatchCreateMediaItems didn't make the right number of items!");
522 #endif
523 
524  rv = UpdateItemsInForeignLib(itemsToCreate, newItems);
525  NS_ENSURE_SUCCESS(rv, rv);
526 
527  }
528 
529  PRUint32 itemsToAddCount;
530  rv = itemsToAdd->GetLength(&itemsToAddCount);
531  NS_ENSURE_SUCCESS(rv, rv);
532 
533  if (itemsToAddCount) {
534  nsRefPtr<sbAddSomeEnumListener> addListener =
535  new sbAddSomeEnumListener(itemsToAdd,
536  mItemsToCreateOrAdd);
537 
538  nsCOMPtr<nsISimpleEnumerator> itemsToAddEnumerator;
539  rv = itemsToAdd->Enumerate(getter_AddRefs(itemsToAddEnumerator));
540  NS_ENSURE_SUCCESS(rv, rv);
541  rv = mListLibrary->AddMediaItems(itemsToAddEnumerator,
542  addListener,
543  PR_FALSE);
544  NS_ENSURE_SUCCESS(rv, rv);
545  }
546  nsCOMPtr<sbIDatabaseQuery> query;
547  rv = mFriendList->MakeStandardQuery(getter_AddRefs(query));
548  NS_ENSURE_SUCCESS(rv, rv);
549 
550  rv = query->AddQuery(NS_LITERAL_STRING("begin"));
551  NS_ENSURE_SUCCESS(rv, rv);
552 
553  nsString ordinal = mStartingOrdinal;
554 
555  // For each item, new or existing, go through and add the item to the media
556  // list
557  for (PRUint32 index = 0; index < itemCount; index++) {
558 
559  nsCOMPtr<sbIMediaItem> mediaItem = mItemList[index];
560 
561  // Use the "value" in mItemsInForeignLib since that is either the item found
562  // in the media list's library or the one previously created in that
563  // library. If there is no entry in mItemsInForeignLib then we can just use
564  // the straight media item that was given
565  nsCOMPtr<sbIMediaItem> newMediaItem;
566  PRBool success = mItemsToCreateOrAdd.Get(mediaItem,
567  getter_AddRefs(newMediaItem));
568  if (success) {
569  //Call the copy listener for this media list at this time.
570  //XXXAus: This could benefit from batching in the future.
571  rv = mFriendList->NotifyCopyListener(mediaItem, newMediaItem);
572  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to notify copy listener!");
573 
574  // We'll replace the passed in media item with either the one found or
575  // the one that was created. This is so the notification logic later
576  // can just use the mItemList for notification.
577  success = mItemList.ReplaceObjectAt(newMediaItem, index);
578  NS_ENSURE_SUCCESS(rv, rv);
579 
580  mediaItem = newMediaItem;
581  }
582 
583  nsCOMPtr<sbILocalDatabaseMediaItem> ldbmi =
584  do_QueryInterface(mediaItem, &rv);
585  NS_ENSURE_SUCCESS(rv, rv);
586 
587  PRUint32 mediaItemId;
588  rv = ldbmi->GetMediaItemId(&mediaItemId);
589  NS_ENSURE_SUCCESS(rv, rv);
590 
591  rv = query->AddQuery(mFriendList->mInsertIntoListQuery);
592  NS_ENSURE_SUCCESS(rv, rv);
593 
594  rv = query->BindInt32Parameter(0, mediaItemId);
595  NS_ENSURE_SUCCESS(rv, rv);
596 
597  rv = query->BindStringParameter(1, ordinal);
598  NS_ENSURE_SUCCESS(rv, rv);
599 
600  // Increment the ordinal
601  rv = mFriendList->AddToLastPathSegment(ordinal, 1);
602  NS_ENSURE_SUCCESS(rv, rv);
603  }
604 
605  rv = query->AddQuery(NS_LITERAL_STRING("commit"));
606  NS_ENSURE_SUCCESS(rv, rv);
607 
608  PRInt32 dbSuccess;
609  rv = query->Execute(&dbSuccess);
610  NS_ENSURE_SUCCESS(rv, rv);
611  NS_ENSURE_TRUE(dbSuccess == 0, NS_ERROR_FAILURE);
612 
613  // Invalidate the cached list. Inserting definitely changes length.
614  rv = mFriendList->GetArray()->Invalidate(PR_TRUE);
615  NS_ENSURE_SUCCESS(rv, rv);
616 
617  rv = mFriendList->UpdateLastModifiedTime();
618  NS_ENSURE_SUCCESS(rv, rv);
619 
620  // Notify our listeners if we have any
621  if (mFriendList->ListenerCount() > 0) {
622  for (PRUint32 index = 0; index < itemCount; index++) {
623  sbIMediaItem * const item = mItemList[index];
624  if (mAddListener) {
625  rv = mAddListener->OnItemAdded(item);
626  NS_ENSURE_SUCCESS(rv, rv);
627  }
628  mFriendList->NotifyListenersItemAdded(mFriendList,
629  item,
630  mStartingIndex + index);
631  }
632  }
633 
634  if (mAddListener) {
635  rv = mAddListener->OnComplete();
636  NS_ENSURE_SUCCESS(rv, rv);
637  }
638 
639  // Reset list content type to trigger recalculation.
641 
642  return NS_OK;
643 }
644 
645 // This class is stack-only but needs to act like an XPCOM object. Add dummy
646 // AddRef/Release methods so the ref count is always 1
647 NS_IMETHODIMP_(nsrefcnt)
649 {
650  return (nsrefcnt)1;
651 }
652 
653 NS_IMETHODIMP_(nsrefcnt)
655 {
656  return (nsrefcnt)1;
657 }
658 
661 
662 
665 NS_IMETHODIMP
666 sbSimpleMediaListRemovingEnumerationListener::OnEnumerationBegin(sbIMediaList* aMediaList,
667  PRUint16* _retval)
668 {
669  NS_ENSURE_ARG_POINTER(_retval);
670 
671  // Prep the query
672  nsresult rv = mFriendList->MakeStandardQuery(getter_AddRefs(mDBQuery));
673  NS_ENSURE_SUCCESS(rv, rv);
674 
675  rv = mDBQuery->AddQuery(NS_LITERAL_STRING("begin"));
676  NS_ENSURE_SUCCESS(rv, rv);
677 
679 
680  return NS_OK;
681 }
682 
686 NS_IMETHODIMP
687 sbSimpleMediaListRemovingEnumerationListener::OnEnumeratedItem(sbIMediaList* aMediaList,
688  sbIMediaItem* aMediaItem,
689  PRUint16* _retval)
690 {
691  NS_ENSURE_ARG_POINTER(aMediaItem);
692  NS_ENSURE_ARG_POINTER(_retval);
693 
694  PRUint32 index;
695  nsresult rv = mFriendList->IndexOf(aMediaItem, 0, &index);
696  // If the item is not in the list, ignore it
697  if (rv == NS_ERROR_NOT_AVAILABLE) {
698  return NS_OK;
699  }
700  NS_ENSURE_SUCCESS(rv, rv);
701 
702  // Remember this media item for later so we can notify with it
703  PRBool success = mNotificationList.AppendObject(aMediaItem);
704  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
705 
706  PRUint32* added = mNotificationIndexes.AppendElement(index);
707  NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
708 
709  nsCOMPtr<sbILocalDatabaseMediaItem> ldbmi =
710  do_QueryInterface(aMediaItem, &rv);
711  NS_ENSURE_SUCCESS(rv, rv);
712 
713  rv = mDBQuery->AddQuery(mFriendList->mDeleteFirstListItemQuery);
714  NS_ENSURE_SUCCESS(rv, rv);
715 
716  PRUint32 mediaItemId;
717  rv = ldbmi->GetMediaItemId(&mediaItemId);
718  NS_ENSURE_SUCCESS(rv, rv);
719 
720  rv = mDBQuery->BindInt32Parameter(0, mediaItemId);
721  NS_ENSURE_SUCCESS(rv, rv);
722 
724 
725  mItemEnumerated = PR_TRUE;
726  return NS_OK;
727 }
728 
732 NS_IMETHODIMP
733 sbSimpleMediaListRemovingEnumerationListener::OnEnumerationEnd(sbIMediaList* aMediaList,
734  nsresult aStatusCode)
735 {
736  nsresult rv;
737 
738  // Notify our listeners before removal if we have any
739  PRUint32 count = mNotificationList.Count();
740  if (mFriendList->ListenerCount() > 0) {
741  for (PRUint32 i = 0; i < count; i++) {
742  mFriendList->NotifyListenersBeforeItemRemoved(mFriendList,
743  mNotificationList[i],
744  mNotificationIndexes[i]);
745  }
746  }
747 
748  if (mItemEnumerated) {
749  rv = mDBQuery->AddQuery(NS_LITERAL_STRING("commit"));
750  NS_ENSURE_SUCCESS(rv, rv);
751 
752  PRInt32 dbSuccess;
753  rv = mDBQuery->Execute(&dbSuccess);
754  NS_ENSURE_SUCCESS(rv, rv);
755  NS_ENSURE_TRUE(dbSuccess == 0, NS_ERROR_FAILURE);
756  }
757 
758  // Invalidate the cached list. Removing definitely changes length.
759  rv = mFriendList->GetArray()->Invalidate(PR_TRUE);
760  NS_ENSURE_SUCCESS(rv, rv);
761 
762  rv = mFriendList->UpdateLastModifiedTime();
763  NS_ENSURE_SUCCESS(rv, rv);
764 
765  // Notify our listeners after removal if we have any
766  if (mFriendList->ListenerCount() > 0) {
767  for (PRUint32 i = 0; i < count; i++) {
768  mFriendList->NotifyListenersAfterItemRemoved(mFriendList,
769  mNotificationList[i],
770  mNotificationIndexes[i]);
771  }
772  }
773 
774  // Reset list content type to trigger recalculation.
776 
777  return NS_OK;
778 }
779 
782  nsIClassInfo,
785 
786 NS_IMPL_CI_INTERFACE_GETTER7(sbLocalDatabaseSimpleMediaList,
790  sbIMediaItem,
791  sbIMediaList,
794 
795 sbLocalDatabaseSimpleMediaList::sbLocalDatabaseSimpleMediaList()
796 {
797  MOZ_COUNT_CTOR(sbLocalDatabaseSimpleMediaList);
798 #ifdef PR_LOGGING
799  if (!gLocalDatabaseSimpleMediaListLog) {
800  gLocalDatabaseSimpleMediaListLog =
801  PR_NewLogModule("sbLocalDatabaseSimpleMediaList");
802  }
803 #endif
804 }
805 
807 {
808  MOZ_COUNT_DTOR(sbLocalDatabaseSimpleMediaList);
809 }
810 
811 nsresult
813  const nsAString& aGuid)
814 {
815  nsresult rv = sbLocalDatabaseMediaListBase::Init(aLibrary, aGuid);
816  NS_ENSURE_SUCCESS(rv, rv);
817 
819  NS_ENSURE_TRUE(GetArray(), NS_ERROR_OUT_OF_MEMORY);
820 
821  PRUint32 mediaItemId;
822  rv = GetMediaItemId(&mediaItemId);
823  NS_ENSURE_SUCCESS(rv, rv);
824 
825  nsAutoString databaseGuid;
826  rv = mLibrary->GetDatabaseGuid(databaseGuid);
827  NS_ENSURE_SUCCESS(rv, rv);
828 
829  rv = GetArray()->SetDatabaseGUID(databaseGuid);
830  NS_ENSURE_SUCCESS(rv, rv);
831 
832  nsCOMPtr<nsIURI> databaseLocation;
833  rv = mLibrary->GetDatabaseLocation(getter_AddRefs(databaseLocation));
834  NS_ENSURE_SUCCESS(rv, rv);
835 
836  if (databaseLocation) {
837  rv = GetArray()->SetDatabaseLocation(databaseLocation);
838  NS_ENSURE_SUCCESS(rv, rv);
839  }
840 
841  rv = GetArray()->SetBaseTable(NS_LITERAL_STRING("simple_media_lists"));
842  NS_ENSURE_SUCCESS(rv, rv);
843 
844  rv = GetArray()->SetBaseConstraintColumn(NS_LITERAL_STRING("media_item_id"));
845  NS_ENSURE_SUCCESS(rv, rv);
846 
847  rv = GetArray()->SetBaseConstraintValue(mediaItemId);
848  NS_ENSURE_SUCCESS(rv, rv);
849 
850  rv = GetArray()->AddSort(DEFAULT_SORT_PROPERTY, PR_TRUE);
851  NS_ENSURE_SUCCESS(rv, rv);
852 
853  rv = GetArray()->SetFetchSize(DEFAULT_FETCH_SIZE);
854  NS_ENSURE_SUCCESS(rv, rv);
855 
856  nsCOMPtr<sbILocalDatabasePropertyCache> propertyCache;
857  rv = aLibrary->GetPropertyCache(getter_AddRefs(propertyCache));
858  NS_ENSURE_SUCCESS(rv, rv);
859 
860  rv = GetArray()->SetPropertyCache(propertyCache);
861  NS_ENSURE_SUCCESS(rv, rv);
862 
863  nsCOMPtr<sbILocalDatabaseGUIDArrayLengthCache> lengthCache;
864  rv = mLibrary->GetLengthCache(getter_AddRefs(lengthCache));
865  NS_ENSURE_SUCCESS(rv, rv);
866 
867  rv = GetArray()->SetLengthCache(lengthCache);
868  NS_ENSURE_SUCCESS(rv, rv);
869 
870  rv = CreateQueries();
871  NS_ENSURE_SUCCESS(rv, rv);
872 
873  PRBool success = mShouldNotifyAfterRemove.Init();
874  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
875 
876  return NS_OK;
877 }
878 
879 NS_IMETHODIMP
881 {
882  aType.Assign(NS_LITERAL_STRING("simple"));
883  return NS_OK;
884 }
885 
886 NS_IMETHODIMP
888  sbIMediaItem** _retval)
889 {
890  NS_ENSURE_ARG_POINTER(_retval);
891 
892  nsresult rv;
893  nsCOMPtr<sbIMediaItem> item;
894  rv = sbLocalDatabaseMediaListBase::GetItemByGuid(aGuid, getter_AddRefs(item));
895  NS_ENSURE_SUCCESS(rv, rv);
896 
897  PRBool contains;
898  rv = Contains(item, &contains);
899  NS_ENSURE_SUCCESS(rv, rv);
900 
901  if (contains) {
902  NS_ADDREF(*_retval = item);
903  return NS_OK;
904  }
905  else {
906  return NS_ERROR_NOT_AVAILABLE;
907  }
908 
909 }
910 
911 NS_IMETHODIMP
913  PRBool* _retval)
914 {
915  NS_ENSURE_ARG_POINTER(aMediaItem);
916  NS_ENSURE_ARG_POINTER(_retval);
917  nsresult rv;
918 
920 
921  nsString guid;
922  rv = aMediaItem->GetGuid(guid);
923  NS_ENSURE_SUCCESS(rv, rv);
924 
925  // Leverage the guid array cache
926  rv = GetArray()->ContainsGuid(guid, _retval);
927  NS_ENSURE_SUCCESS(rv, rv);
928 
929  return NS_OK;
930 }
931 
932 NS_IMETHODIMP
934 {
935  return AddItem(aMediaItem, nsnull);
936 }
937 
938 NS_IMETHODIMP
940  sbIMediaItem ** aNewMediaItem)
941 {
942  NS_ENSURE_ARG_POINTER(aMediaItem);
943 
945 
946  PRUint32 startingIndex;
947  nsresult rv = GetLength(&startingIndex);
948  NS_ENSURE_SUCCESS(rv, rv);
949 
950  nsString startingOrdinal;
951  rv = GetNextOrdinal(startingOrdinal);
952  NS_ENSURE_SUCCESS(rv, rv);
953 
955  startingIndex,
956  startingOrdinal);
957 
958  PRUint16 stepResult;
959  rv = listener.OnEnumerationBegin(nsnull, &stepResult);
960  NS_ENSURE_SUCCESS(rv, rv);
961 
962  rv = listener.OnEnumeratedItem(nsnull, aMediaItem, &stepResult);
963  NS_ENSURE_SUCCESS(rv, rv);
964 
965  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
966  NS_ENSURE_SUCCESS(rv, rv);
967 
968  if (aNewMediaItem) {
969  rv = GetItemByIndex(startingIndex, aNewMediaItem);
970  NS_ENSURE_SUCCESS(rv, rv);
971  }
972  return NS_OK;
973 }
974 
975 NS_IMETHODIMP
977 {
978  NS_ENSURE_ARG_POINTER(aMediaList);
979 
981 
982  sbAutoBatchHelper batchHelper(*this);
983 
984  PRUint32 startingIndex;
985  nsresult rv = GetLength(&startingIndex);
986  NS_ENSURE_SUCCESS(rv, rv);
987 
988  nsString startingOrdinal;
989  rv = GetNextOrdinal(startingOrdinal);
990  NS_ENSURE_SUCCESS(rv, rv);
991 
993  startingIndex,
994  startingOrdinal);
995  rv =
996  aMediaList->EnumerateAllItems(&listener,
998  NS_ENSURE_SUCCESS(rv, rv);
999 
1000  return NS_OK;
1001 }
1002 
1003 NS_IMETHODIMP
1004 sbLocalDatabaseSimpleMediaList::InsertAllBefore(PRUint32 aIndex,
1005  sbIMediaList* aMediaList)
1006 {
1007  NS_ENSURE_ARG_POINTER(aMediaList);
1008 
1010 
1011  sbAutoBatchHelper batchHelper(*this);
1012 
1013  PRUint32 startingIndex;
1014  nsresult rv = GetLength(&startingIndex);
1015  NS_ENSURE_SUCCESS(rv, rv);
1016 
1017  nsString startingOrdinal;
1018  rv = GetBeforeOrdinal(aIndex, startingOrdinal);
1019  NS_ENSURE_SUCCESS(rv, rv);
1020 
1021  startingOrdinal.AppendLiteral(".0");
1022 
1024  aIndex,
1025  startingOrdinal);
1026  rv =
1027  aMediaList->EnumerateAllItems(&listener,
1029  NS_ENSURE_SUCCESS(rv, rv);
1030 
1031  return NS_OK;
1032 }
1033 
1034 NS_IMETHODIMP
1036 {
1037  return AddMediaItems(aMediaItems, nsnull, PR_FALSE);
1038 }
1039 
1040 NS_IMETHODIMP
1042  nsISimpleEnumerator* aMediaItems,
1043  sbIAddMediaItemsListener * aListener,
1044  PRBool aAsync)
1045 {
1046  NS_ENSURE_ARG_POINTER(aMediaItems);
1047 
1048  if (aAsync)
1049  {
1050  PRUint32 startingIndex;
1051  nsresult rv = GetLength(&startingIndex);
1052  NS_ENSURE_SUCCESS(rv, rv);
1053 
1054  nsString startingOrdinal;
1055  rv = GetNextOrdinal(startingOrdinal);
1056  NS_ENSURE_SUCCESS(rv, rv);
1057 
1058  nsCOMPtr<nsIThread> target;
1059  rv = NS_GetMainThread(getter_AddRefs(target));
1060  NS_ENSURE_SUCCESS(rv, rv);
1061 
1062  nsCOMPtr<sbIAddMediaItemsListener> proxiedListener;
1063  if (aListener) {
1064  rv = do_GetProxyForObject(target,
1065  NS_GET_IID(sbIAddMediaItemsListener),
1066  aListener,
1067  NS_PROXY_SYNC | NS_PROXY_ALWAYS,
1068  getter_AddRefs(proxiedListener));
1069  NS_ENSURE_SUCCESS(rv, rv);
1070  }
1071  nsRefPtr<sbLocalDatabaseSimpleMediaListAddSomeAsyncRunner> runner =
1073  this, aMediaItems, proxiedListener, startingIndex, startingOrdinal);
1074  NS_ENSURE_TRUE(runner, NS_ERROR_OUT_OF_MEMORY);
1075 
1076  nsCOMPtr<nsIThreadPool> threadPoolService =
1077  do_GetService("@songbirdnest.com/Songbird/ThreadPoolService;1", &rv);
1078  NS_ENSURE_SUCCESS(rv, rv);
1079 
1080  rv = threadPoolService->Dispatch(runner, NS_DISPATCH_NORMAL);
1081  NS_ENSURE_SUCCESS(rv, rv);
1082 
1083  return NS_OK;
1084  }
1085  else {
1087 
1088  PRUint32 startingIndex;
1089  nsresult rv = GetLength(&startingIndex);
1090  NS_ENSURE_SUCCESS(rv, rv);
1091 
1092  nsString startingOrdinal;
1093  rv = GetNextOrdinal(startingOrdinal);
1094  NS_ENSURE_SUCCESS(rv, rv);
1095 
1097  startingIndex,
1098  startingOrdinal,
1099  aListener);
1100 
1101  PRUint16 stepResult;
1102  rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1103  NS_ENSURE_SUCCESS(rv, rv);
1104 
1105  sbAutoBatchHelper batchHelper(*this);
1106 
1107  PRBool hasMore;
1108  while (NS_SUCCEEDED(aMediaItems->HasMoreElements(&hasMore)) && hasMore) {
1109  nsCOMPtr<nsISupports> supports;
1110  rv = aMediaItems->GetNext(getter_AddRefs(supports));
1112 
1113  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1115 
1116  rv = listener.OnEnumeratedItem(nsnull, item, &stepResult);
1117  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "OnEnumeratedItem failed!");
1118  }
1119 
1120  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1121  NS_ENSURE_SUCCESS(rv, rv);
1122  }
1123  return NS_OK;
1124 }
1125 
1126 nsresult
1128  nsISupports * aListener,
1129  PRUint32 aStartingIndex,
1130  nsAString& aStartingOrdinal)
1131 {
1132  NS_ENSURE_ARG_POINTER(aMediaItems);
1133  NS_ENSURE_ARG_POINTER(aListener);
1134 
1135  nsresult rv;
1136 
1137  NS_ASSERTION(!NS_IsMainThread(),
1138  "AddSomeAsyncInternal should never be called on the main thread!");
1139 
1140  nsCOMPtr<sbIMediaListAsyncListener> asyncListener;
1141  nsCOMPtr<sbIAddMediaItemsListener> addListener;
1142  if (aListener) {
1143  asyncListener = do_QueryInterface(aListener);
1144  addListener = do_QueryInterface(aListener);
1145  }
1146 
1148 
1150  aStartingIndex,
1151  aStartingOrdinal);
1152 
1153  PRUint16 stepResult;
1154  rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1155  NS_ENSURE_SUCCESS(rv, rv);
1156 
1157  sbAutoBatchHelper batchHelper(*this);
1158 
1159  PRBool hasMore;
1160  PRUint32 itemsProcessed = 0;
1161 
1162  while (NS_SUCCEEDED(aMediaItems->HasMoreElements(&hasMore)) && hasMore) {
1163  nsCOMPtr<nsISupports> supports;
1164  rv = aMediaItems->GetNext(getter_AddRefs(supports));
1166 
1167  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1169 
1170  rv = listener.OnEnumeratedItem(nsnull, item, &stepResult);
1171  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "OnEnumeratedItem failed!");
1172 
1173  ++itemsProcessed;
1174 
1175  // only send notifications every SB_ASYNC_NOTIFICATION_ITEMS items or
1176  // when it's finished if < SB_ASYNC_NOTIFICATION_ITEMS items.
1177  if (itemsProcessed % SB_ASYNC_NOTIFICATION_ITEMS == 0) {
1178  if (asyncListener) {
1179  rv = asyncListener->OnProgress(itemsProcessed, PR_FALSE);
1180  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to call async listener.");
1181  }
1182  else if (addListener) {
1183  rv = addListener->OnProgress(itemsProcessed, PR_FALSE);
1184  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to call add listener.");
1185  }
1186  }
1187 
1188  // Yield to other threads.
1189  PR_Sleep(0);
1190  }
1191 
1192  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1193  NS_ENSURE_SUCCESS(rv, rv);
1194 
1195  if (asyncListener) {
1196  rv = asyncListener->OnProgress(itemsProcessed, PR_TRUE);
1197  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to call async listener.");
1198  }
1199  else if (addListener) {
1200  rv = addListener->OnProgress(itemsProcessed, PR_TRUE);
1201  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to call add listener.");
1202  }
1203  return NS_OK;
1204 }
1205 
1206 NS_IMETHODIMP
1207 sbLocalDatabaseSimpleMediaList::InsertBefore(PRUint32 aIndex,
1208  sbIMediaItem* aMediaItem)
1209 {
1210  NS_ENSURE_ARG_POINTER(aMediaItem);
1212  SB_ENSURE_INDEX1(aIndex);
1213 
1214  nsString startingOrdinal;
1215  nsresult rv = GetBeforeOrdinal(aIndex, startingOrdinal);
1216  NS_ENSURE_SUCCESS(rv, rv);
1217 
1219  aIndex,
1220  startingOrdinal);
1221 
1222  PRUint16 stepResult;
1223  rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1224  NS_ENSURE_SUCCESS(rv, rv);
1225 
1226  rv = listener.OnEnumeratedItem(nsnull, aMediaItem, &stepResult);
1227  NS_ENSURE_SUCCESS(rv, rv);
1228 
1229  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1230  NS_ENSURE_SUCCESS(rv, rv);
1231 
1232  return NS_OK;
1233 }
1234 
1235 NS_IMETHODIMP
1236 sbLocalDatabaseSimpleMediaList::MoveBefore(PRUint32 aFromIndex,
1237  PRUint32 aToIndex)
1238 {
1239  // Do nothing if we don't have to move
1240  if (aFromIndex == aToIndex) {
1241  return NS_OK;
1242  }
1243 
1244  nsresult rv;
1245 
1247  SB_ENSURE_INDEX2(aFromIndex, aToIndex);
1248 
1249  // Get the ordinal of the space before the to index
1250  nsAutoString ordinal;
1251  rv = GetBeforeOrdinal(aToIndex, ordinal);
1252  NS_ENSURE_SUCCESS(rv, rv);
1253 
1254  rv = UpdateOrdinalByIndex(aFromIndex, ordinal);
1255  NS_ENSURE_SUCCESS(rv, rv);
1256 
1257  // Invalidate the cached list. Moving items does not invalidate length.
1258  rv = GetArray()->Invalidate(PR_FALSE);
1259  NS_ENSURE_SUCCESS(rv, rv);
1260 
1261  rv = UpdateLastModifiedTime();
1262  NS_ENSURE_SUCCESS(rv, rv);
1263 
1264  nsCOMPtr<sbIMediaList> list =
1265  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1266  NS_ENSURE_SUCCESS(rv, rv);
1267 
1268  // If the from index is smaller than the to index, then moving the item out
1269  // of the from index causes everything to shift once
1270  if (aFromIndex < aToIndex) {
1271  aToIndex--;
1272  }
1273 
1275  aFromIndex,
1276  aToIndex);
1277 
1278  return NS_OK;
1279 }
1280 
1281 NS_IMETHODIMP
1282 sbLocalDatabaseSimpleMediaList::MoveLast(PRUint32 aIndex)
1283 {
1284  nsresult rv;
1285 
1287  SB_ENSURE_INDEX1(aIndex);
1288 
1289  // Get the ordinal for the space after the last item in the list
1290  nsAutoString ordinal;
1291  rv = GetNextOrdinal(ordinal);
1292  NS_ENSURE_SUCCESS(rv, rv);
1293 
1294  rv = UpdateOrdinalByIndex(aIndex, ordinal);
1295  NS_ENSURE_SUCCESS(rv, rv);
1296 
1297  // Grab the length before the invalidation since it won't be changing
1298  PRUint32 length;
1299  rv = GetArray()->GetLength(&length);
1300  NS_ENSURE_SUCCESS(rv, rv);
1301 
1302  // Invalidate the cached list. Moving items does not invalidate length.
1303  rv = GetArray()->Invalidate(PR_FALSE);
1304  NS_ENSURE_SUCCESS(rv, rv);
1305 
1306  rv = UpdateLastModifiedTime();
1307  NS_ENSURE_SUCCESS(rv, rv);
1308 
1309  nsCOMPtr<sbIMediaList> list =
1310  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1311  NS_ENSURE_SUCCESS(rv, rv);
1312 
1314  aIndex,
1315  length - 1);
1316 
1317  return NS_OK;
1318 }
1319 
1320 NS_IMETHODIMP
1321 sbLocalDatabaseSimpleMediaList::InsertSomeBefore(PRUint32 aIndex,
1322  nsISimpleEnumerator* aMediaItems)
1323 {
1324  NS_ENSURE_ARG_POINTER(aMediaItems);
1326  SB_ENSURE_INDEX1(aIndex);
1327 
1328  nsString startingOrdinal;
1329  nsresult rv = GetBeforeOrdinal(aIndex, startingOrdinal);
1330  NS_ENSURE_SUCCESS(rv, rv);
1331 
1332  startingOrdinal.AppendLiteral(".0");
1333 
1335  aIndex,
1336  startingOrdinal);
1337 
1338  PRUint16 stepResult;
1339  rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1340  NS_ENSURE_SUCCESS(rv, rv);
1341 
1342  sbAutoBatchHelper batchHelper(*this);
1343 
1344  PRBool hasMore;
1345  while (NS_SUCCEEDED(aMediaItems->HasMoreElements(&hasMore)) && hasMore) {
1346  nsCOMPtr<nsISupports> supports;
1347  rv = aMediaItems->GetNext(getter_AddRefs(supports));
1349 
1350  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1352 
1353  rv = listener.OnEnumeratedItem(nsnull, item, &stepResult);
1354  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "OnEnumeratedItem failed!");
1355  }
1356 
1357  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1358  NS_ENSURE_SUCCESS(rv, rv);
1359 
1360  return NS_OK;
1361 }
1362 
1363 NS_IMETHODIMP
1364 sbLocalDatabaseSimpleMediaList::InsertSomeBeforeAsync(
1365  PRUint32 aIndex,
1366  nsISimpleEnumerator* aMediaItems,
1367  sbIMediaListAsyncListener* aListener)
1368 {
1369  NS_ENSURE_ARG_POINTER(aMediaItems);
1370  NS_ENSURE_ARG_POINTER(aListener);
1371  SB_ENSURE_INDEX1(aIndex);
1372 
1373  nsresult rv;
1374 
1375  nsString startingOrdinal;
1376  rv = GetBeforeOrdinal(aIndex, startingOrdinal);
1377  NS_ENSURE_SUCCESS(rv, rv);
1378 
1379  startingOrdinal.AppendLiteral(".0");
1380 
1381  nsCOMPtr<nsIThread> target;
1382  rv = NS_GetMainThread(getter_AddRefs(target));
1383  NS_ENSURE_SUCCESS(rv, rv);
1384 
1385  nsCOMPtr<sbIMediaListAsyncListener> proxiedListener;
1386  rv = do_GetProxyForObject(target,
1387  NS_GET_IID(sbIMediaListAsyncListener),
1388  aListener,
1389  NS_PROXY_SYNC | NS_PROXY_ALWAYS,
1390  getter_AddRefs(proxiedListener));
1391  NS_ENSURE_SUCCESS(rv, rv);
1392 
1393  nsRefPtr<sbLocalDatabaseSimpleMediaListAddSomeAsyncRunner> runner =
1395  this, aMediaItems, proxiedListener, aIndex, startingOrdinal);
1396  NS_ENSURE_TRUE(runner, NS_ERROR_OUT_OF_MEMORY);
1397 
1398  nsCOMPtr<nsIThreadPool> threadPoolService =
1399  do_GetService("@songbirdnest.com/Songbird/ThreadPoolService;1", &rv);
1400  NS_ENSURE_SUCCESS(rv, rv);
1401 
1402  rv = threadPoolService->Dispatch(runner, NS_DISPATCH_NORMAL);
1403  NS_ENSURE_SUCCESS(rv, rv);
1404 
1405  return NS_OK;
1406 }
1407 
1408 NS_IMETHODIMP
1409 sbLocalDatabaseSimpleMediaList::MoveSomeBefore(PRUint32* aFromIndexArray,
1410  PRUint32 aFromIndexArrayCount,
1411  PRUint32 aToIndex)
1412 {
1413  NS_ENSURE_ARG_POINTER(aFromIndexArray);
1414 
1415  nsresult rv;
1416 
1418  SB_ENSURE_INDEX1(aToIndex);
1419 
1420  nsAutoString ordinal;
1421  rv = GetBeforeOrdinal(aToIndex, ordinal);
1422  NS_ENSURE_SUCCESS(rv, rv);
1423 
1424  ordinal.AppendLiteral(".");
1425  rv = MoveSomeInternal(aFromIndexArray,
1426  aFromIndexArrayCount,
1427  aToIndex,
1428  ordinal);
1429  NS_ENSURE_SUCCESS(rv, rv);
1430 
1431  return NS_OK;
1432 }
1433 
1434 NS_IMETHODIMP
1435 sbLocalDatabaseSimpleMediaList::MoveSomeLast(PRUint32* aIndexArray,
1436  PRUint32 aIndexArrayCount)
1437 {
1439 
1440  NS_ENSURE_ARG_POINTER(aIndexArray);
1441 
1442  nsAutoString ordinal;
1443  nsresult rv = GetNextOrdinal(ordinal);
1444  NS_ENSURE_SUCCESS(rv, rv);
1445 
1446  ordinal.AppendLiteral(".");
1447 
1448  PRUint32 length;
1449  rv = GetArray()->GetLength(&length);
1450  NS_ENSURE_SUCCESS(rv, rv);
1451 
1452  rv = MoveSomeInternal(aIndexArray, aIndexArrayCount, length, ordinal);
1453  NS_ENSURE_SUCCESS(rv, rv);
1454 
1455  return NS_OK;
1456 }
1457 
1458 NS_IMETHODIMP
1460 {
1461  NS_ENSURE_ARG_POINTER(aMediaItem);
1462 
1464 
1465  // Use our enumeration helper to make all these remove calls use the same
1466  // code.
1468 
1469  PRUint16 stepResult;
1470  nsresult rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1471  NS_ENSURE_SUCCESS(rv, rv);
1472 
1473  rv = listener.OnEnumeratedItem(nsnull, aMediaItem, &stepResult);
1474  NS_ENSURE_SUCCESS(rv, rv);
1475 
1476  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1477  NS_ENSURE_SUCCESS(rv, rv);
1478 
1479  return NS_OK;
1480 }
1481 
1482 NS_IMETHODIMP
1484 {
1486 
1487  nsresult rv;
1488 
1489  nsAutoString ordinal;
1490  rv = GetArray()->GetSortPropertyValueByIndex(aIndex, ordinal);
1491  NS_ENSURE_SUCCESS(rv, rv);
1492 
1493  nsCOMPtr<sbIMediaItem> item;
1494  rv = GetItemByIndex(aIndex, getter_AddRefs(item));
1495  NotifyListenersBeforeItemRemoved(this, item, aIndex);
1496 
1497  nsCOMPtr<sbIDatabaseQuery> dbQuery;
1498  rv = MakeStandardQuery(getter_AddRefs(dbQuery));
1499  NS_ENSURE_SUCCESS(rv, rv);
1500 
1501  rv = dbQuery->AddQuery(mDeleteListItemByOrdinalQuery);
1502  NS_ENSURE_SUCCESS(rv, rv);
1503 
1504  rv = dbQuery->BindStringParameter(0, ordinal);
1505  NS_ENSURE_SUCCESS(rv, rv);
1506 
1507  PRInt32 dbSuccess;
1508  rv = dbQuery->Execute(&dbSuccess);
1509  NS_ENSURE_SUCCESS(rv, rv);
1510  NS_ENSURE_TRUE(dbSuccess == 0, NS_ERROR_FAILURE);
1511 
1512  rv = GetArray()->RemoveByIndex(aIndex);
1513  NS_ENSURE_SUCCESS(rv, rv);
1514 
1515  rv = UpdateLastModifiedTime();
1516  NS_ENSURE_SUCCESS(rv, rv);
1517 
1518  nsCOMPtr<sbIMediaList> mediaList =
1519  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1520  NS_ENSURE_SUCCESS(rv, rv);
1521 
1522  NotifyListenersAfterItemRemoved(mediaList, item, aIndex);
1523 
1524  // Reset list content type to trigger recalculation.
1526 
1527  return NS_OK;
1528 }
1529 
1530 NS_IMETHODIMP
1532 {
1533  NS_ENSURE_ARG_POINTER(aMediaItems);
1534 
1536 
1538 
1539  sbAutoBatchHelper batchHelper(*this);
1540 
1541  PRUint16 stepResult;
1542  nsresult rv = listener.OnEnumerationBegin(nsnull, &stepResult);
1543  NS_ENSURE_SUCCESS(rv, rv);
1544 
1545  PRBool hasMore;
1546  while (NS_SUCCEEDED(aMediaItems->HasMoreElements(&hasMore)) && hasMore) {
1547 
1548  nsCOMPtr<nsISupports> supports;
1549  rv = aMediaItems->GetNext(getter_AddRefs(supports));
1551 
1552  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1554 
1555  rv = listener.OnEnumeratedItem(nsnull, item, &stepResult);
1556  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "OnEnumeratedItem failed!");
1557  }
1558 
1559  rv = listener.OnEnumerationEnd(nsnull, NS_OK);
1560  NS_ENSURE_SUCCESS(rv, rv);
1561 
1562  return NS_OK;
1563 }
1564 
1565 NS_IMETHODIMP
1567 {
1569 
1570  nsresult rv;
1571  PRInt32 dbOk;
1572 
1573  nsCOMPtr<sbIMediaList> mediaList =
1574  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1575  NS_ENSURE_SUCCESS(rv, rv);
1576 
1578  PR_FALSE);
1579 
1580  nsCOMPtr<sbIDatabaseQuery> query;
1581  rv = MakeStandardQuery(getter_AddRefs(query));
1582  NS_ENSURE_SUCCESS(rv, rv);
1583 
1584  rv = query->AddQuery(mDeleteAllQuery);
1585  NS_ENSURE_SUCCESS(rv, rv);
1586 
1587  rv = query->Execute(&dbOk);
1588  NS_ENSURE_SUCCESS(rv, rv);
1589  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1590 
1591  // Invalidate the cached list. Clearing definitely invalidates length.
1592  rv = GetArray()->Invalidate(PR_TRUE);
1593  NS_ENSURE_SUCCESS(rv, rv);
1594 
1595  rv = UpdateLastModifiedTime();
1596  NS_ENSURE_SUCCESS(rv, rv);
1597 
1599  PR_FALSE);
1600 
1601  // Reset list content type to trigger recalculation.
1603 
1604  return NS_OK;
1605 }
1606 
1607 // Called when something external changed our content without going through the
1608 // normal means (ie, sbIMediaList). This is not a routine operation, normally
1609 // everything should go through the media list methods, but there are cases,
1610 // such as smart playlists, where it makes sense to just copy the content of
1611 // one table into another. When this happens, none of the listeners will have
1612 // been notified of anything that may have happened to the items in the list.
1613 // For instance, this includes the medialistview, which does not refresh its
1614 // content. This method first triggers a LISTCLEARED notification, then enters
1615 // batch mode and sends one ITEMADDED per item in the list.
1616 NS_IMETHODIMP
1617 sbLocalDatabaseSimpleMediaList::NotifyContentChanged()
1618 {
1619  // Invalidate the cached list. No way to tell if length changes so we have
1620  // to invalidate it as well.
1621  nsresult rv = GetArray()->Invalidate(PR_TRUE);
1622  NS_ENSURE_SUCCESS(rv, rv);
1623 
1624  // Reset list content type to trigger recalculation.
1626 
1627  nsCOMPtr<sbIMediaList> mediaList =
1628  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1629  NS_ENSURE_SUCCESS(rv, rv);
1630 
1631  // If we have listeners, they will probably want to know about this
1632  if (ListenerCount() > 0) {
1633  // Start a batch for both the LISTCLEARED and all the ITEMADDED notifications,
1634  // so that if a listener needs to differentiate between ContentChanged and
1635  // a real LISTCLEAR + N*ITEMADDED, the fact that the whole thing happened in
1636  // one single batch will be its clue.
1637  sbAutoBatchHelper batchHelper(*this);
1638 
1639  // First, notify listeners that the list has been cleared
1641  (mediaList, PR_FALSE);
1643  (mediaList, PR_FALSE);
1644 
1645  // Then send an ITEMADDED notification for each item that we now have in the list
1646  PRUint32 length;
1647  rv = GetArray()->GetLength(&length);
1648  NS_ENSURE_SUCCESS(rv, rv);
1649 
1650  for (PRUint32 index=0; index<length; index++) {
1651  nsCOMPtr<sbIMediaItem> item;
1652  rv = GetItemByIndex(index, getter_AddRefs(item));
1653  NotifyListenersItemAdded(this, item, index);
1654  }
1655  }
1656 
1657  return NS_OK;
1658 }
1659 
1660 NS_IMETHODIMP
1662  sbIMediaListView** _retval)
1663 {
1664  NS_ENSURE_ARG_POINTER(_retval);
1665 
1666  nsresult rv;
1667 
1668  nsAutoString defaultSortProperty;
1669  rv = GetDefaultSortProperty(defaultSortProperty);
1670  NS_ENSURE_SUCCESS(rv, rv);
1671 
1672  PRUint32 mediaItemId;
1673  rv = GetMediaItemId(&mediaItemId);
1674  NS_ENSURE_SUCCESS(rv, rv);
1675 
1676  nsRefPtr<sbLocalDatabaseMediaListView>
1678  this,
1679  defaultSortProperty,
1680  mediaItemId));
1681  NS_ENSURE_TRUE(view, NS_ERROR_OUT_OF_MEMORY);
1682  rv = view->Init(aState);
1683  NS_ENSURE_SUCCESS(rv, rv);
1684 
1685  NS_ADDREF(*_retval = view);
1686  return NS_OK;
1687 }
1688 
1689 // sbILocalDatabaseSimpleMediaList
1690 NS_IMETHODIMP
1691 sbLocalDatabaseSimpleMediaList::GetCopyListener(
1692  sbILocalDatabaseMediaListCopyListener * *aCopyListener)
1693 {
1694  NS_ENSURE_ARG_POINTER(aCopyListener);
1695 
1696  *aCopyListener = nsnull;
1697 
1698  if(mCopyListener) {
1699  NS_ADDREF(*aCopyListener = mCopyListener);
1700  }
1701 
1702  return NS_OK;
1703 }
1704 
1705 NS_IMETHODIMP sbLocalDatabaseSimpleMediaList::SetCopyListener(
1706  sbILocalDatabaseMediaListCopyListener * aCopyListener)
1707 {
1708  NS_ENSURE_ARG_POINTER(aCopyListener);
1709 
1710  mCopyListener = aCopyListener;
1711 
1712  return NS_OK;
1713 }
1714 
1715 NS_IMETHODIMP
1716 sbLocalDatabaseSimpleMediaList::GetIndexByOrdinal(const nsAString& aOrdinal,
1717  PRUint32* _retval)
1718 {
1719  NS_ENSURE_ARG_POINTER(_retval);
1720 
1721  nsresult rv;
1722 
1723  // First, search the cache for this ordinal
1724  PRUint32 length;
1725  rv = GetArray()->GetLength(&length);
1726  NS_ENSURE_SUCCESS(rv, rv);
1727 
1728  for (PRUint32 i = 0; i < length; i++) {
1729  PRBool isCached;
1730  rv = GetArray()->IsIndexCached(i, &isCached);
1731  NS_ENSURE_SUCCESS(rv, rv);
1732 
1733  if (isCached) {
1734  nsAutoString ordinal;
1735  rv = GetArray()->GetOrdinalByIndex(i, ordinal);
1736  NS_ENSURE_SUCCESS(rv, rv);
1737 
1738  if (ordinal.Equals(aOrdinal)) {
1739  *_retval = i;
1740  return NS_OK;
1741  }
1742  }
1743  }
1744 
1745  // Not cached, search the database
1746  PRUint32 index;
1747  rv = GetArray()->GetFirstIndexByPrefix(aOrdinal, &index);
1748  if (NS_SUCCEEDED(rv)) {
1749  *_retval = index;
1750  return NS_OK;
1751  }
1752 
1753  return NS_ERROR_NOT_AVAILABLE;
1754 }
1755 
1756 NS_IMETHODIMP
1757 sbLocalDatabaseSimpleMediaList::Invalidate(PRBool aInvalidateLength)
1758 {
1759  nsresult rv = GetArray()->Invalidate(aInvalidateLength);
1760  NS_ENSURE_SUCCESS(rv, rv);
1761 
1762  // Reset list content type to trigger recalculation.
1764 
1765  nsCOMPtr<sbIMediaList> list =
1766  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1767  NS_ENSURE_SUCCESS(rv, rv);
1768 
1769  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(list, &rv);
1770  NS_ENSURE_SUCCESS(rv, rv);
1771 
1772  nsCOMPtr<sbIMutablePropertyArray> properties =
1773  do_CreateInstance(SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv);
1774  NS_ENSURE_SUCCESS(rv, rv);
1775 
1776  // XXXsteve What should go into the updated properties array?
1777 
1779  item,
1780  properties);
1781  return NS_OK;
1782 }
1783 
1784 NS_IMETHODIMP
1786  PRUint32 aIndex,
1787  sbIPropertyArray* aProperties)
1788 {
1789  NS_ENSURE_ARG_POINTER(aItem);
1790  NS_ENSURE_ARG_POINTER(aProperties);
1791 
1792  nsresult rv;
1793  nsCOMPtr<sbIMediaList> list =
1794  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
1795  NS_ENSURE_SUCCESS(rv, rv);
1797  aItem,
1798  aProperties);
1799  return NS_OK;
1800 }
1801 
1802 NS_IMETHODIMP
1804  sbIMediaItem* aItem,
1805  PRUint32 aIndex)
1806 {
1807  NS_ENSURE_ARG_POINTER(aList);
1808  NS_ENSURE_ARG_POINTER(aItem);
1809 
1811  aItem,
1812  aIndex);
1813  return NS_OK;
1814 }
1815 
1816 NS_IMETHODIMP
1818  sbIMediaItem* aItem,
1819  PRUint32 aIndex)
1820 {
1821  NS_ENSURE_ARG_POINTER(aList);
1822  NS_ENSURE_ARG_POINTER(aItem);
1823 
1825  aItem,
1826  aIndex);
1827  return NS_OK;
1828 }
1829 
1830 NS_IMETHODIMP
1832  (sbIMediaList* aList,
1833  PRBool aExcludeLists)
1834 {
1835  NS_ENSURE_ARG_POINTER(aList);
1836 
1838  (aList, aExcludeLists);
1839  return NS_OK;
1840 }
1841 
1842 NS_IMETHODIMP
1844  (sbIMediaList* aList,
1845  PRBool aExcludeLists)
1846 {
1847  NS_ENSURE_ARG_POINTER(aList);
1848 
1850  aExcludeLists);
1851  return NS_OK;
1852 }
1853 
1854 NS_IMETHODIMP
1856 {
1857  NS_ENSURE_ARG_POINTER(aList);
1858 
1860  return NS_OK;
1861 }
1862 
1863 NS_IMETHODIMP
1865 {
1866  NS_ENSURE_ARG_POINTER(aList);
1867 
1869  return NS_OK;
1870 }
1871 
1872 nsresult
1873 sbLocalDatabaseSimpleMediaList::UpdateLastModifiedTime()
1874 {
1875  nsresult rv;
1876 
1877  sbAutoString now((PRUint64)(PR_Now()/PR_MSEC_PER_SEC));
1878  rv = SetProperty(NS_LITERAL_STRING(SB_PROPERTY_UPDATED), now);
1879  NS_ENSURE_SUCCESS(rv, rv);
1880 
1881  return NS_OK;
1882 }
1883 
1884 nsresult
1885 sbLocalDatabaseSimpleMediaList::ExecuteAggregateQuery(const nsAString& aQuery,
1886  nsAString& aValue)
1887 {
1888  nsresult rv;
1889  PRInt32 dbOk;
1890 
1891  nsCOMPtr<sbIDatabaseQuery> query;
1892  rv = MakeStandardQuery(getter_AddRefs(query));
1893  NS_ENSURE_SUCCESS(rv, rv);
1894 
1895  rv = query->AddQuery(aQuery);
1896  NS_ENSURE_SUCCESS(rv, rv);
1897 
1898  rv = query->Execute(&dbOk);
1899  NS_ENSURE_SUCCESS(rv, rv);
1900  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1901 
1902  nsCOMPtr<sbIDatabaseResult> result;
1903  rv = query->GetResultObject(getter_AddRefs(result));
1904  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1905 
1906  PRUint32 rowCount;
1907  rv = result->GetRowCount(&rowCount);
1908  NS_ENSURE_SUCCESS(rv, rv);
1909 
1910  if (rowCount == 0) {
1911  return NS_ERROR_UNEXPECTED;
1912  }
1913 
1914  rv = result->GetRowCell(0, 0, aValue);
1915  NS_ENSURE_SUCCESS(rv, rv);
1916 
1917  return NS_OK;
1918 }
1919 
1920 nsresult
1921 sbLocalDatabaseSimpleMediaList::UpdateOrdinalByIndex(PRUint32 aIndex,
1922  const nsAString& aOrdinal)
1923 {
1924  nsresult rv;
1925  PRInt32 dbOk;
1926 
1927  // Get the media item id of the item we are moving
1928  PRUint32 mediaItemId;
1929  rv = GetArray()->GetMediaItemIdByIndex(aIndex, &mediaItemId);
1930  NS_ENSURE_SUCCESS(rv, rv);
1931 
1932  // Get the old ordinal
1933  nsString oldOrdinal;
1934  rv = GetArray()->GetOrdinalByIndex(aIndex, oldOrdinal);
1935  NS_ENSURE_SUCCESS(rv, rv);
1936 
1937  // Update the item at the from index with the new ordinal
1938  nsCOMPtr<sbIDatabaseQuery> query;
1939  rv = MakeStandardQuery(getter_AddRefs(query));
1940  NS_ENSURE_SUCCESS(rv, rv);
1941 
1942  rv = query->AddQuery(mUpdateListItemOrdinalQuery);
1943  NS_ENSURE_SUCCESS(rv, rv);
1944 
1945  rv = query->BindStringParameter(0, aOrdinal);
1946  NS_ENSURE_SUCCESS(rv, rv);
1947 
1948  rv = query->BindInt32Parameter(1, mediaItemId);
1949  NS_ENSURE_SUCCESS(rv, rv);
1950 
1951  rv = query->BindStringParameter(2, oldOrdinal);
1952  NS_ENSURE_SUCCESS(rv, rv);
1953 
1954  rv = query->Execute(&dbOk);
1955  NS_ENSURE_SUCCESS(rv, rv);
1956  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1957 
1958  return NS_OK;
1959 }
1960 
1961 nsresult
1962 sbLocalDatabaseSimpleMediaList::MoveSomeInternal(PRUint32* aFromIndexArray,
1963  PRUint32 aFromIndexArrayCount,
1964  PRUint32 aToIndex,
1965  const nsAString& aOrdinalRoot)
1966 {
1967  NS_ASSERTION(aFromIndexArray, "aFromIndexArray is null");
1968 
1969  PRUint32 length;
1970  nsresult rv = GetArray()->GetLength(&length);
1971  NS_ENSURE_SUCCESS(rv, rv);
1972 
1973  // Make sure all the from array indexes are legal
1974  for (PRUint32 i = 0; i < aFromIndexArrayCount; i++) {
1975  NS_ENSURE_ARG_MAX(aFromIndexArray[i], length - 1);
1976  }
1977 
1978  nsCOMPtr<sbIDatabaseQuery> query;
1979  rv = MakeStandardQuery(getter_AddRefs(query));
1980  NS_ENSURE_SUCCESS(rv, rv);
1981 
1982  sbAutoBatchHelper batchHelper(*this);
1983 
1984  rv = query->AddQuery(NS_LITERAL_STRING("begin"));
1985  NS_ENSURE_SUCCESS(rv, rv);
1986 
1987  for (PRUint32 i = 0; i < aFromIndexArrayCount; i++) {
1988  nsAutoString ordinal(aOrdinalRoot);
1989  ordinal.AppendInt(i);
1990 
1991  PRUint32 mediaItemId;
1992  rv = GetArray()->GetMediaItemIdByIndex(aFromIndexArray[i], &mediaItemId);
1993  NS_ENSURE_SUCCESS(rv, rv);
1994 
1995  nsString oldOrdinal;
1996  rv = GetArray()->GetOrdinalByIndex(aFromIndexArray[i], oldOrdinal);
1997  NS_ENSURE_SUCCESS(rv, rv);
1998 
1999  rv = query->AddQuery(mUpdateListItemOrdinalQuery);
2000  NS_ENSURE_SUCCESS(rv, rv);
2001 
2002  rv = query->BindStringParameter(0, ordinal);
2003  NS_ENSURE_SUCCESS(rv, rv);
2004 
2005  rv = query->BindInt32Parameter(1, mediaItemId);
2006  NS_ENSURE_SUCCESS(rv, rv);
2007 
2008  rv = query->BindStringParameter(2, oldOrdinal);
2009  NS_ENSURE_SUCCESS(rv, rv);
2010  }
2011 
2012  rv = query->AddQuery(NS_LITERAL_STRING("commit"));
2013  NS_ENSURE_SUCCESS(rv, rv);
2014 
2015  PRInt32 dbOk;
2016  rv = query->Execute(&dbOk);
2017  NS_ENSURE_SUCCESS(rv, rv);
2018  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2019 
2020  // Invalidate the cached list. Moving items does not invalidate length.
2021  rv = GetArray()->Invalidate(PR_FALSE);
2022  NS_ENSURE_SUCCESS(rv, rv);
2023 
2024  nsCOMPtr<sbIMediaList> list =
2025  do_QueryInterface(NS_ISUPPORTS_CAST(sbILocalDatabaseSimpleMediaList*, this), &rv);
2026  NS_ENSURE_SUCCESS(rv, rv);
2027 
2028  nsTArray<PRUint32> shiftedIndexes;
2029  PRUint32* success = shiftedIndexes.AppendElements(aFromIndexArray,
2030  aFromIndexArrayCount);
2031  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
2032 
2033  for (PRUint32 i = 0; i < aFromIndexArrayCount; i++) {
2034  PRUint32 fromIndex = shiftedIndexes[i];
2035 
2036  // If this item has moved forward, the we shift the to-index back once since
2037  // the incoming indexes are all "move before" indicies
2038  PRUint32 shift = 0;
2039  if (fromIndex < aToIndex) {
2040  shift = 1;
2041  }
2042 
2044  fromIndex,
2045  aToIndex - shift);
2046 
2047  // If this moved shifted the remaining indexes to be notified, shift them
2048  for (PRUint32 j = i + 1; j < aFromIndexArrayCount; j++) {
2049  // The moved item has jumped behind this index, causing this index to
2050  // shift forward. Shift it back.
2051  if (fromIndex < shiftedIndexes[j] && aToIndex > shiftedIndexes[j]) {
2052  shiftedIndexes[j]--;
2053  }
2054  else {
2055  // The moved item has jumped in front of this index, causing this index
2056  // to shift backwards. Shift it forward.
2057  if (aToIndex <= shiftedIndexes[j] && fromIndex > shiftedIndexes[j]) {
2058  shiftedIndexes[j]++;
2059  }
2060  }
2061  }
2062 
2063  // If we're moving indexes backwards, we need to adjust the insert point
2064  // so the next item is put after the previous
2065  if (fromIndex > aToIndex) {
2066  aToIndex++;
2067  }
2068 
2069  }
2070 
2071  rv = UpdateLastModifiedTime();
2072  NS_ENSURE_SUCCESS(rv, rv);
2073 
2074  return NS_OK;
2075 }
2076 
2077 nsresult
2078 sbLocalDatabaseSimpleMediaList::GetNextOrdinal(nsAString& aValue)
2079 {
2080  nsresult rv;
2081 
2082  PRUint32 length;
2083  rv = GetArray()->GetLength(&length);
2084  NS_ENSURE_SUCCESS(rv, rv);
2085 
2086  if (length == 0) {
2087  aValue.AssignLiteral("0");
2088  return NS_OK;
2089  }
2090 
2091  PRBool cached;
2092  rv = GetArray()->IsIndexCached(length - 1, &cached);
2093  NS_ENSURE_SUCCESS(rv, rv);
2094 
2095  if (cached) {
2096  rv = GetArray()->GetSortPropertyValueByIndex(length - 1, aValue);
2097  NS_ENSURE_SUCCESS(rv, rv);
2098  }
2099  else {
2100  rv = ExecuteAggregateQuery(mGetLastOrdinalQuery, aValue);
2101  NS_ENSURE_SUCCESS(rv, rv);
2102  }
2103 
2104  rv = AddToLastPathSegment(aValue, 1);
2105  NS_ENSURE_SUCCESS(rv, rv);
2106 
2107  return NS_OK;
2108 }
2109 
2110 nsresult
2111 sbLocalDatabaseSimpleMediaList::GetBeforeOrdinal(PRUint32 aIndex,
2112  nsAString& aValue)
2113 {
2114  nsresult rv;
2115 
2116  // If we want to insert before the first index, get the ordinal of the
2117  // first index and trim off everything but the first path and subtract 1
2118  if (aIndex == 0) {
2119  PRBool cached;
2120  rv = GetArray()->IsIndexCached(0, &cached);
2121  NS_ENSURE_SUCCESS(rv, rv);
2122 
2123  nsAutoString ordinal;
2124  if (cached) {
2125  rv = GetArray()->GetSortPropertyValueByIndex(0, ordinal);
2126  NS_ENSURE_SUCCESS(rv, rv);
2127  }
2128  else {
2129  rv = ExecuteAggregateQuery(mGetFirstOrdinalQuery, ordinal);
2130  NS_ENSURE_SUCCESS(rv, rv);
2131  }
2132 
2133  // Trim off additional path segments, if any
2134  PRUint32 pos = ordinal.FindChar('.');
2135  if (pos >= 0) {
2136  ordinal.SetLength(pos);
2137  }
2138 
2139  PRInt32 value = ordinal.ToInteger(&rv) - 1;
2140  NS_ENSURE_SUCCESS(rv, rv);
2141 
2142  nsAutoString newOrdinal;
2143  newOrdinal.AppendInt(value);
2144  aValue = newOrdinal;
2145 
2146  return NS_OK;
2147  }
2148 
2149  // Find the ordinals before and after the place we want to insert
2150  nsAutoString aboveOrdinal;
2151  nsAutoString belowOrdinal;
2152 
2153  rv = GetArray()->GetSortPropertyValueByIndex(aIndex - 1, aboveOrdinal);
2154  NS_ENSURE_SUCCESS(rv, rv);
2155 
2156  rv = GetArray()->GetSortPropertyValueByIndex(aIndex, belowOrdinal);
2157  NS_ENSURE_SUCCESS(rv, rv);
2158 
2159  PRUint32 aboveLevels = CountLevels(aboveOrdinal);
2160  PRUint32 belowLevels = CountLevels(belowOrdinal);
2161 
2162  // If the two paths are to the same level, create a new level on the
2163  // below path to make a path that sorts between
2164  if (aboveLevels == belowLevels) {
2165  belowOrdinal.AppendLiteral(".0");
2166  aValue = belowOrdinal;
2167  return NS_OK;
2168  }
2169 
2170  // Otherwise if the below path is longer than the above path, decrement the
2171  // last path segment of the below path
2172  if (belowLevels > aboveLevels) {
2173  rv = AddToLastPathSegment(belowOrdinal, -1);
2174  NS_ENSURE_SUCCESS(rv, rv);
2175  aValue = belowOrdinal;
2176  return NS_OK;
2177  }
2178 
2179  // If the above path is longer than the below, increment the last path
2180  // segment of the above path
2181  rv = AddToLastPathSegment(aboveOrdinal, 1);
2182  NS_ENSURE_SUCCESS(rv, rv);
2183  aValue = aboveOrdinal;
2184  return NS_OK;
2185 }
2186 
2187 nsresult
2188 sbLocalDatabaseSimpleMediaList::AddToLastPathSegment(nsAString& aPath,
2189  PRInt32 aToAdd)
2190 {
2191 
2192  PRUint32 startPos = aPath.RFindChar('.') + 1;
2193  PRUint32 length = aPath.Length() - startPos;
2194 
2195  nsresult rv;
2196  PRInt32 value = Substring(aPath, startPos, length).ToInteger(&rv);
2197  NS_ENSURE_SUCCESS(rv, rv);
2198 
2199  value += aToAdd;
2200 
2201  nsAutoString newValue;
2202  newValue.AppendInt(value);
2203  aPath.Replace(startPos, length, newValue);
2204 
2205  return NS_OK;
2206 }
2207 
2208 PRUint32
2209 sbLocalDatabaseSimpleMediaList::CountLevels(const nsAString& aPath)
2210 {
2211  PRUint32 count = 0;
2212  PRInt32 foundpos = aPath.FindChar('.');
2213  while(foundpos >= 0) {
2214  count++;
2215  foundpos = aPath.FindChar('.', foundpos + 1);
2216  }
2217  return count;
2218 }
2219 
2220 nsresult
2221 sbLocalDatabaseSimpleMediaList::CreateQueries()
2222 {
2223  nsresult rv;
2224 
2225  PRUint32 mediaItemId;
2226  rv = GetMediaItemId(&mediaItemId);
2227  NS_ENSURE_SUCCESS(rv, rv);
2228 
2229  // The following builder is shared between queries that operate on the
2230  // items in this list
2231  nsCOMPtr<sbISQLSelectBuilder> builder =
2232  do_CreateInstance(SB_SQLBUILDER_SELECT_CONTRACTID, &rv);
2233  NS_ENSURE_SUCCESS(rv, rv);
2234 
2235  nsCOMPtr<sbISQLBuilderCriterion> criterion;
2236 
2237  rv = builder->SetBaseTableName(NS_LITERAL_STRING("media_items"));
2238  NS_ENSURE_SUCCESS(rv, rv);
2239 
2240  rv = builder->SetBaseTableAlias(NS_LITERAL_STRING("_mi"));
2241  NS_ENSURE_SUCCESS(rv, rv);
2242 
2243  rv = builder->AddJoin(sbISQLSelectBuilder::JOIN_INNER,
2244  NS_LITERAL_STRING("simple_media_lists"),
2245  NS_LITERAL_STRING("_sml"),
2246  NS_LITERAL_STRING("member_media_item_id"),
2247  NS_LITERAL_STRING("_mi"),
2248  NS_LITERAL_STRING("media_item_id"));
2249  NS_ENSURE_SUCCESS(rv, rv);
2250 
2251  rv = builder->CreateMatchCriterionLong(NS_LITERAL_STRING("_sml"),
2252  NS_LITERAL_STRING("media_item_id"),
2254  mediaItemId,
2255  getter_AddRefs(criterion));
2256  NS_ENSURE_SUCCESS(rv, rv);
2257 
2258  rv = builder->AddCriterion(criterion);
2259  NS_ENSURE_SUCCESS(rv, rv);
2260 
2261  // Create get last ordinal query
2262  rv = builder->ClearColumns();
2263  NS_ENSURE_SUCCESS(rv, rv);
2264 
2265  rv = builder->AddColumn(EmptyString(),
2266  NS_LITERAL_STRING("max(ordinal)"));
2267  NS_ENSURE_SUCCESS(rv, rv);
2268 
2269  rv = builder->ToString(mGetLastOrdinalQuery);
2270  NS_ENSURE_SUCCESS(rv, rv);
2271 
2272  // Create get first ordinal query
2273  rv = builder->ClearColumns();
2274  NS_ENSURE_SUCCESS(rv, rv);
2275 
2276  rv = builder->AddColumn(EmptyString(),
2277  NS_LITERAL_STRING("min(ordinal)"));
2278  NS_ENSURE_SUCCESS(rv, rv);
2279 
2280  rv = builder->ToString(mGetFirstOrdinalQuery);
2281  NS_ENSURE_SUCCESS(rv, rv);
2282 
2283  // Create the query used by contains to see if a guid is in this list
2284  rv = builder->ClearColumns();
2285  NS_ENSURE_SUCCESS(rv, rv);
2286 
2287  rv = builder->AddColumn(NS_LITERAL_STRING("_mi"),
2288  NS_LITERAL_STRING("media_item_id"));
2289  NS_ENSURE_SUCCESS(rv, rv);
2290 
2291  rv = builder->CreateMatchCriterionParameter(NS_LITERAL_STRING("_mi"),
2292  NS_LITERAL_STRING("guid"),
2294  getter_AddRefs(criterion));
2295  NS_ENSURE_SUCCESS(rv, rv);
2296 
2297  rv = builder->AddCriterion(criterion);
2298  NS_ENSURE_SUCCESS(rv, rv);
2299 
2300  rv = builder->ToString(mGetMediaItemIdForGuidQuery);
2301  NS_ENSURE_SUCCESS(rv, rv);
2302 
2303  // Create insertion query
2304  nsCOMPtr<sbISQLInsertBuilder> insert =
2305  do_CreateInstance(SB_SQLBUILDER_INSERT_CONTRACTID, &rv);
2306 
2307  rv = insert->SetIntoTableName(NS_LITERAL_STRING("simple_media_lists"));
2308  NS_ENSURE_SUCCESS(rv, rv);
2309 
2310  rv = insert->AddColumn(NS_LITERAL_STRING("media_item_id"));
2311  NS_ENSURE_SUCCESS(rv, rv);
2312 
2313  rv = insert->AddColumn(NS_LITERAL_STRING("member_media_item_id"));
2314  NS_ENSURE_SUCCESS(rv, rv);
2315 
2316  rv = insert->AddColumn(NS_LITERAL_STRING("ordinal"));
2317  NS_ENSURE_SUCCESS(rv, rv);
2318 
2319  rv = insert->AddValueLong(mediaItemId);
2320  NS_ENSURE_SUCCESS(rv, rv);
2321 
2322  rv = insert->AddValueParameter();
2323  NS_ENSURE_SUCCESS(rv, rv);
2324 
2325  rv = insert->AddValueParameter();
2326  NS_ENSURE_SUCCESS(rv, rv);
2327 
2328  rv = insert->ToString(mInsertIntoListQuery);
2329  NS_ENSURE_SUCCESS(rv, rv);
2330 
2331  // Create ordinal update query
2332  nsCOMPtr<sbISQLUpdateBuilder> update =
2333  do_CreateInstance(SB_SQLBUILDER_UPDATE_CONTRACTID, &rv);
2334 
2335  rv = update->SetTableName(NS_LITERAL_STRING("simple_media_lists"));
2336  NS_ENSURE_SUCCESS(rv, rv);
2337 
2338  rv = update->AddAssignmentParameter(NS_LITERAL_STRING("ordinal"));
2339  NS_ENSURE_SUCCESS(rv, rv);
2340 
2341  rv = update->CreateMatchCriterionLong(EmptyString(),
2342  NS_LITERAL_STRING("media_item_id"),
2344  mediaItemId,
2345  getter_AddRefs(criterion));
2346  NS_ENSURE_SUCCESS(rv, rv);
2347 
2348  rv = update->AddCriterion(criterion);
2349  NS_ENSURE_SUCCESS(rv, rv);
2350 
2351  rv = update->CreateMatchCriterionParameter(EmptyString(),
2352  NS_LITERAL_STRING("member_media_item_id"),
2354  getter_AddRefs(criterion));
2355  NS_ENSURE_SUCCESS(rv, rv);
2356 
2357  rv = update->AddCriterion(criterion);
2358  NS_ENSURE_SUCCESS(rv, rv);
2359 
2360  rv = update->CreateMatchCriterionParameter(EmptyString(),
2361  NS_LITERAL_STRING("ordinal"),
2363  getter_AddRefs(criterion));
2364  NS_ENSURE_SUCCESS(rv, rv);
2365 
2366  rv = update->AddCriterion(criterion);
2367  NS_ENSURE_SUCCESS(rv, rv);
2368 
2369  rv = update->ToString(mUpdateListItemOrdinalQuery);
2370  NS_ENSURE_SUCCESS(rv, rv);
2371 
2372  // Create first item delete query
2373  // delete from
2374  // simple_media_lists
2375  // where
2376  // media_item_id = x and
2377  // ordinal in (
2378  // select
2379  // ordinal
2380  // from
2381  // simple_media_lists
2382  // where
2383  // member_media_item_id = ?
2384  // order by ordinal limit 1)
2385  nsCOMPtr<sbISQLDeleteBuilder> deleteb =
2386  do_CreateInstance(SB_SQLBUILDER_DELETE_CONTRACTID, &rv);
2387 
2388  rv = deleteb->SetTableName(NS_LITERAL_STRING("simple_media_lists"));
2389  NS_ENSURE_SUCCESS(rv, rv);
2390 
2391  rv = deleteb->CreateMatchCriterionLong(EmptyString(),
2392  NS_LITERAL_STRING("media_item_id"),
2394  mediaItemId,
2395  getter_AddRefs(criterion));
2396  NS_ENSURE_SUCCESS(rv, rv);
2397 
2398  rv = deleteb->AddCriterion(criterion);
2399  NS_ENSURE_SUCCESS(rv, rv);
2400 
2401  // Build the subquery
2402  nsCOMPtr<sbISQLSelectBuilder> subquery =
2403  do_CreateInstance(SB_SQLBUILDER_SELECT_CONTRACTID, &rv);
2404  NS_ENSURE_SUCCESS(rv, rv);
2405 
2406  rv = subquery->AddColumn(EmptyString(), NS_LITERAL_STRING("rowid"));
2407  NS_ENSURE_SUCCESS(rv, rv);
2408 
2409  rv = subquery->SetBaseTableName(NS_LITERAL_STRING("simple_media_lists"));
2410  NS_ENSURE_SUCCESS(rv, rv);
2411 
2412  rv = subquery->CreateMatchCriterionParameter(EmptyString(),
2413  NS_LITERAL_STRING("member_media_item_id"),
2415  getter_AddRefs(criterion));
2416  NS_ENSURE_SUCCESS(rv, rv);
2417 
2418  rv = subquery->AddCriterion(criterion);
2419  NS_ENSURE_SUCCESS(rv, rv);
2420 
2421  rv = subquery->CreateMatchCriterionLong(EmptyString(),
2422  NS_LITERAL_STRING("media_item_id"),
2424  mediaItemId,
2425  getter_AddRefs(criterion));
2426  NS_ENSURE_SUCCESS(rv, rv);
2427 
2428  rv = subquery->AddCriterion(criterion);
2429  NS_ENSURE_SUCCESS(rv, rv);
2430 
2431  rv = subquery->AddOrder(EmptyString(), NS_LITERAL_STRING("ordinal"), PR_TRUE);
2432  NS_ENSURE_SUCCESS(rv, rv);
2433 
2434  rv = subquery->SetLimit(1);
2435  NS_ENSURE_SUCCESS(rv, rv);
2436 
2437  nsCOMPtr<sbISQLBuilderCriterionIn> inCriterion;
2438  rv = deleteb->CreateMatchCriterionIn(EmptyString(),
2439  NS_LITERAL_STRING("rowid"),
2440  getter_AddRefs(inCriterion));
2441  NS_ENSURE_SUCCESS(rv, rv);
2442 
2443  rv = inCriterion->AddSubquery(subquery);
2444  NS_ENSURE_SUCCESS(rv, rv);
2445 
2446  rv = deleteb->AddCriterion(inCriterion);
2447  NS_ENSURE_SUCCESS(rv, rv);
2448 
2449  rv = deleteb->ToString(mDeleteFirstListItemQuery);
2450  NS_ENSURE_SUCCESS(rv, rv);
2451 
2452  // Create item delete by ordinal query
2453  rv = deleteb->Reset();
2454  NS_ENSURE_SUCCESS(rv, rv);
2455 
2456  rv = deleteb->SetTableName(NS_LITERAL_STRING("simple_media_lists"));
2457  NS_ENSURE_SUCCESS(rv, rv);
2458 
2459  rv = deleteb->CreateMatchCriterionLong(EmptyString(),
2460  NS_LITERAL_STRING("media_item_id"),
2462  mediaItemId,
2463  getter_AddRefs(criterion));
2464  NS_ENSURE_SUCCESS(rv, rv);
2465 
2466  rv = deleteb->AddCriterion(criterion);
2467  NS_ENSURE_SUCCESS(rv, rv);
2468 
2469  rv = deleteb->CreateMatchCriterionParameter(EmptyString(),
2470  NS_LITERAL_STRING("ordinal"),
2472  getter_AddRefs(criterion));
2473  NS_ENSURE_SUCCESS(rv, rv);
2474 
2475  rv = deleteb->AddCriterion(criterion);
2476  NS_ENSURE_SUCCESS(rv, rv);
2477 
2478  rv = deleteb->ToString(mDeleteListItemByOrdinalQuery);
2479  NS_ENSURE_SUCCESS(rv, rv);
2480 
2481  // Create delete all query
2482  rv = deleteb->Reset();
2483  NS_ENSURE_SUCCESS(rv, rv);
2484 
2485  rv = deleteb->SetTableName(NS_LITERAL_STRING("simple_media_lists"));
2486  NS_ENSURE_SUCCESS(rv, rv);
2487 
2488  rv = deleteb->CreateMatchCriterionLong(EmptyString(),
2489  NS_LITERAL_STRING("media_item_id"),
2491  mediaItemId,
2492  getter_AddRefs(criterion));
2493  NS_ENSURE_SUCCESS(rv, rv);
2494 
2495  rv = deleteb->AddCriterion(criterion);
2496  NS_ENSURE_SUCCESS(rv, rv);
2497 
2498  rv = deleteb->ToString(mDeleteAllQuery);
2499  NS_ENSURE_SUCCESS(rv, rv);
2500 
2501  return NS_OK;
2502 }
2503 
2504 nsresult
2505 sbLocalDatabaseSimpleMediaList::NotifyCopyListener(sbIMediaItem *aSourceItem,
2506  sbIMediaItem *aDestItem)
2507 {
2508  NS_ENSURE_ARG_POINTER(aSourceItem);
2509  NS_ENSURE_ARG_POINTER(aDestItem);
2510 
2511  if(mCopyListener) {
2512  return mCopyListener->OnItemCopied(aSourceItem, aDestItem);
2513  }
2514 
2515  return NS_OK;
2516 }
2517 
2518 
2519 NS_IMETHODIMP
2521 {
2522  aProperty.Assign(DEFAULT_SORT_PROPERTY);
2523  return NS_OK;
2524 }
2525 
2526 // nsIClassInfo
2527 NS_IMETHODIMP
2528 sbLocalDatabaseSimpleMediaList::GetInterfaces(PRUint32* count, nsIID*** array)
2529 {
2530  return NS_CI_INTERFACE_GETTER_NAME(sbLocalDatabaseSimpleMediaList)(count, array);
2531 }
2532 
2533 NS_IMETHODIMP
2534 sbLocalDatabaseSimpleMediaList::GetHelperForLanguage(PRUint32 language,
2535  nsISupports** _retval)
2536 {
2537  *_retval = nsnull;
2538  return NS_OK;
2539 }
2540 
2541 NS_IMETHODIMP
2542 sbLocalDatabaseSimpleMediaList::GetContractID(char** aContractID)
2543 {
2544  *aContractID = nsnull;
2545  return NS_OK;
2546 }
2547 
2548 NS_IMETHODIMP
2549 sbLocalDatabaseSimpleMediaList::GetClassDescription(char** aClassDescription)
2550 {
2551  *aClassDescription = nsnull;
2552  return NS_OK;
2553 }
2554 
2555 NS_IMETHODIMP
2556 sbLocalDatabaseSimpleMediaList::GetClassID(nsCID** aClassID)
2557 {
2558  *aClassID = nsnull;
2559  return NS_OK;
2560 }
2561 
2562 NS_IMETHODIMP
2563 sbLocalDatabaseSimpleMediaList::GetImplementationLanguage(PRUint32* aImplementationLanguage)
2564 {
2565  *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
2566  return NS_OK;
2567 }
2568 
2569 NS_IMETHODIMP
2570 sbLocalDatabaseSimpleMediaList::GetFlags(PRUint32 *aFlags)
2571 {
2572  *aFlags = nsIClassInfo::THREADSAFE;
2573  return NS_OK;
2574 }
2575 
2576 NS_IMETHODIMP
2577 sbLocalDatabaseSimpleMediaList::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc)
2578 {
2579  return NS_ERROR_NOT_AVAILABLE;
2580 }
2581 
nsresult GetOriginProperties(sbIMediaItem *aSourceItem, sbIMutablePropertyArray *aProperties)
return foundItem
NS_IMETHOD GetItemByGuid(const nsAString &aGuid, sbIMediaItem **_retval)
sbLocalDatabaseLibrary * mLibrary
void addListener(in sbIMediaListListener aListener, [optional] in boolean aOwnsWeak, [optional] in unsigned long aFlags, [optional] in sbIPropertyArray aPropertyFilter)
Add a listener to this media list.
return NS_OK
_updateCookies aPath
NS_IMETHOD CreateView(sbIMediaListViewState *aState, sbIMediaListView **_retval)
NS_IMETHOD RemoveSome(nsISimpleEnumerator *aMediaItems)
#define SB_SQLBUILDER_UPDATE_CONTRACTID
#define SB_PROPERTY_ORIGINLIBRARYGUID
static sbMediaListEnumSingleItemHelper * New()
_dialogDatepicker pos
void NotifyListenersAfterItemRemoved(sbIMediaList *aList, sbIMediaItem *aItem, PRUint32 aIndex)
Notifies all listeners that an item has been removed from the list.
Interface used to enumerate the items in a media list.
void NotifyListenersBeforeListCleared(sbIMediaList *aList, PRBool aExcludeLists)
Notifies all listeners before the list has been cleared.
onPageChanged aValue
Definition: FeedWriter.js:1395
inArray array
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define SB_ENSURE_INDEX2(_index1, _index2)
boolean contains(in sbIMediaItem aMediaItem)
Check if the list contains a media item.
void NotifyListenersItemAdded(sbIMediaList *aList, sbIMediaItem *aItem, PRUint32 aIndex)
Notifies all listeners that an item has been added to the list.
#define SB_SQLBUILDER_INSERT_CONTRACTID
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
nsresult do_GetProxyForObject(nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
#define SB_MEDIALIST_LOCK_FULLARRAY_AND_ENSURE_MUTABLE()
void SetArray(sbILocalDatabaseGUIDArray *aArray)
NS_IMETHOD AddSome(nsISimpleEnumerator *aMediaItems)
var language
Definition: Info.js:44
A brief description of the contents of this interface.
NS_IMETHOD Contains(sbIMediaItem *aMediaItem, PRBool *_retval)
NS_IMETHOD Add(sbIMediaItem *aMediaItem)
A distinct view on a given media list.
Simple class to make sure we notify listeners that a batch operation has completed every time they ar...
void NotifyListenersItemUpdated(sbIMediaList *aList, sbIMediaItem *aItem, sbIPropertyArray *aProperties)
Notifies all listeners that an item has been updated.
readonly attribute AString guid
The guid of this resource.
nsresult AddSomeAsyncInternal(nsISimpleEnumerator *aMediaItems, nsISupports *aListener, PRUint32 aStartingIndex, nsAString &aStartingOrdinal)
#define SB_SQLBUILDER_DELETE_CONTRACTID
#define TRACE(args)
readonly attribute unsigned long length
Returns the length of the list.
Saved state of a media list view.
#define SB_SQLBUILDER_SELECT_CONTRACTID
NS_IMETHOD AddAll(sbIMediaList *aMediaList)
var count
Definition: test_bug7406.js:32
void NotifyListenersBeforeItemRemoved(sbIMediaList *aList, sbIMediaItem *aItem, PRUint32 aIndex)
Notifies all listeners that an item is about to be removed from the list.
Media lists that implement this interface support custom ordering.
#define SB_PROPERTY_UPDATED
const unsigned short ENUMERATIONTYPE_SNAPSHOT
This flag means that the list being enumerated is a copy that may become out of date.
#define SB_ENSURE_INDEX1(_index)
NS_IMETHOD Remove(sbIMediaItem *aMediaItem)
General interface to data resources.
Interface for use with async methods on sbIMediaList. NOTE: this interface is now deprecated...
#define SB_CONTINUE_IF_FAILED(_rv)
void NotifyListenersListCleared(sbIMediaList *aList, PRBool aExcludeLists)
Notifies all listeners that the list has been cleared.
PRBool sbIsMainLibrary(sbILibrary *aLibrary)
const unsigned short CONTENTTYPE_NONE
These flags specify the contentType of the media list.
function insert(dbq, size, name)
NS_IMETHODIMP_(nsresult) sbVariant
Definition: sbVariant.cpp:1954
const unsigned long JOIN_INNER
NS_IMPL_ISUPPORTS_INHERITED3(sbLocalDatabaseSimpleMediaList, sbLocalDatabaseMediaListBase, nsIClassInfo, sbIOrderableMediaList, sbILocalDatabaseSimpleMediaList) NS_IMPL_CI_INTERFACE_GETTER7(sbLocalDatabaseSimpleMediaList
NS_IMPL_QUERY_INTERFACE1(sbSimpleMediaListInsertingEnumerationListener, sbIMediaListEnumerationListener) NS_IMETHODIMP sbSimpleMediaListInsertingEnumerationListener
NS_IMETHOD AddItem(sbIMediaItem *aMediaItem, sbIMediaItem **aNewMediaItem)
sbILocalDatabaseGUIDArray * GetArray()
void SetCachedListContentType(PRUint16 aContentType)
var uri
Definition: FeedWriter.js:1135
StringArrayEnumerator prototype hasMore
nsresult GetLengthCache(sbILocalDatabaseGUIDArrayLengthCache **aLengthCache)
countRef value
Definition: FeedWriter.js:1423
#define DEFAULT_SORT_PROPERTY
nsresult MakeStandardQuery(sbIDatabaseQuery **_retval)
NS_IMETHOD GetDefaultSortProperty(nsAString &aProperty)
void NotifyListenersBatchEnd(sbIMediaList *aList)
Notifies all listeners that multiple items have been changed.
void NotifyListenersBatchBegin(sbIMediaList *aList)
Notifies all listeners that multiple items are about to be changed.
#define SB_ASYNC_NOTIFICATION_ITEMS
readonly attribute unsigned long mediaItemId
function now()
Interface that defines a single item of media in the system.
NS_DECL_ISUPPORTS sbLocalDatabaseSimpleMediaListAddSomeAsyncRunner(sbLocalDatabaseSimpleMediaList *aLocalDatabaseSimpleMediaList, nsISimpleEnumerator *aMediaItems, nsISupports *aListener, PRUint32 aStartingIndex, const nsAString &aStartingOrdinal)
void NotifyListenersItemMoved(sbIMediaList *aList, PRUint32 aFromIndex, PRUint32 aToIndex)
Notifies all listeners that an item has been moved.
restoreWindow aState
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
window addListener("unload", function(){window.removeListener("unload", arguments.callee);document.purge();if(Browser.Engine.trident){CollectGarbage();}})
#define SB_PROPERTY_ORIGINITEMGUID
NS_DECL_ISUPPORTS NS_DECL_SBIADDMEDIAITEMSLISTENER sbAddSomeEnumListener(nsIArray *aItemsToAdd, nsInterfaceHashtable< nsISupportsHashKey, sbIMediaItem > &aForeignItems)
_getSelectedPageStyle s i
NS_IMETHOD AddMediaItems(nsISimpleEnumerator *aMediaItems, sbIAddMediaItemsListener *aListener, PRBool aAsync)
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define DEFAULT_FETCH_SIZE
const unsigned long MATCH_EQUALS
nsresult GetFilteredPropertiesForNewItem(sbIPropertyArray *aProperties, sbIPropertyArray **_retval)
NS_IMPL_THREADSAFE_ISUPPORTS1(sbAddSomeEnumListener, sbIAddMediaItemsListener)
Songbird Database Object Definition.