32 #include <nsIAppStartupNotifier.h>
33 #include <nsICategoryManager.h>
34 #include <nsIClassInfoImpl.h>
36 #include <nsIMutableArray.h>
37 #include <nsIObserverService.h>
38 #include <nsIProgrammingLanguage.h>
39 #include <nsIStringEnumerator.h>
41 #include <sbIMediaListView.h>
43 #include <nsArrayUtils.h>
44 #include <nsComponentManagerUtils.h>
45 #include <nsDataHashtable.h>
46 #include <nsHashKeys.h>
47 #include <nsTHashtable.h>
49 #include <nsServiceManagerUtils.h>
51 #include <nsXPCOMCID.h>
60 static nsID
const NULL_GUID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0 } };
63 static PRLogModuleInfo* gsbLocalDatabaseDiffingLog = nsnull;
64 # define TRACE(args) \
66 if (!gsbLocalDatabaseDiffingLog) \
67 gsbLocalDatabaseDiffingLog = PR_NewLogModule("sbLocalDatabaseDiffingService"); \
68 PR_LOG(gsbLocalDatabaseDiffingLog, PR_LOG_DEBUG, args); \
72 if (!gsbLocalDatabaseDiffingLog) \
73 gsbLocalDatabaseDiffingLog = PR_NewLogModule("sbLocalDatabaseDiffingService"); \
74 PR_LOG(gsbLocalDatabaseDiffingLog, PR_LOG_WARN, args); \
79 aMediaItem->GetContentSrc(getter_AddRefs(uri));
81 aMediaItem->GetGuid(sourceGUID);
82 nsString sourceOriginGUID;
89 LOG((
"%s\n URL=%s\n ID=%s\n Origin=%s",
92 NS_LossyConvertUTF16toASCII(sourceGUID).BeginReading(),
93 NS_LossyConvertUTF16toASCII(sourceOriginGUID).BeginReading()));
96 # define TRACE(args) PR_BEGIN_MACRO PR_END_MACRO
97 # define LOG(args) PR_BEGIN_MACRO PR_END_MACRO
107 char guidBuffer[NSID_LENGTH];
108 aID.ToProvidedString(guidBuffer);
109 guidBuffer[NSID_LENGTH - 2] =
'\0';
111 retval.AssignLiteral(guidBuffer + 1);
119 nsresult rv = aItem->GetGuid(itemGUID);
122 returnedID.Parse(NS_LossyConvertUTF16toASCII(itemGUID).BeginReading());
130 NS_ASSERTION(aItem,
"aItem is null");
131 NS_ASSERTION(!aProperty.IsEmpty(),
"aProperty is empty");
134 nsresult rv = aItem->GetProperty(aProperty, guid);
135 if (rv == NS_ERROR_NOT_AVAILABLE || guid.IsEmpty()) {
140 returnedID.Parse(NS_LossyConvertUTF16toASCII(guid).BeginReading());
160 return aLeft.
mID.Equals(aRight.
mID) != PR_FALSE;
181 static bool lessThan(nsID
const & aLeftID, nsID
const & aRightID)
183 if (aLeftID.m0 < aRightID.m0) {
186 else if (aLeftID.m0 > aRightID.m0) {
190 if (aLeftID.m1 < aRightID.m1) {
193 else if (aLeftID.m1 > aRightID.m1) {
197 if (aLeftID.m2 < aRightID.m2) {
200 else if (aLeftID.m2 > aRightID.m2) {
204 if (aLeftID.m2 < aRightID.m2) {
205 for (PRUint32 index = 0; index < 8; ++index) {
206 if (aLeftID.m3[index] < aRightID.m3[index]) {
209 else if (aLeftID.m3[index] > aRightID.m3[index]) {
222 typedef nsID
const & (*IDExtractorFunc)(ItemInfos::const_iterator);
232 bool operator()(nsID
const & aID, ItemInfos::const_iterator aRight)
const
237 ItemInfos::const_iterator aRight)
const
239 return lessThan(aLeft->mID, aRight->mID);
245 bool operator()(nsID
const & aID, ItemInfos::iterator aRight)
const
250 ItemInfos::iterator aRight)
const
252 return lessThan(aLeft->mID, aRight->mID);
260 return lessThan(aLeft->mOriginID, aID);
262 bool operator()(nsID
const & aID, ItemInfos::const_iterator aRight)
const
264 return lessThan(aID, aRight->mOriginID);
267 ItemInfos::const_iterator aRight)
const
269 return lessThan(aLeft->mOriginID, aRight->mOriginID);
274 return lessThan(aLeft->mOriginID, aID);
276 bool operator()(nsID
const & aID, ItemInfos::iterator aRight)
const
278 return lessThan(aID, aRight->mOriginID);
281 ItemInfos::iterator aRight)
const
283 return lessThan(aLeft->mOriginID, aRight->mOriginID);
289 NS_DECL_SBIMEDIALISTENUMERATIONLISTENER
307 mIDIndex.
Build(mItemInfos.begin(),
309 mOriginIndex.
Build(mItemInfos.begin(),
313 return mIDIndex.
find(aID);
316 return mIDIndex.
find(aID);
319 return mOriginIndex.
find(aID);
322 return mOriginIndex.
find(aID);
326 return mItemInfos.begin();
330 return mItemInfos.begin();
334 return mItemInfos.end();
338 return mItemInfos.end();
343 return mIDIndex.
begin();
347 return mIDIndex.
begin();
351 return mIDIndex.
end();
355 return mIDIndex.
end();
360 return mOriginIndex.
begin();
364 return mOriginIndex.
begin();
368 return mOriginIndex.
end();
372 return mOriginIndex.
end();
401 sbLDBDSEnumerator::OnEnumerationBegin(
sbIMediaList *aMediaList,
404 NS_ENSURE_ARG_POINTER(aMediaList);
405 NS_ENSURE_ARG_POINTER(_retval);
407 LOG((
"Scanning for items"));
410 nsresult rv = aMediaList->GetLength(&length);
411 NS_ENSURE_SUCCESS(rv, rv);
413 mItemInfos.reserve(length);
422 sbLDBDSEnumerator::OnEnumeratedItem(
sbIMediaList *aMediaList,
426 NS_ENSURE_ARG_POINTER(aMediaList);
427 NS_ENSURE_ARG_POINTER(aMediaItem);
428 NS_ENSURE_ARG_POINTER(_retval);
434 NS_ENSURE_TRUE(!info.mID.Equals(
NULL_GUID), NS_ERROR_FAILURE);
439 if (rv != NS_ERROR_NOT_AVAILABLE) {
440 NS_ENSURE_SUCCESS(rv, rv);
442 PRBool parsed = PR_FALSE;
444 if (!originID.IsEmpty()) {
445 parsed = originGUID.Parse(
446 NS_LossyConvertUTF16toASCII(originID).BeginReading());
449 info.mOriginID = originGUID;
451 info.mPosition = mItemIndex++;
453 nsCOMPtr<nsIURI>
uri;
454 aMediaItem->GetContentSrc(getter_AddRefs(uri));
459 LOG((
" URL=%s\n ID=%s\n Origin=%s",
461 NS_LossyConvertUTF16toASCII(
sbGUIDToString(info.mID)).BeginReading(),
462 NS_LossyConvertUTF16toASCII(
sbGUIDToString(info.mOriginID)).BeginReading()));
464 mItemInfos.push_back(info);
472 sbLDBDSEnumerator::OnEnumerationEnd(
sbIMediaList *aMediaList,
473 nsresult aStatusCode)
475 LOG((
"Scanning complete, sorting"));
496 sbLocalDatabaseDiffingService::sbLocalDatabaseDiffingService()
500 sbLocalDatabaseDiffingService::~sbLocalDatabaseDiffingService()
506 nsIComponentManager* aCompMgr,
508 const char* aLoaderStr,
510 const nsModuleComponentInfo *aInfo)
513 nsCOMPtr<nsICategoryManager> categoryManager =
514 do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
515 NS_ENSURE_SUCCESS(rv, rv);
517 rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY,
523 NS_ENSURE_SUCCESS(rv, rv);
528 template <
class T,
class M>
532 nsID
const id = (**aIter).*aMember;
533 while (aIter != aEnd &&
536 ((**aIter).*aMember).Equals(
id)) {
540 (!((**aIter).*aMember).Equals(
id) ||
551 LOG((
"Marking source and destination"));
569 if (destOriginIter != destOriginEnd) {
571 foundDestID = (*destOriginIter)->mID;
584 if (destIDIter == destIDEnd && !srcIter->mOriginID.Equals(
NULL_GUID)) {
585 destIDIter = aDest->
FindByID(srcIter->mOriginID);
591 if (destIDIter != destIDEnd) {
593 foundDestID = (*destIDIter)->mID;
602 srcIter->mOriginID = foundDestID;
604 LOG((
" Updating src=%s, dest=%s",
605 NS_LossyConvertUTF16toASCII(
607 NS_LossyConvertUTF16toASCII(
613 NS_LossyConvertUTF16toASCII(
625 nsIArray ** aChanges)
627 NS_ENSURE_ARG_POINTER(aSrcList);
628 NS_ENSURE_ARG_POINTER(aDestList);
629 NS_ENSURE_ARG_POINTER(aChanges);
633 LOG((
"Creating changes"));
634 nsCOMPtr<nsIMutableArray> libraryChanges =
635 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
636 NS_ENSURE_SUCCESS(rv, rv);
638 nsCOMPtr<sbIMediaItem> srcItem;
639 nsCOMPtr<sbIMediaItem> destItem;
640 nsCOMPtr<sbILibraryChange> libraryChange;
649 getter_AddRefs(srcItem));
650 if (NS_FAILED(rv) || !srcItem) {
654 switch (srcIter->mAction) {
657 nsCOMPtr<nsIURI>
uri;
658 srcItem->GetContentSrc(getter_AddRefs(uri));
664 NS_LossyConvertUTF16toASCII(
666 spec.BeginReading()));
669 getter_AddRefs(libraryChange));
670 NS_ENSURE_SUCCESS(rv, rv);
676 getter_AddRefs(destItem));
677 if (NS_FAILED(rv) || !destItem) {
681 nsCOMPtr<nsIURI>
uri;
682 srcItem->GetContentSrc(getter_AddRefs(uri));
685 uri->GetSpec(srcSpec);
687 destItem->GetContentSrc(getter_AddRefs(uri));
690 uri->GetSpec(destSpec);
694 NS_LossyConvertUTF16toASCII(
696 srcSpec.BeginReading()));
698 NS_LossyConvertUTF16toASCII(
700 destSpec.BeginReading()));
704 getter_AddRefs(libraryChange));
706 if (rv == NS_ERROR_NOT_AVAILABLE) {
709 NS_ENSURE_SUCCESS(rv, rv);
713 NS_WARNING(
"Unexpected action in diffing source, skipping");
718 rv = libraryChanges->AppendElement(libraryChange, PR_FALSE);
719 NS_ENSURE_SUCCESS(rv, rv);
731 if (destIter->mAction ==
734 getter_AddRefs(destItem));
736 if (rv == NS_ERROR_NOT_AVAILABLE || !destItem) {
739 NS_ENSURE_SUCCESS(rv, rv);
742 nsCOMPtr<nsIURI>
uri;
743 destItem->GetContentSrc(getter_AddRefs(uri));
748 LOG((
" Delete %s-%s",
749 NS_LossyConvertUTF16toASCII(
751 spec.BeginReading()));
754 getter_AddRefs(libraryChange));
755 NS_ENSURE_SUCCESS(rv, rv);
757 rv = libraryChanges->AppendElement(libraryChange, PR_FALSE);
758 NS_ENSURE_SUCCESS(rv, rv);
762 rv = CallQueryInterface(libraryChanges.get(), aChanges);
763 NS_ENSURE_SUCCESS(rv, rv);
774 NS_ENSURE_SUCCESS(rv, rv);
782 NS_ENSURE_ARG_POINTER(aPropertyIDs);
785 nsCOMPtr<nsIStringEnumerator> ids;
788 NS_ENSURE_SUCCESS(rv, rv);
790 ids.forget(aPropertyIDs);
801 NS_ENSURE_ARG_POINTER(aSourceItem);
802 NS_ENSURE_ARG_POINTER(aDestinationItem);
803 NS_ENSURE_ARG_POINTER(aLibraryChange);
805 nsCOMPtr<sbIPropertyArray> sourceProperties;
806 nsCOMPtr<sbIPropertyArray> destinationProperties;
808 nsresult rv = aSourceItem->GetProperties(nsnull,
809 getter_AddRefs(sourceProperties));
810 NS_ENSURE_SUCCESS(rv, rv);
812 rv = aDestinationItem->GetProperties(nsnull,
813 getter_AddRefs(destinationProperties));
814 NS_ENSURE_SUCCESS(rv, rv);
816 nsCOMPtr<nsIArray> propertyChanges;
818 destinationProperties,
819 getter_AddRefs(propertyChanges));
820 if (rv == NS_ERROR_NOT_AVAILABLE) {
821 return NS_ERROR_NOT_AVAILABLE;
823 NS_ENSURE_SUCCESS(rv, rv);
825 nsRefPtr<sbLibraryChange> libraryChange;
826 NS_NEWXPCOM(libraryChange, sbLibraryChange);
827 NS_ENSURE_TRUE(libraryChange, NS_ERROR_OUT_OF_MEMORY);
835 NS_ENSURE_SUCCESS(rv, rv);
837 return CallQueryInterface(libraryChange.get(), aLibraryChange);
845 NS_ENSURE_ARG_POINTER(aSourceItem);
846 NS_ENSURE_ARG_POINTER(aLibraryChange);
848 nsRefPtr<sbLibraryChange> libraryChange;
849 NS_NEWXPCOM(libraryChange, sbLibraryChange);
850 NS_ENSURE_TRUE(libraryChange, NS_ERROR_OUT_OF_MEMORY);
852 nsCOMPtr<sbIPropertyArray> properties;
853 nsresult rv = aSourceItem->GetProperties(nsnull, getter_AddRefs(properties));
854 NS_ENSURE_SUCCESS(rv, rv);
856 nsCOMPtr<nsIMutableArray> propertyChanges =
857 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
858 NS_ENSURE_SUCCESS(rv, rv);
860 PRUint32 propertyCount = 0;
861 rv = properties->GetLength(&propertyCount);
862 NS_ENSURE_SUCCESS(rv, rv);
864 nsString strPropertyID;
865 nsString strPropertyValue;
866 nsCOMPtr<sbIProperty> property;
868 for(PRUint32 current = 0; current < propertyCount; ++current) {
870 rv = properties->GetPropertyAt(current, getter_AddRefs(property));
871 NS_ENSURE_SUCCESS(rv, rv);
873 rv =
property->GetId(strPropertyID);
874 NS_ENSURE_SUCCESS(rv, rv);
876 rv =
property->GetValue(strPropertyValue);
877 NS_ENSURE_SUCCESS(rv, rv);
879 nsRefPtr<sbPropertyChange> propertyChange;
881 NS_ENSURE_TRUE(propertyChange, NS_ERROR_OUT_OF_MEMORY);
887 NS_ENSURE_SUCCESS(rv, rv);
889 nsCOMPtr<nsISupports>
element =
891 NS_ENSURE_SUCCESS(rv, rv);
893 rv = propertyChanges->AppendElement(element,
895 NS_ENSURE_SUCCESS(rv, rv);
904 NS_ENSURE_SUCCESS(rv, rv);
906 return CallQueryInterface(libraryChange.get(), aLibraryChange);
911 PRUint32 aItemOrdinal,
914 NS_ENSURE_ARG_POINTER(aSourceItem);
915 NS_ENSURE_ARG_POINTER(aLibraryChange);
917 nsresult rv = NS_ERROR_UNEXPECTED;
919 nsRefPtr<sbLibraryChange> libraryChange;
920 NS_NEWXPCOM(libraryChange, sbLibraryChange);
921 NS_ENSURE_TRUE(libraryChange, NS_ERROR_OUT_OF_MEMORY);
923 nsCOMPtr<nsIMutableArray> propertyChanges =
924 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
925 NS_ENSURE_SUCCESS(rv, rv);
927 nsRefPtr<sbPropertyChange> propertyChange;
929 NS_ENSURE_TRUE(propertyChange, NS_ERROR_OUT_OF_MEMORY);
931 nsString strPropertyValue;
932 strPropertyValue.AppendInt(aItemOrdinal);
938 NS_ENSURE_SUCCESS(rv, rv);
940 nsCOMPtr<nsISupports>
element =
942 NS_ENSURE_SUCCESS(rv, rv);
944 rv = propertyChanges->AppendElement(element,
946 NS_ENSURE_SUCCESS(rv, rv);
954 NS_ENSURE_SUCCESS(rv, rv);
956 return CallQueryInterface(libraryChange.get(), aLibraryChange);
963 NS_ENSURE_ARG_POINTER(aDestinationItem);
964 NS_ENSURE_ARG_POINTER(aLibraryChange);
966 nsRefPtr<sbLibraryChange> libraryChange;
967 NS_NEWXPCOM(libraryChange, sbLibraryChange);
968 NS_ENSURE_TRUE(libraryChange, NS_ERROR_OUT_OF_MEMORY);
976 NS_ENSURE_SUCCESS(rv, rv);
978 return CallQueryInterface(libraryChange.get(), aLibraryChange);
985 nsIArray **aPropertyChanges)
987 NS_ENSURE_ARG_POINTER(aSourceProperties);
988 NS_ENSURE_ARG_POINTER(aDestinationProperties);
989 NS_ENSURE_ARG_POINTER(aPropertyChanges);
992 nsCOMPtr<nsIMutableArray> propertyChanges =
993 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
994 NS_ENSURE_SUCCESS(rv, rv);
996 PRUint32 sourceLength;
997 rv = aSourceProperties->GetLength(&sourceLength);
998 NS_ENSURE_SUCCESS(rv, rv);
1000 PRUint32 destinationLength;
1001 rv = aDestinationProperties->GetLength(&destinationLength);
1003 nsCOMPtr<sbIProperty> property;
1004 nsTHashtable<nsStringHashKey> sourcePropertyNamesFoundInDestination;
1006 PRBool success = sourcePropertyNamesFoundInDestination.Init();
1007 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1012 nsTHashtable<nsStringHashKey> propertyExclusionList;
1013 success = propertyExclusionList.Init();
1014 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1016 nsStringHashKey* successHashkey =
1018 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1022 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1026 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1030 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1034 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1038 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1044 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1046 nsString propertyId;
1047 nsString propertyValue;
1048 nsString propertyDestinationValue;
1051 for(PRUint32 current = 0; current < sourceLength; ++current)
1053 rv = aSourceProperties->GetPropertyAt(current, getter_AddRefs(property));
1054 NS_ENSURE_SUCCESS(rv, rv);
1056 rv =
property->GetId(propertyId);
1057 NS_ENSURE_SUCCESS(rv, rv);
1059 rv =
property->GetValue(propertyValue);
1060 NS_ENSURE_SUCCESS(rv, rv);
1062 if(propertyExclusionList.GetEntry(propertyId)) {
1066 rv = aDestinationProperties->GetPropertyValue(propertyId,
1067 propertyDestinationValue);
1069 if(rv == NS_ERROR_NOT_AVAILABLE) {
1070 nsRefPtr<sbPropertyChange> propertyChange;
1072 NS_ENSURE_TRUE(propertyChange, NS_ERROR_OUT_OF_MEMORY);
1078 NS_ENSURE_SUCCESS(rv, rv);
1080 nsCOMPtr<nsISupports>
element =
1083 rv = propertyChanges->AppendElement(element,
1085 NS_ENSURE_SUCCESS(rv, rv);
1089 NS_ENSURE_SUCCESS(rv, rv);
1092 successHashkey = sourcePropertyNamesFoundInDestination.PutEntry(propertyId);
1093 NS_ENSURE_TRUE(successHashkey, NS_ERROR_OUT_OF_MEMORY);
1097 rv = aDestinationProperties->GetPropertyValue(
1100 if (NS_SUCCEEDED(rv) && !originURL.IsEmpty()) {
1101 if (propertyValue.Equals(originURL)) {
1109 if (NS_SUCCEEDED(rv)) {
1110 PRUint64
const destDuration =
1114 if (NS_SUCCEEDED(rv)) {
1116 PRInt64 durationDiff = sourceDuration - destDuration;
1117 if ((durationDiff < 0 && -durationDiff < PR_USEC_PER_SEC) ||
1118 durationDiff < PR_USEC_PER_SEC)
1125 if(propertyValue.Equals(propertyDestinationValue)) {
1129 nsRefPtr<sbPropertyChange> propertyChange;
1131 NS_ENSURE_TRUE(propertyChange, NS_ERROR_OUT_OF_MEMORY);
1135 propertyDestinationValue,
1137 NS_ENSURE_SUCCESS(rv, rv);
1139 nsCOMPtr<nsISupports>
element =
1141 rv = propertyChanges->AppendElement(element,
1143 NS_ENSURE_SUCCESS(rv, rv);
1150 for(PRUint32 current = 0; current < destinationLength; ++current) {
1151 rv = aDestinationProperties->GetPropertyAt(current, getter_AddRefs(property));
1152 NS_ENSURE_SUCCESS(rv, rv);
1154 rv =
property->GetId(propertyId);
1155 NS_ENSURE_SUCCESS(rv, rv);
1157 rv =
property->GetValue(propertyDestinationValue);
1158 NS_ENSURE_SUCCESS(rv, rv);
1160 if(propertyExclusionList.GetEntry(propertyId)) {
1164 if(!sourcePropertyNamesFoundInDestination.GetEntry(propertyId)) {
1168 nsRefPtr<sbPropertyChange> propertyChange;
1170 NS_ENSURE_TRUE(propertyChange, NS_ERROR_OUT_OF_MEMORY);
1174 propertyDestinationValue,
1176 NS_ENSURE_SUCCESS(rv, rv);
1178 rv = propertyChanges->AppendElement(NS_ISUPPORTS_CAST(
sbIPropertyChange *, propertyChange),
1180 NS_ENSURE_SUCCESS(rv, rv);
1184 PRUint32 propertyChangesCount = 0;
1185 rv = propertyChanges->GetLength(&propertyChangesCount);
1186 NS_ENSURE_SUCCESS(rv, rv);
1188 if (propertyChangesCount == 0) {
1189 return NS_ERROR_NOT_AVAILABLE;
1192 return CallQueryInterface(propertyChanges.get(), aPropertyChanges);
1201 NS_ENSURE_ARG_POINTER(aSourceList);
1202 NS_ENSURE_ARG_POINTER(aDestinationList);
1203 NS_ENSURE_ARG_POINTER(aLibraryChangeset);
1205 nsRefPtr<sbLibraryChangeset> libraryChangeset;
1206 NS_NEWXPCOM(libraryChangeset, sbLibraryChangeset);
1207 NS_ENSURE_TRUE(libraryChangeset, NS_ERROR_OUT_OF_MEMORY);
1211 nsRefPtr<sbLDBDSEnumerator> sourceEnum;
1213 NS_ENSURE_TRUE(sourceEnum, NS_ERROR_OUT_OF_MEMORY);
1215 nsRefPtr<sbLDBDSEnumerator> destinationEnum;
1217 NS_ENSURE_TRUE(destinationEnum, NS_ERROR_OUT_OF_MEMORY);
1219 rv = aSourceList->EnumerateAllItems(sourceEnum,
1221 NS_ENSURE_SUCCESS(rv, rv);
1223 rv = aDestinationList->EnumerateAllItems(destinationEnum,
1225 NS_ENSURE_SUCCESS(rv, rv);
1229 nsCOMPtr<nsIArray> libraryChanges;
1234 getter_AddRefs(libraryChanges));
1235 NS_ENSURE_SUCCESS(rv, rv);
1237 nsCOMPtr<nsIMutableArray> libraryChangesMutable =
1238 do_QueryInterface(libraryChanges, &rv);
1239 NS_ENSURE_SUCCESS(rv, rv);
1243 PRInt32 listIndex = 0;
1246 sourceIter != sourceEnd;
1252 nsCOMPtr<sbIMediaItem> sourceItem;
1253 rv = aSourceList->GetItemByIndex(sourceIter->mPosition,
1254 getter_AddRefs(sourceItem));
1255 if (NS_SUCCEEDED(rv)) {
1256 nsCOMPtr<sbILibraryChange> libraryChange;
1259 getter_AddRefs(libraryChange));
1260 NS_ENSURE_SUCCESS(rv, rv);
1262 rv = libraryChangesMutable->AppendElement(libraryChange, PR_FALSE);
1263 NS_ENSURE_SUCCESS(rv, rv);
1268 nsCOMPtr<nsIMutableArray> sources =
1269 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1270 NS_ENSURE_SUCCESS(rv, rv);
1272 rv = sources->AppendElement(aSourceList, PR_FALSE);
1273 NS_ENSURE_SUCCESS(rv, rv);
1275 rv = libraryChangeset->InitWithValues(sources,
1278 NS_ENSURE_SUCCESS(rv, rv);
1280 return CallQueryInterface(libraryChangeset.get(), aLibraryChangeset);
1289 NS_ENSURE_ARG_POINTER(aSourceLibrary);
1290 NS_ENSURE_ARG_POINTER(aDestinationLibrary);
1291 NS_ENSURE_ARG_POINTER(aLibraryChangeset);
1295 nsRefPtr<sbLibraryChangeset> libraryChangeset;
1296 NS_NEWXPCOM(libraryChangeset, sbLibraryChangeset);
1297 NS_ENSURE_TRUE(libraryChangeset, NS_ERROR_OUT_OF_MEMORY);
1301 nsRefPtr<sbLDBDSEnumerator> sourceEnum;
1303 NS_ENSURE_TRUE(sourceEnum, NS_ERROR_OUT_OF_MEMORY);
1305 nsRefPtr<sbLDBDSEnumerator> destinationEnum;
1307 NS_ENSURE_TRUE(destinationEnum, NS_ERROR_OUT_OF_MEMORY);
1309 rv = aSourceLibrary->EnumerateAllItems(sourceEnum,
1311 NS_ENSURE_SUCCESS(rv, rv);
1313 rv = aDestinationLibrary->EnumerateAllItems(destinationEnum,
1315 NS_ENSURE_SUCCESS(rv, rv);
1319 nsCOMPtr<nsIArray> libraryChanges;
1321 aDestinationLibrary,
1324 getter_AddRefs(libraryChanges));
1325 NS_ENSURE_SUCCESS(rv, rv);
1328 nsCOMPtr<nsIMutableArray> sources =
1329 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1330 NS_ENSURE_SUCCESS(rv, rv);
1332 rv = sources->AppendElement(aSourceLibrary, PR_FALSE);
1333 NS_ENSURE_SUCCESS(rv, rv);
1335 rv = libraryChangeset->InitWithValues(sources,
1336 aDestinationLibrary,
1338 NS_ENSURE_SUCCESS(rv, rv);
1340 return CallQueryInterface(libraryChangeset.get(), aLibraryChangeset);
1347 NS_ENSURE_SUCCESS(!itemID.Equals(
NULL_GUID), NS_ERROR_FAILURE);
1350 if (!aItems.GetEntry(itemID)) {
1351 nsIDHashKey *hashKey = aItems.PutEntry(itemID);
1352 NS_ENSURE_TRUE(hashKey, NS_ERROR_OUT_OF_MEMORY);
1374 nsCOMPtr<sbIMediaItem> sourceItem;
1378 getter_AddRefs(sourceItem));
1379 NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
1381 nsCOMPtr<sbILibraryChange> libraryChange;
1385 nsCOMPtr<sbIMediaItem> destinationItem;
1390 getter_AddRefs(destinationItem));
1391 NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
1408 getter_AddRefs(destinationItem));
1409 NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
1412 if (destinationItem) {
1417 NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
1419 if (isList.EqualsLiteral(
"1"))
1420 return PL_DHASH_NEXT;
1427 getter_AddRefs(libraryChange));
1430 if (rv == NS_ERROR_NOT_AVAILABLE) {
1431 return PL_DHASH_NEXT;
1433 NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
1440 getter_AddRefs(libraryChange));
1441 NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
1444 NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
1445 return PL_DHASH_NEXT;
1450 nsIArray *aSourceLists,
1454 NS_ENSURE_ARG_POINTER(aSourceLists);
1455 NS_ENSURE_ARG_POINTER(aDestinationLibrary);
1456 NS_ENSURE_ARG_POINTER(aLibraryChangeset);
1459 PRUint32 sourcesLength = 0;
1460 nsresult rv = aSourceLists->GetLength(&sourcesLength);
1461 NS_ENSURE_SUCCESS(rv, rv);
1463 nsCOMPtr<sbIMediaItem> sourceItem;
1464 nsCOMPtr<sbIMediaList> sourceList;
1465 nsCOMPtr<sbILibrary> sourceLibrary;
1467 nsTHashtable<nsIDHashKey> sourceItemIDs;
1468 sourceItemIDs.Init();
1469 for(PRUint32 currentSource = 0;
1470 currentSource < sourcesLength;
1473 sourceItem = do_QueryElementAt(aSourceLists, currentSource, &rv);
1474 NS_ENSURE_SUCCESS(rv, rv);
1478 if (currentSource == 0) {
1479 rv = sourceItem->GetLibrary(getter_AddRefs(sourceLibrary));
1480 NS_ENSURE_SUCCESS(rv, rv);
1485 nsCOMPtr<sbILibrary> testLibrary;
1486 PRBool sameLibrary = PR_FALSE;
1487 rv = sourceItem->GetLibrary(getter_AddRefs(testLibrary));
1488 if (NS_SUCCEEDED(rv)) {
1490 rv = testLibrary->Equals(sourceLibrary, &sameLibrary);
1491 sameLibrary = sameLibrary && NS_SUCCEEDED(rv);
1493 NS_ASSERTION(sameLibrary,
1494 "Source cannot contain items from different libraries");
1497 sourceList = do_QueryInterface(sourceItem, &rv);
1499 if (NS_FAILED(rv)) {
1501 NS_ENSURE_SUCCESS(rv, rv);
1504 PRUint32 sourceLength = 0;
1505 rv = sourceList->GetLength(&sourceLength);
1506 NS_ENSURE_SUCCESS(rv, rv);
1508 for(PRUint32 currentItem = 0; currentItem < sourceLength; ++currentItem) {
1509 rv = sourceList->GetItemByIndex(currentItem,
1510 getter_AddRefs(sourceItem));
1511 NS_ENSURE_SUCCESS(rv, rv);
1515 NS_ENSURE_SUCCESS(rv, rv);
1519 nsCOMPtr<sbILibrary> sourceListIsLibrary = do_QueryInterface(sourceList);
1520 if (!sourceListIsLibrary) {
1523 NS_ENSURE_SUCCESS(rv, rv);
1528 nsRefPtr<sbLibraryChangeset> libraryChangeset;
1529 NS_NEWXPCOM(libraryChangeset, sbLibraryChangeset);
1530 NS_ENSURE_TRUE(libraryChangeset, NS_ERROR_OUT_OF_MEMORY);
1532 nsCOMPtr<nsIMutableArray> libraryChanges =
1533 do_CreateInstance(
"@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1534 NS_ENSURE_SUCCESS(rv, rv);
1536 nsRefPtr<sbLDBDSEnumerator> destinationEnum;
1538 NS_ENSURE_TRUE(destinationEnum, NS_ERROR_OUT_OF_MEMORY);
1540 rv = aDestinationLibrary->EnumerateAllItems(destinationEnum,
1542 NS_ENSURE_SUCCESS(rv, rv);
1552 sourceItemIDs.EnumerateEntries(
Enumerator, &args);
1562 nsCOMPtr<sbIMediaItem> destItem;
1563 rv = aDestinationLibrary->GetItemByGuid(
sbGUIDToString(iter->mID),
1564 getter_AddRefs(destItem));
1566 if (rv == NS_ERROR_NOT_AVAILABLE || !destItem) {
1569 NS_ENSURE_SUCCESS(rv, rv);
1571 nsCOMPtr<sbILibraryChange> libraryChange;
1573 NS_ENSURE_SUCCESS(rv, rv);
1575 rv = libraryChanges->AppendElement(libraryChange, PR_FALSE);
1576 NS_ENSURE_SUCCESS(rv, rv);
1581 rv = libraryChangeset->InitWithValues(aSourceLists,
1582 aDestinationLibrary,
1584 NS_ENSURE_SUCCESS(rv, rv);
1586 return CallQueryInterface(libraryChangeset.get(), aLibraryChangeset);
1590 NS_IMETHODIMP sbLocalDatabaseDiffingService::CreateChangeset(
sbIMediaList *aSource,
1594 NS_ENSURE_ARG_POINTER(aSource);
1595 NS_ENSURE_ARG_POINTER(aDestination);
1596 NS_ENSURE_ARG_POINTER(_retval);
1598 nsCOMPtr<sbILibrary> sourceLibrary = do_QueryInterface(aSource);
1599 nsCOMPtr<sbILibrary> destinationLibrary = do_QueryInterface(aDestination);
1601 nsresult rv = NS_ERROR_FAILURE;
1602 nsCOMPtr<sbILibraryChangeset> changeset;
1604 if(sourceLibrary && destinationLibrary) {
1608 getter_AddRefs(changeset));
1614 getter_AddRefs(changeset));
1617 NS_ENSURE_SUCCESS(rv, rv);
1618 changeset.forget(_retval);
1624 NS_IMETHODIMP sbLocalDatabaseDiffingService::CreateMultiChangeset(nsIArray *aSources,
1628 NS_ENSURE_ARG_POINTER(aSources);
1629 NS_ENSURE_ARG_POINTER(aDestination);
1630 NS_ENSURE_ARG_POINTER(_retval);
1632 nsresult rv = NS_ERROR_UNEXPECTED;
1635 nsCOMPtr<sbILibrary> destinationLibrary =
1636 do_QueryInterface(aDestination);
1637 NS_ENSURE_TRUE(destinationLibrary, NS_ERROR_INVALID_ARG);
1639 nsCOMPtr<sbILibraryChangeset> changeset;
1642 getter_AddRefs(changeset));
1643 NS_ENSURE_SUCCESS(rv, rv);
1645 changeset.forget(_retval);
1651 NS_IMETHODIMP sbLocalDatabaseDiffingService::CreateChangesetAsync(
sbIMediaList *aSource,
1654 nsAString & _retval)
1656 NS_ENSURE_ARG_POINTER(aSource);
1657 NS_ENSURE_ARG_POINTER(aDestination);
1659 return NS_ERROR_NOT_IMPLEMENTED;
1663 NS_IMETHODIMP sbLocalDatabaseDiffingService::CreateMultiChangesetAsync(nsIArray *aSources,
1668 NS_ENSURE_ARG_POINTER(aSources);
1669 NS_ENSURE_ARG_POINTER(aDestination);
1670 NS_ENSURE_ARG_POINTER(_retval);
1672 return NS_ERROR_NOT_IMPLEMENTED;
1676 NS_IMETHODIMP sbLocalDatabaseDiffingService::GetChangeset(
const nsAString & aChangesetCookie,
1679 NS_ENSURE_ARG_POINTER(_retval);
1681 return NS_ERROR_NOT_IMPLEMENTED;
IDIndex::const_iterator ConstOriginIterator
NS_IMPL_THREADSAFE_ISUPPORTS1(sbLDBDSEnumerator, sbIMediaListEnumerationListener) sbLDBDSEnumerator
const unsigned long DELETED
ConstIDIterator IDEnd() const
IDIndex::const_iterator ConstIDIterator
bool operator()(ItemInfos::iterator aLeft, nsID const &aID) const
#define SB_LOCALDATABASE_DIFFINGSERVICE_CONTRACTID
IDIndex::iterator IDIterator
bool operator()(nsID const &aID, ItemInfos::const_iterator aRight) const
#define SB_PROPERTY_ORIGINLIBRARYGUID
bool operator()(nsID const &aID, ItemInfos::iterator aRight) const
#define SB_PROPERTY_ORIGINURL
nsresult CreatePropertyChangesFromProperties(sbIPropertyArray *aSourceProperties, sbIPropertyArray *aDestinationProperties, nsIArray **aPropertyChanges)
OriginIterator OriginEnd()
nsCOMPtr< sbIPropertyManager > mPropertyManager
static NS_METHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
PRUint64 nsString_ToUint64(const nsAString &str, nsresult *rv)
nsresult CreateLibraryChangesetFromLists(sbIMediaList *aSourceList, sbIMediaList *aDestinationList, sbILibraryChangeset **aLibraryChangeset)
nsID GetItemGUID(sbIMediaItem *aItem)
sbILibrary * mSourceLibrary
bool operator()(ItemInfos::const_iterator aLeft, ItemInfos::const_iterator aRight) const
T FindNextUsable(T aIter, T aEnd, M aMember)
Indexes::iterator iterator
nsIMutableArray * mLibraryChanges
Library and media list diffing service.
bool operator()(ItemInfos::iterator aLeft, ItemInfos::iterator aRight) const
nsresult CreateItemDeletedLibraryChange(sbIMediaItem *aDestinationItem, sbILibraryChange **aLibraryChange)
#define SB_PROPERTY_ORDINAL
static bool lessThan(nsID const &aLeftID, nsID const &aRightID)
IDIterator FindByID(nsID const &aID)
bool operator()(ItemInfos::const_iterator aLeft, nsID const &aID) const
nsresult CreateItemMovedLibraryChange(sbIMediaItem *aSourceItem, PRUint32 aItemOrdinal, sbILibraryChange **aLibraryChange)
bool operator()(ItemInfos::iterator aLeft, ItemInfos::iterator aRight) const
sbLibraryChangeset Definition.
static bool CompareID(ItemInfo const &aLeft, ItemInfo const &aRight)
bool operator()(ItemInfos::iterator aLeft, nsID const &aID) const
static nsID const NULL_GUID
std::vector< ItemInfo > ItemInfos
nsresult AddUniqueItem(nsTHashtable< nsIDHashKey > &aItems, sbIMediaItem *aItem)
NS_IMPL_THREADSAFE_RELEASE(sbRequestItem)
NS_IMPL_THREADSAFE_ADDREF(sbRequestItem)
OriginIterator OriginBegin()
ItemInfos::const_iterator const_iterator
#define SB_PROPERTYMANAGER_CONTRACTID
nsresult CreateLibraryChangesetFromLibraries(sbILibrary *aSourceLibrary, sbILibrary *aDestinationLibrary, sbILibraryChangeset **aLibraryChangeset)
void Build(IterT aBegin, IterT aEnd)
const_iterator find(KeyT const &aData) const
bool operator()(ItemInfos::const_iterator aLeft, ItemInfos::const_iterator aRight) const
#define SB_PROPERTY_CONTENTLENGTH
nsresult CreateLibraryChangesetFromListsToLibrary(nsIArray *aSourceLists, sbILibrary *aDestinationLibrary, sbILibraryChangeset **aLibraryChangeset)
sbLDBDSEnumerator * mDestinationEnum
#define SB_PROPERTY_CREATED
sbIndex< nsID, ItemInfos::iterator, IDCompare > IDIndex
#define SB_PROPERTY_UPDATED
OriginIterator FindByOrigin(nsID const &aID)
IDIndex::iterator OriginIterator
ConstOriginIterator FindByOrigin(nsID const &aID) const
const_iterator begin() const
nsresult CreateItemAddedLibraryChange(sbIMediaItem *aSourceItem, sbILibraryChange **aLibraryChange)
nsresult CreateChanges(sbIMediaList *aSrcLibrary, sbIMediaList *aDestLibrary, sbLDBDSEnumerator *aSrcEnum, sbLDBDSEnumerator *aDestEnum, nsIArray **aChanges)
sbIndex< nsID, ItemInfos::iterator, OriginIDCompare > OriginIDIndex
ConstOriginIterator OriginBegin() const
#define SB_PROPERTY_DURATION
nsString sbGUIDToString(nsID const &aID)
const unsigned long MODIFIED
Media library abstraction.
const_iterator end() const
ConstOriginIterator OriginEnd() const
sbLocalDatabaseDiffingService * mDiffService
ItemInfos::iterator iterator
static void MarkLists(sbLDBDSEnumerator *aSrc, sbLDBDSEnumerator *aDest)
const_iterator end() const
const_iterator begin() const
nsID GetGUIDProperty(sbIMediaItem *aItem, nsAString const &aProperty)
#define SB_LOCALDATABASE_DIFFINGSERVICE_DESCRIPTION
nsresult CreateLibraryChangeFromItems(sbIMediaItem *aSourceItem, sbIMediaItem *aDestinationItem, sbILibraryChange **aLibraryChange)
#define SB_PROPERTY_ISLIST
bool operator()(nsID const &aID, ItemInfos::const_iterator aRight) const
#define SB_PROPERTY_CONTENTURL
const unsigned long MOVED
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
static PLDHashOperator Enumerator(nsIDHashKey *aEntry, void *userArg)
#define SB_PROPERTY_ORIGINITEMGUID
sbILibrary * mDestinationLibrary
NS_INTERFACE_MAP_END NS_IMPL_CI_INTERFACE_GETTER1(sbLocalDatabaseDiffingService, sbILibraryDiffingService) sbLocalDatabaseDiffingService
void LogMediaItem(char const *, sbIMediaItem *)
nsresult GetPropertyIDs(nsIStringEnumerator **aPropertyIDs)
Indexes::const_iterator const_iterator
const unsigned long ADDED
ConstIDIterator FindByID(nsID const &aID) const
bool operator()(ItemInfos::const_iterator aLeft, nsID const &aID) const
bool operator()(nsID const &aID, ItemInfos::iterator aRight) const
ConstIDIterator IDBegin() const