sbPlaybackHistoryService.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
28 #ifdef METRICS_ENABLED
29 #include "sbPlaybackMetricsKeys.h"
30 #endif
31 
32 #include <nsIArray.h>
33 #include <nsICategoryManager.h>
34 #include <nsIConverterInputStream.h>
35 #include <nsIInputStream.h>
36 #include <nsILocalFile.h>
37 #include <nsIMutableArray.h>
38 #include <nsIObserverService.h>
39 #include <nsIURL.h>
40 #include <nsIVariant.h>
41 #include <nsIWeakReferenceUtils.h>
42 
43 #include <nsArrayUtils.h>
44 #include <nsAutoLock.h>
45 #include <nsCOMArray.h>
46 #include <nsComponentManagerUtils.h>
47 #include <nsNetUtil.h>
48 #include <nsThreadUtils.h>
49 #include <nsServiceManagerUtils.h>
50 #include <nsXPCOMCID.h>
51 
52 #include <prprf.h>
53 
54 #include <sbILibrary.h>
55 #include <sbILibraryManager.h>
56 #include <sbIMediacoreEvent.h>
57 #include <sbIMediacoreEventTarget.h>
58 #include <sbIMediacoreManager.h>
59 #include <sbIMediaList.h>
60 #include <sbIPlaybackHistoryEntry.h>
61 #include <sbIPropertyArray.h>
62 #include <sbIPropertyInfo.h>
63 #include <sbIPropertyManager.h>
64 #include <sbISQLBuilder.h>
65 
66 #include <DatabaseQuery.h>
67 #include <sbArray.h>
68 #include <sbLibraryCID.h>
69 #include <sbPropertiesCID.h>
70 #include <sbStandardProperties.h>
72 #include <sbSQLBuilderCID.h>
73 #include <sbStringUtils.h>
74 #include <sbDebugUtils.h>
75 
76 #define NS_APPSTARTUP_CATEGORY "app-startup"
77 #define NS_APPSTARTUP_TOPIC "app-startup"
78 
79 #define CONVERTER_BUFFER_SIZE 8192
80 
81 #define PLAYBACKHISTORY_DB_GUID "playbackhistory@songbirdnest.com"
82 #define SCHEMA_URL \
83  "chrome://songbird/content/mediacore/playback/history/playbackhistoryservice.sql"
84 
85 #define PLAYBACKHISTORY_ENTRIES_TABLE "playback_history_entries"
86 #define PLAYBACKHISTORY_ANNOTATIONS_TABLE "playback_history_entry_annotations"
87 #define PLAYBACKHISTORY_PROPERTIES_TABLE "properties"
88 #define PLAYBACKHISTORY_COUNT_ENTRIES "count(entry_id)"
89 
90 #define ENTRY_ID_COLUMN "entry_id"
91 #define LIBRARY_GUID_COLUMN "library_guid"
92 #define MEDIA_ITEM_GUID_COLUMN "media_item_guid"
93 #define PLAY_TIME_COLUMN "play_time"
94 #define PLAY_DURATION_COLUMN "play_duration"
95 
96 #define ENTRY_ID_COLUMN "entry_id"
97 #define PROPERTY_ID_COLUMN "property_id"
98 #define PROPERTY_NAME_COLUMN "property_name"
99 #define OBJ_COLUMN "obj"
100 #define OBJ_SORTABLE "obj_sortable"
101 
102 //------------------------------------------------------------------------------
103 // Support Functions
104 //------------------------------------------------------------------------------
105 static already_AddRefed<nsILocalFile>
107 {
108  nsresult rv;
109  nsCOMPtr<nsIProperties> ds =
110  do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
111  NS_ENSURE_SUCCESS(rv, nsnull);
112 
113  nsILocalFile* file;
114  rv = ds->Get("ProfD", NS_GET_IID(nsILocalFile), (void**)&file);
115  NS_ENSURE_SUCCESS(rv, nsnull);
116 
117  rv = file->AppendRelativePath(NS_LITERAL_STRING("db"));
118  if (NS_FAILED(rv)) {
119  NS_WARNING("AppendRelativePath failed!");
120 
121  NS_RELEASE(file);
122  return nsnull;
123  }
124 
125  return file;
126 }
127 
128 //-----------------------------------------------------------------------------
129 // sbPlaybackHistoryService
130 //-----------------------------------------------------------------------------
134  nsIObserver)
135 
137 : mCurrentlyTracking(PR_FALSE)
138 , mCurrentStartTime(0)
139 , mCurrentPauseTime(0)
140 , mCurrentDelta(0)
141 {
142  MOZ_COUNT_CTOR(sbPlaybackHistoryService);
143 }
144 
146 {
147  MOZ_COUNT_DTOR(sbPlaybackHistoryService);
148 }
149 
150 /*static*/ NS_METHOD
151 sbPlaybackHistoryService::RegisterSelf(nsIComponentManager* aCompMgr,
152  nsIFile* aPath,
153  const char* aLoaderStr,
154  const char* aType,
155  const nsModuleComponentInfo *aInfo)
156 {
157  NS_ENSURE_ARG_POINTER(aCompMgr);
158  NS_ENSURE_ARG_POINTER(aPath);
159  NS_ENSURE_ARG_POINTER(aLoaderStr);
160  NS_ENSURE_ARG_POINTER(aType);
161  NS_ENSURE_ARG_POINTER(aInfo);
162 
163  nsresult rv = NS_ERROR_UNEXPECTED;
164  nsCOMPtr<nsICategoryManager> categoryManager =
165  do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
166  NS_ENSURE_SUCCESS(rv, rv);
167 
168  rv = categoryManager->AddCategoryEntry(NS_APPSTARTUP_CATEGORY,
170  "service,"
172  PR_TRUE, PR_TRUE, nsnull);
173  NS_ENSURE_SUCCESS(rv, rv);
174 
175  return NS_OK;
176 }
177 
178 /* static */ PLDHashOperator PR_CALLBACK
181  void* aUserData)
182 {
183  NS_ASSERTION(aKey, "Null key in hashtable!");
184  NS_ASSERTION(aEntry, "Null entry in hashtable!");
185 
186  nsCOMArray<sbIPlaybackHistoryListener>* array =
187  static_cast<nsCOMArray<sbIPlaybackHistoryListener>*>(aUserData);
188 
189  PRBool success = array->AppendObject(aEntry);
190  NS_ENSURE_TRUE(success, PL_DHASH_STOP);
191 
192  return PL_DHASH_NEXT;
193 }
194 
195 NS_METHOD
197 {
198  nsresult rv = NS_ERROR_UNEXPECTED;
199  nsCOMPtr<nsIObserverService> observerService =
200  do_GetService("@mozilla.org/observer-service;1", &rv);
201  NS_ENSURE_SUCCESS(rv, rv);
202 
203  rv = observerService->AddObserver(this,
205  PR_FALSE);
206  NS_ENSURE_SUCCESS(rv, rv);
207 
208 
209  rv = observerService->AddObserver(this,
211  PR_FALSE);
212  NS_ENSURE_SUCCESS(rv, rv);
213 
214  mMonitor = nsAutoMonitor::NewMonitor("sbPlaybackHistoryService::mMonitor");
215  NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
216 
217  rv = CreateQueries();
218  NS_ENSURE_SUCCESS(rv, rv);
219 
220  PRBool success = mLibraries.Init();
221  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
222 
223  success = mListeners.Init();
224  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
225 
226  success = mPropertyDBIDToID.Init();
227  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
228 
229  success = mPropertyIDToDBID.Init();
230  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
231 
232  nsCOMPtr<nsISupportsWeakReference> weakRef =
233  do_GetService(SB_MEDIACOREMANAGER_CONTRACTID, &rv);
234  NS_ENSURE_SUCCESS(rv, rv);
235 
236  rv = weakRef->GetWeakReference(getter_AddRefs(mMediacoreManager));
237  NS_ENSURE_SUCCESS(rv, rv);
238 
239  nsCOMPtr<sbIMediacoreEventTarget> eventTarget =
240  do_QueryReferent(mMediacoreManager, &rv);
241  NS_ENSURE_SUCCESS(rv, rv);
242 
243  rv = eventTarget->AddListener(this);
244  NS_ENSURE_SUCCESS(rv, rv);
245 
246 #ifdef METRICS_ENABLED
247  mMetrics = do_ProxiedCreateInstance("@songbirdnest.com/Songbird/Metrics;1",
248  &rv);
249  NS_ENSURE_SUCCESS(rv, rv);
250 #endif
251 
252  return NS_OK;
253 }
254 
255 nsresult
257 {
258  nsresult rv = NS_ERROR_UNEXPECTED;
259 
260  NS_NAMED_LITERAL_STRING(playbackHistoryEntriesTableName,
262 
263  NS_NAMED_LITERAL_STRING(playbackHistoryAnnotationsTableName,
265 
266  NS_NAMED_LITERAL_STRING(playbackHistoryCountEntries,
268 
269  NS_NAMED_LITERAL_STRING(entryIdColumn, ENTRY_ID_COLUMN);
270  NS_NAMED_LITERAL_STRING(libraryGuidColumn, LIBRARY_GUID_COLUMN);
271  NS_NAMED_LITERAL_STRING(mediaItemGuidColumn, MEDIA_ITEM_GUID_COLUMN);
272  NS_NAMED_LITERAL_STRING(playTimeColumn, PLAY_TIME_COLUMN);
273  NS_NAMED_LITERAL_STRING(playDurationColumn, PLAY_DURATION_COLUMN);
274 
275  NS_NAMED_LITERAL_STRING(propertiesTableName,
277 
278  NS_NAMED_LITERAL_STRING(propertyIdColumn, PROPERTY_ID_COLUMN);
279  NS_NAMED_LITERAL_STRING(propertyNameColumn, PROPERTY_NAME_COLUMN);
280  NS_NAMED_LITERAL_STRING(objColumn, OBJ_COLUMN);
281  NS_NAMED_LITERAL_STRING(objSortableColumn, OBJ_SORTABLE);
282 
283  nsCOMPtr<sbISQLInsertBuilder> insertBuilder =
284  do_CreateInstance(SB_SQLBUILDER_INSERT_CONTRACTID, &rv);
285  NS_ENSURE_SUCCESS(rv, rv);
286 
287  // Query for Inserting new Playback History Entries.
288  rv = insertBuilder->SetIntoTableName(playbackHistoryEntriesTableName);
289  NS_ENSURE_SUCCESS(rv, rv);
290 
291  rv = insertBuilder->AddColumn(libraryGuidColumn);
292  NS_ENSURE_SUCCESS(rv, rv);
293 
294  rv = insertBuilder->AddColumn(mediaItemGuidColumn);
295  NS_ENSURE_SUCCESS(rv, rv);
296 
297  rv = insertBuilder->AddColumn(playTimeColumn);
298  NS_ENSURE_SUCCESS(rv, rv);
299 
300  rv = insertBuilder->AddColumn(playDurationColumn);
301  NS_ENSURE_SUCCESS(rv, rv);
302 
303  rv = insertBuilder->AddValueParameter();
304  NS_ENSURE_SUCCESS(rv, rv);
305 
306  rv = insertBuilder->AddValueParameter();
307  NS_ENSURE_SUCCESS(rv, rv);
308 
309  rv = insertBuilder->AddValueParameter();
310  NS_ENSURE_SUCCESS(rv, rv);
311 
312  rv = insertBuilder->AddValueParameter();
313  NS_ENSURE_SUCCESS(rv, rv);
314 
315  rv = insertBuilder->ToString(mAddEntryQuery);
316  NS_ENSURE_SUCCESS(rv, rv);
317 
318  rv = insertBuilder->Reset();
319  NS_ENSURE_SUCCESS(rv, rv);
320 
321  // Query for Inserting Annotations
322  rv = insertBuilder->Reset();
323  NS_ENSURE_SUCCESS(rv, rv);
324 
325  rv = insertBuilder->SetIntoTableName(playbackHistoryAnnotationsTableName);
326  NS_ENSURE_SUCCESS(rv, rv);
327 
328  rv = insertBuilder->AddColumn(entryIdColumn);
329  NS_ENSURE_SUCCESS(rv, rv);
330 
331  rv = insertBuilder->AddValueRaw(NS_LITERAL_STRING("(select entry_id from playback_history_entries where library_guid = ? AND media_item_guid = ? AND play_time = ?)"));
332  NS_ENSURE_SUCCESS(rv, rv);
333 
334  rv = insertBuilder->AddColumn(propertyIdColumn);
335  NS_ENSURE_SUCCESS(rv, rv);
336 
337  rv = insertBuilder->AddValueParameter();
338  NS_ENSURE_SUCCESS(rv, rv);
339 
340  rv = insertBuilder->AddColumn(objColumn);
341  NS_ENSURE_SUCCESS(rv, rv);
342 
343  rv = insertBuilder->AddValueParameter();
344  NS_ENSURE_SUCCESS(rv, rv);
345 
346  rv = insertBuilder->AddColumn(objSortableColumn);
347  NS_ENSURE_SUCCESS(rv, rv);
348 
349  rv = insertBuilder->AddValueParameter();
350  NS_ENSURE_SUCCESS(rv, rv);
351 
352  rv = insertBuilder->ToString(mAddAnnotationQuery);
353  NS_ENSURE_SUCCESS(rv, rv);
354 
355  // Query to insert annotations
356  mInsertAnnotationQuery.AssignLiteral("insert into ");
357  mInsertAnnotationQuery.Append(playbackHistoryAnnotationsTableName);
358  mInsertAnnotationQuery.AppendLiteral(" (");
359 
360  mInsertAnnotationQuery.Append(entryIdColumn);
361  mInsertAnnotationQuery.AppendLiteral(",");
362 
363  mInsertAnnotationQuery.Append(propertyIdColumn);
364  mInsertAnnotationQuery.AppendLiteral(",");
365 
366  mInsertAnnotationQuery.Append(objColumn);
367  mInsertAnnotationQuery.AppendLiteral(",");
368 
369  mInsertAnnotationQuery.Append(objSortableColumn);
370 
371  mInsertAnnotationQuery.AppendLiteral(" )");
372  mInsertAnnotationQuery.AppendLiteral(" values (?, ?, ?, ?)");
373 
374  // Query to update an annotation
375  mUpdateAnnotationQuery.AssignLiteral("update ");
376  mUpdateAnnotationQuery.Append(playbackHistoryAnnotationsTableName);
377  mUpdateAnnotationQuery.AppendLiteral(" set ");
378 
379  mUpdateAnnotationQuery.Append(propertyIdColumn);
380  mUpdateAnnotationQuery.AppendLiteral(" = ?, ");
381 
382  mUpdateAnnotationQuery.Append(objColumn);
383  mUpdateAnnotationQuery.AppendLiteral(" = ?, ");
384 
385  mUpdateAnnotationQuery.Append(objSortableColumn);
386  mUpdateAnnotationQuery.AppendLiteral(" = ? ");
387 
388  mUpdateAnnotationQuery.AppendLiteral(" where entry_id = ?");
389 
390  // Query to remove an annotation
391  mRemoveAnnotationQuery.AssignLiteral("delete from ");
392  mRemoveAnnotationQuery.Append(playbackHistoryAnnotationsTableName);
393  mRemoveAnnotationQuery.AppendLiteral(" where entry_id = ? AND property_id = ?");
394 
395  // Query to figure out if an annotation is present already or not.
396  mIsAnnotationPresentQuery.AssignLiteral("select entry_id from ");
397  mIsAnnotationPresentQuery.Append(playbackHistoryAnnotationsTableName);
398  mIsAnnotationPresentQuery.AppendLiteral(" where entry_id = ? and property_id = ?");
399 
400  // Query for Entry Count
401  nsCOMPtr<sbISQLSelectBuilder> selectBuilder =
402  do_CreateInstance(SB_SQLBUILDER_SELECT_CONTRACTID, &rv);
403  NS_ENSURE_SUCCESS(rv, rv);
404 
405  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
406  NS_ENSURE_SUCCESS(rv, rv);
407 
408  rv = selectBuilder->AddColumn(EmptyString(), playbackHistoryCountEntries);
409  NS_ENSURE_SUCCESS(rv, rv);
410 
411  rv = selectBuilder->ToString(mGetEntryCountQuery);
412  NS_ENSURE_SUCCESS(rv, rv);
413 
414  // Query for inserting a property dbid for a property id.
415  rv = insertBuilder->Reset();
416  NS_ENSURE_SUCCESS(rv, rv);
417 
418  rv = insertBuilder->SetIntoTableName(propertiesTableName);
419  NS_ENSURE_SUCCESS(rv, rv);
420 
421  rv = insertBuilder->AddColumn(propertyNameColumn);
422  NS_ENSURE_SUCCESS(rv, rv);
423 
424  rv = insertBuilder->AddValueParameter();
425  NS_ENSURE_SUCCESS(rv, rv);
426 
427  rv = insertBuilder->ToString(mInsertPropertyIDQuery);
428  NS_ENSURE_SUCCESS(rv, rv);
429 
430  // Query for Getting Entries by Index
431  rv = selectBuilder->Reset();
432  NS_ENSURE_SUCCESS(rv, rv);
433 
434  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
435  NS_ENSURE_SUCCESS(rv, rv);
436 
437  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
438  NS_ENSURE_SUCCESS(rv, rv);
439 
440  rv = selectBuilder->AddColumn(EmptyString(), libraryGuidColumn);
441  NS_ENSURE_SUCCESS(rv, rv);
442 
443  rv = selectBuilder->AddColumn(EmptyString(), mediaItemGuidColumn);
444  NS_ENSURE_SUCCESS(rv, rv);
445 
446  rv = selectBuilder->AddColumn(EmptyString(), playTimeColumn);
447  NS_ENSURE_SUCCESS(rv, rv);
448 
449  rv = selectBuilder->AddColumn(EmptyString(), playDurationColumn);
450  NS_ENSURE_SUCCESS(rv, rv);
451 
452  rv = selectBuilder->AddOrder(EmptyString(), playTimeColumn, PR_FALSE);
453  NS_ENSURE_SUCCESS(rv, rv);
454 
455  rv = selectBuilder->SetLimitIsParameter(PR_TRUE);
456  NS_ENSURE_SUCCESS(rv, rv);
457 
458  rv = selectBuilder->SetOffsetIsParameter(PR_TRUE);
459  NS_ENSURE_SUCCESS(rv, rv);
460 
461  rv = selectBuilder->ToString(mGetEntriesByIndexQuery);
462  NS_ENSURE_SUCCESS(rv, rv);
463 
464  // Query for Getting Entries by Index, Ascending.
465  rv = selectBuilder->Reset();
466  NS_ENSURE_SUCCESS(rv, rv);
467 
468  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
469  NS_ENSURE_SUCCESS(rv, rv);
470 
471  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
472  NS_ENSURE_SUCCESS(rv, rv);
473 
474  rv = selectBuilder->AddColumn(EmptyString(), libraryGuidColumn);
475  NS_ENSURE_SUCCESS(rv, rv);
476 
477  rv = selectBuilder->AddColumn(EmptyString(), mediaItemGuidColumn);
478  NS_ENSURE_SUCCESS(rv, rv);
479 
480  rv = selectBuilder->AddColumn(EmptyString(), playTimeColumn);
481  NS_ENSURE_SUCCESS(rv, rv);
482 
483  rv = selectBuilder->AddColumn(EmptyString(), playDurationColumn);
484  NS_ENSURE_SUCCESS(rv, rv);
485 
486  rv = selectBuilder->AddOrder(EmptyString(), playTimeColumn, PR_TRUE);
487  NS_ENSURE_SUCCESS(rv, rv);
488 
489  rv = selectBuilder->SetLimitIsParameter(PR_TRUE);
490  NS_ENSURE_SUCCESS(rv, rv);
491 
492  rv = selectBuilder->SetOffsetIsParameter(PR_TRUE);
493  NS_ENSURE_SUCCESS(rv, rv);
494 
495  rv = selectBuilder->ToString(mGetEntriesByIndexQueryAscending);
496  NS_ENSURE_SUCCESS(rv, rv);
497 
498  rv = selectBuilder->Reset();
499  NS_ENSURE_SUCCESS(rv, rv);
500 
501  // Query for Getting Entries by Timestamp
502  rv = selectBuilder->Reset();
503  NS_ENSURE_SUCCESS(rv, rv);
504 
505  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
506  NS_ENSURE_SUCCESS(rv, rv);
507 
508  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
509  NS_ENSURE_SUCCESS(rv, rv);
510 
511  rv = selectBuilder->AddColumn(EmptyString(), libraryGuidColumn);
512  NS_ENSURE_SUCCESS(rv, rv);
513 
514  rv = selectBuilder->AddColumn(EmptyString(), mediaItemGuidColumn);
515  NS_ENSURE_SUCCESS(rv, rv);
516 
517  rv = selectBuilder->AddColumn(EmptyString(), playTimeColumn);
518  NS_ENSURE_SUCCESS(rv, rv);
519 
520  rv = selectBuilder->AddColumn(EmptyString(), playDurationColumn);
521  NS_ENSURE_SUCCESS(rv, rv);
522 
523  rv = selectBuilder->AddOrder(EmptyString(), playTimeColumn, PR_FALSE);
524  NS_ENSURE_SUCCESS(rv, rv);
525 
526  nsCOMPtr<sbISQLBuilderCriterion> criterionPlayTimeMin;
527  rv = selectBuilder->CreateMatchCriterionParameter(
528  EmptyString(),
529  playTimeColumn,
531  getter_AddRefs(criterionPlayTimeMin));
532  NS_ENSURE_SUCCESS(rv, rv);
533 
534  nsCOMPtr<sbISQLBuilderCriterion> criterionPlayTimeMax;
535  rv = selectBuilder->CreateMatchCriterionParameter(
536  EmptyString(),
537  playTimeColumn,
539  getter_AddRefs(criterionPlayTimeMax));
540  NS_ENSURE_SUCCESS(rv, rv);
541 
542  nsCOMPtr<sbISQLBuilderCriterion> criterionPlayTimeRange;
543  rv = selectBuilder->CreateAndCriterion(criterionPlayTimeMin,
544  criterionPlayTimeMax,
545  getter_AddRefs(criterionPlayTimeRange));
546  NS_ENSURE_SUCCESS(rv, rv);
547 
548  rv = selectBuilder->AddCriterion(criterionPlayTimeRange);
549  NS_ENSURE_SUCCESS(rv, rv);
550 
551  rv = selectBuilder->ToString(mGetEntriesByTimestampQuery);
552  NS_ENSURE_SUCCESS(rv, rv);
553 
554  // Query for Getting Entries by Timestamp, Ascending.
555  rv = selectBuilder->Reset();
556  NS_ENSURE_SUCCESS(rv, rv);
557 
558  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
559  NS_ENSURE_SUCCESS(rv, rv);
560 
561  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
562  NS_ENSURE_SUCCESS(rv, rv);
563 
564  rv = selectBuilder->AddColumn(EmptyString(), libraryGuidColumn);
565  NS_ENSURE_SUCCESS(rv, rv);
566 
567  rv = selectBuilder->AddColumn(EmptyString(), mediaItemGuidColumn);
568  NS_ENSURE_SUCCESS(rv, rv);
569 
570  rv = selectBuilder->AddColumn(EmptyString(), playTimeColumn);
571  NS_ENSURE_SUCCESS(rv, rv);
572 
573  rv = selectBuilder->AddColumn(EmptyString(), playDurationColumn);
574  NS_ENSURE_SUCCESS(rv, rv);
575 
576  rv = selectBuilder->AddOrder(EmptyString(), playTimeColumn, PR_FALSE);
577  NS_ENSURE_SUCCESS(rv, rv);
578 
579  rv = selectBuilder->AddCriterion(criterionPlayTimeRange);
580  NS_ENSURE_SUCCESS(rv, rv);
581 
582  rv = selectBuilder->ToString(mGetEntriesByTimestampQueryAscending);
583  NS_ENSURE_SUCCESS(rv, rv);
584 
585  // Query for Getting All Entries
586  rv = selectBuilder->Reset();
587  NS_ENSURE_SUCCESS(rv, rv);
588 
589  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
590  NS_ENSURE_SUCCESS(rv, rv);
591 
592  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
593  NS_ENSURE_SUCCESS(rv, rv);
594 
595  rv = selectBuilder->AddColumn(EmptyString(), libraryGuidColumn);
596  NS_ENSURE_SUCCESS(rv, rv);
597 
598  rv = selectBuilder->AddColumn(EmptyString(), mediaItemGuidColumn);
599  NS_ENSURE_SUCCESS(rv, rv);
600 
601  rv = selectBuilder->AddColumn(EmptyString(), playTimeColumn);
602  NS_ENSURE_SUCCESS(rv, rv);
603 
604  rv = selectBuilder->AddColumn(EmptyString(), playDurationColumn);
605  NS_ENSURE_SUCCESS(rv, rv);
606 
607  rv = selectBuilder->AddOrder(EmptyString(), playTimeColumn, PR_FALSE);
608  NS_ENSURE_SUCCESS(rv, rv);
609 
610  rv = selectBuilder->ToString(mGetAllEntriesQuery);
611  NS_ENSURE_SUCCESS(rv, rv);
612 
613  // Query for Getting All Annotations Related to an Entry Id.
614  rv = selectBuilder->Reset();
615  NS_ENSURE_SUCCESS(rv, rv);
616 
617  rv = selectBuilder->SetBaseTableName(playbackHistoryAnnotationsTableName);
618  NS_ENSURE_SUCCESS(rv, rv);
619 
620  rv = selectBuilder->AddColumn(EmptyString(), propertyIdColumn);
621  NS_ENSURE_SUCCESS(rv, rv);
622 
623  rv = selectBuilder->AddColumn(EmptyString(), objColumn);
624  NS_ENSURE_SUCCESS(rv, rv);
625 
626  nsCOMPtr<sbISQLBuilderCriterion> criterionEntryId;
627  rv = selectBuilder->CreateMatchCriterionParameter(
628  EmptyString(),
629  entryIdColumn,
631  getter_AddRefs(criterionEntryId));
632  NS_ENSURE_SUCCESS(rv, rv);
633 
634  rv = selectBuilder->AddCriterion(criterionEntryId);
635  NS_ENSURE_SUCCESS(rv, rv);
636 
637  rv = selectBuilder->ToString(mGetAnnotationsForEntryQuery);
638  NS_ENSURE_SUCCESS(rv, rv);
639 
640  // Query for Deleting Entries by Index
641  nsCOMPtr<sbISQLDeleteBuilder> deleteBuilder =
642  do_CreateInstance(SB_SQLBUILDER_DELETE_CONTRACTID, &rv);
643  NS_ENSURE_SUCCESS(rv, rv);
644 
645  rv = deleteBuilder->SetTableName(playbackHistoryEntriesTableName);
646  NS_ENSURE_SUCCESS(rv, rv);
647 
648  nsCOMPtr<sbISQLBuilderCriterionIn> criterionIn;
649  rv = deleteBuilder->CreateMatchCriterionIn(EmptyString(),
650  entryIdColumn,
651  getter_AddRefs(criterionIn));
652  NS_ENSURE_SUCCESS(rv, rv);
653 
654  rv = selectBuilder->Reset();
655  NS_ENSURE_SUCCESS(rv, rv);
656 
657  rv = selectBuilder->SetBaseTableName(playbackHistoryEntriesTableName);
658  NS_ENSURE_SUCCESS(rv, rv);
659 
660  rv = selectBuilder->AddColumn(EmptyString(), entryIdColumn);
661  NS_ENSURE_SUCCESS(rv, rv);
662 
663  nsCOMPtr<sbISQLBuilderCriterion> criterionLibraryGuid;
664  rv = selectBuilder->CreateMatchCriterionParameter(
665  EmptyString(),
666  libraryGuidColumn,
668  getter_AddRefs(criterionLibraryGuid));
669  NS_ENSURE_SUCCESS(rv, rv);
670 
671  nsCOMPtr<sbISQLBuilderCriterion> criterionMediaItemGuid;
672  rv = selectBuilder->CreateMatchCriterionParameter(
673  EmptyString(),
674  mediaItemGuidColumn,
676  getter_AddRefs(criterionMediaItemGuid));
677  NS_ENSURE_SUCCESS(rv, rv);
678 
679  nsCOMPtr<sbISQLBuilderCriterion> criterionPlayTime;
680  rv = selectBuilder->CreateMatchCriterionParameter(
681  EmptyString(),
682  playTimeColumn,
684  getter_AddRefs(criterionPlayTime));
685  NS_ENSURE_SUCCESS(rv, rv);
686 
687  nsCOMPtr<sbISQLBuilderCriterion> criterionLeft;
688  rv = selectBuilder->CreateAndCriterion(criterionLibraryGuid,
689  criterionMediaItemGuid,
690  getter_AddRefs(criterionLeft));
691  NS_ENSURE_SUCCESS(rv, rv);
692 
693  nsCOMPtr<sbISQLBuilderCriterion> criterionRight;
694  rv = selectBuilder->CreateAndCriterion(criterionLeft,
695  criterionPlayTime,
696  getter_AddRefs(criterionRight));
697  NS_ENSURE_SUCCESS(rv, rv);
698 
699  rv = selectBuilder->AddCriterion(criterionRight);
700  NS_ENSURE_SUCCESS(rv, rv);
701 
702  rv = criterionIn->AddSubquery(selectBuilder);
703  NS_ENSURE_SUCCESS(rv, rv);
704 
705  rv = deleteBuilder->AddCriterion(criterionIn);
706  NS_ENSURE_SUCCESS(rv, rv);
707 
708  rv = deleteBuilder->ToString(mRemoveEntriesQuery);
709  NS_ENSURE_SUCCESS(rv, rv);
710 
711  // Query for Deleting Annotations
712  rv = deleteBuilder->Reset();
713  NS_ENSURE_SUCCESS(rv, rv);
714 
715  rv = deleteBuilder->SetTableName(playbackHistoryEntriesTableName);
716  NS_ENSURE_SUCCESS(rv, rv);
717 
718  rv = selectBuilder->CreateMatchCriterionParameter(
719  EmptyString(),
720  entryIdColumn,
722  getter_AddRefs(criterionEntryId));
723  NS_ENSURE_SUCCESS(rv, rv);
724 
725  rv = deleteBuilder->AddCriterion(criterionEntryId);
726  NS_ENSURE_SUCCESS(rv, rv);
727 
728  rv = deleteBuilder->ToString(mRemoveAnnotationsQuery);
729  NS_ENSURE_SUCCESS(rv, rv);
730 
731  // Query for Deleting All Entries
732  rv = deleteBuilder->Reset();
733  NS_ENSURE_SUCCESS(rv, rv);
734 
735  rv = deleteBuilder->SetTableName(playbackHistoryEntriesTableName);
736  NS_ENSURE_SUCCESS(rv, rv);
737 
738  rv = deleteBuilder->ToString(mRemoveAllEntriesQuery);
739  NS_ENSURE_SUCCESS(rv, rv);
740 
741  // Query for Deleting All Annotations
742  rv = deleteBuilder->Reset();
743  NS_ENSURE_SUCCESS(rv, rv);
744 
745  rv = deleteBuilder->SetTableName(playbackHistoryAnnotationsTableName);
746  NS_ENSURE_SUCCESS(rv, rv);
747 
748  rv = deleteBuilder->ToString(mRemoveAllAnnotationsQuery);
749  NS_ENSURE_SUCCESS(rv, rv);
750 
751  return NS_OK;
752 }
753 
754 nsresult
756 {
757  NS_ENSURE_ARG_POINTER(aQuery);
758 
759  NS_NAMED_LITERAL_STRING(playbackHistoryDatabaseGUID,
761 
762  nsresult rv = NS_ERROR_UNEXPECTED;
763  nsCOMPtr<sbIDatabaseQuery> query =
764  do_CreateInstance(SONGBIRD_DATABASEQUERY_CONTRACTID, &rv);
765  NS_ENSURE_SUCCESS(rv, rv);
766 
767  rv = query->SetAsyncQuery(PR_FALSE);
768  NS_ENSURE_SUCCESS(rv, rv);
769 
770  rv = query->SetDatabaseGUID(playbackHistoryDatabaseGUID);
771  NS_ENSURE_SUCCESS(rv, rv);
772 
773  query.forget(aQuery);
774 
775  return NS_OK;
776 }
777 
778 nsresult
780  PRInt64 aEntryId,
781  sbIPropertyArray **aAnnotations)
782 {
783  NS_ENSURE_ARG_POINTER(aAnnotations);
784  NS_ENSURE_ARG(aEntryId != -1);
785 
786  nsCOMPtr<sbIDatabaseQuery> query;
787  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
788  NS_ENSURE_SUCCESS(rv, rv);
789 
790  rv = query->AddQuery(mGetAnnotationsForEntryQuery);
791  NS_ENSURE_SUCCESS(rv, rv);
792 
793  rv = query->BindInt64Parameter(0, aEntryId);
794  NS_ENSURE_SUCCESS(rv, rv);
795 
796  PRInt32 dbOk = 0;
797  rv = query->Execute(&dbOk);
798  NS_ENSURE_SUCCESS(rv, rv);
799  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
800 
801  nsCOMPtr<sbIDatabaseResult> result;
802  rv = query->GetResultObject(getter_AddRefs(result));
803  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
804 
805  PRUint32 rowCount = 0;
806  rv = result->GetRowCount(&rowCount);
807  NS_ENSURE_SUCCESS(rv, rv);
808 
809  nsCOMPtr<sbIMutablePropertyArray> annotations =
810  do_CreateInstance(SB_MUTABLEPROPERTYARRAY_CONTRACTID, &rv);
811  NS_ENSURE_SUCCESS(rv, rv);
812 
813  for(PRUint32 current = 0; current < rowCount; ++current) {
814  nsString propertyDBIDStr;
815  rv = result->GetRowCell(current, 0, propertyDBIDStr);
816  NS_ENSURE_SUCCESS(rv, rv);
817 
818  nsString annotationValue;
819  rv = result->GetRowCell(current, 1, annotationValue);
820  NS_ENSURE_SUCCESS(rv, rv);
821 
822  PRUint32 propertyId = propertyDBIDStr.ToInteger(&rv);
823  NS_ENSURE_SUCCESS(rv, rv);
824 
825  nsString annotationId;
826  PRBool success = mPropertyDBIDToID.Get(propertyId, &annotationId);
827  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
828 
829  rv = annotations->AppendProperty(annotationId, annotationValue);
830  NS_ENSURE_SUCCESS(rv, rv);
831  }
832 
833  nsCOMPtr<sbIPropertyArray> immutableAnnotations =
834  do_QueryInterface(annotations, &rv);
835  NS_ENSURE_SUCCESS(rv, rv);
836 
837  immutableAnnotations.forget(aAnnotations);
838 
839  return NS_OK;
840 }
841 
842 
843 nsresult
845  PRUint32 aRow,
846  sbIPlaybackHistoryEntry **aEntry)
847 {
848  NS_ENSURE_ARG_POINTER(aResult);
849  NS_ENSURE_ARG_POINTER(aEntry);
850 
851  PRUint32 rowCount = 0;
852  nsresult rv = aResult->GetRowCount(&rowCount);
853  NS_ENSURE_SUCCESS(rv, rv);
854  NS_ENSURE_TRUE(aRow < rowCount, NS_ERROR_INVALID_ARG);
855 
856  nsString entryIdStr;
857  rv = aResult->GetRowCell(aRow, 0, entryIdStr);
858  NS_ENSURE_SUCCESS(rv, rv);
859 
860  nsString libraryGuid;
861  rv = aResult->GetRowCell(aRow, 1, libraryGuid);
862  NS_ENSURE_SUCCESS(rv, rv);
863 
864  nsString mediaItemGuid;
865  rv = aResult->GetRowCell(aRow, 2, mediaItemGuid);
866  NS_ENSURE_SUCCESS(rv, rv);
867 
868  nsString playTime;
869  rv = aResult->GetRowCell(aRow, 3, playTime);
870  NS_ENSURE_SUCCESS(rv, rv);
871 
872  nsString playDuration;
873  rv = aResult->GetRowCell(aRow, 4, playDuration);
874  NS_ENSURE_SUCCESS(rv, rv);
875 
876  PRInt64 timestamp = nsString_ToUint64(playTime, &rv);
877  NS_ENSURE_SUCCESS(rv, rv);
878 
879  PRInt64 duration = nsString_ToUint64(playDuration, &rv);
880  NS_ENSURE_SUCCESS(rv, rv);
881 
882  nsCOMPtr<sbIMediaItem> item;
883  rv = GetItem(libraryGuid, mediaItemGuid, getter_AddRefs(item));
884  NS_ENSURE_SUCCESS(rv, rv);
885 
886  PRInt64 entryId = nsString_ToUint64(entryIdStr, &rv);
887  NS_ENSURE_SUCCESS(rv, rv);
888 
889  nsCOMPtr<sbIPropertyArray> annotations;
890  rv = CreateAnnotationsFromEntryId(entryId, getter_AddRefs(annotations));
891  NS_ENSURE_SUCCESS(rv, rv);
892 
893  nsCOMPtr<sbIPlaybackHistoryEntry> entry;
894  rv = CreateEntry(item, timestamp, duration, annotations, getter_AddRefs(entry));
895  NS_ENSURE_SUCCESS(rv, rv);
896 
897  entry->SetEntryId(entryId);
898  entry.forget(aEntry);
899 
900  return NS_OK;
901 }
902 
903 nsresult
905  nsIArray **aEntries)
906 {
907  NS_ENSURE_ARG_POINTER(aResult);
908  NS_ENSURE_ARG_POINTER(aEntries);
909 
910  nsresult rv = NS_ERROR_UNEXPECTED;
911  nsCOMPtr<nsIMutableArray> mutableArray =
912  do_CreateInstance(SB_THREADSAFE_ARRAY_CONTRACTID, &rv);
913  NS_ENSURE_SUCCESS(rv, rv);
914 
915  PRUint32 rowCount = 0;
916  rv = aResult->GetRowCount(&rowCount);
917  NS_ENSURE_SUCCESS(rv, rv);
918 
919  for(PRUint32 currentRow = 0; currentRow < rowCount; ++currentRow) {
920  nsCOMPtr<sbIPlaybackHistoryEntry> entry;
921 
922  rv = CreateEntryFromResultSet(aResult, currentRow, getter_AddRefs(entry));
923  // failing to find the item is not fatal, it only means that it has been
924  // deleted from the library, so just skip it. Do not remove it from the
925  // history though, so that if the same item is added again, we'll still
926  // have its data.
927  if (rv == NS_ERROR_NOT_AVAILABLE)
928  continue;
929 
930  rv = mutableArray->AppendElement(entry, PR_FALSE);
931  NS_ENSURE_SUCCESS(rv, rv);
932  }
933 
934  nsCOMPtr<nsIArray> array = do_QueryInterface(mutableArray);
935  array.forget(aEntries);
936 
937  return NS_OK;
938 }
939 
940 nsresult
942 {
943  nsresult rv = NS_ERROR_UNEXPECTED;
944 
945  nsCOMPtr<nsILocalFile> file = GetDBFolder();
946  NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
947 
948  nsString dbFileName = NS_LITERAL_STRING(PLAYBACKHISTORY_DB_GUID);
949  dbFileName.AppendLiteral(".db");
950 
951  rv = file->AppendRelativePath(dbFileName);
952  NS_ENSURE_SUCCESS(rv, rv);
953 
954  PRBool exists = PR_FALSE;
955  rv = file->Exists(&exists);
956  NS_ENSURE_SUCCESS(rv, rv);
957 
958  if(exists) {
959  return NS_OK;
960  }
961 
962  nsCOMPtr<sbIDatabaseQuery> query =
963  do_CreateInstance(SONGBIRD_DATABASEQUERY_CONTRACTID, &rv);
964  NS_ENSURE_SUCCESS(rv, rv);
965 
966  rv = query->SetDatabaseGUID(NS_LITERAL_STRING(PLAYBACKHISTORY_DB_GUID));
967  NS_ENSURE_SUCCESS(rv, rv);
968 
969  nsCOMPtr<nsIURI> schemaURI;
970  rv = NS_NewURI(getter_AddRefs(schemaURI), NS_LITERAL_CSTRING(SCHEMA_URL));
971  NS_ENSURE_SUCCESS(rv, rv);
972 
973  nsCOMPtr<nsIInputStream> input;
974  rv = NS_OpenURI(getter_AddRefs(input), schemaURI);
975  NS_ENSURE_SUCCESS(rv, rv);
976 
977  nsCOMPtr<nsIConverterInputStream> converterStream =
978  do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
979  NS_ENSURE_SUCCESS(rv, rv);
980 
981  rv = converterStream->Init(input,
982  "UTF-8",
984  nsIConverterInputStream::DEFAULT_REPLACEMENT_CHARACTER);
985  NS_ENSURE_SUCCESS(rv, rv);
986 
987  nsCOMPtr<nsIUnicharInputStream> unichar =
988  do_QueryInterface(converterStream, &rv);
989  NS_ENSURE_SUCCESS(rv, rv);
990 
991  PRUint32 read = 0;
992  nsString response;
993  rv = unichar->ReadString(PR_UINT32_MAX, response, &read);
994  NS_ENSURE_SUCCESS(rv, rv);
995 
996  NS_ASSERTION(read, "Schema file zero bytes?");
997 
998  rv = unichar->Close();
999  NS_ENSURE_SUCCESS(rv, rv);
1000 
1001  NS_NAMED_LITERAL_STRING(colonNewline, ";\n");
1002 
1003  PRInt32 posStart = 0;
1004  PRInt32 posEnd = response.Find(colonNewline, posStart);
1005  while (posEnd >= 0) {
1006  rv = query->AddQuery(Substring(response, posStart, posEnd - posStart));
1007  NS_ENSURE_SUCCESS(rv, rv);
1008  posStart = posEnd + 2;
1009  posEnd = response.Find(colonNewline, posStart);
1010  }
1011 
1012  PRInt32 dbOk = 0;
1013  rv = query->Execute(&dbOk);
1014  NS_ENSURE_SUCCESS(rv, rv);
1015  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1016 
1017  return NS_OK;
1018 }
1019 
1020 nsresult
1022  sbIPlaybackHistoryEntry *aEntry)
1023 {
1024  NS_ENSURE_ARG_POINTER(aQuery);
1025  NS_ENSURE_ARG_POINTER(aEntry);
1026 
1027  nsCOMPtr<sbIMediaItem> item;
1028  nsresult rv = aEntry->GetItem(getter_AddRefs(item));
1029  NS_ENSURE_SUCCESS(rv, rv);
1030 
1031  nsCOMPtr<sbILibrary> library;
1032  rv = item->GetLibrary(getter_AddRefs(library));
1033  NS_ENSURE_SUCCESS(rv, rv);
1034 
1035  nsString libraryGuid;
1036  rv = library->GetGuid(libraryGuid);
1037  NS_ENSURE_SUCCESS(rv, rv);
1038 
1039  rv = aQuery->BindStringParameter(0, libraryGuid);
1040  NS_ENSURE_SUCCESS(rv, rv);
1041 
1042  nsString itemGuid;
1043  rv = item->GetGuid(itemGuid);
1044  NS_ENSURE_SUCCESS(rv, rv);
1045 
1046  rv = aQuery->BindStringParameter(1, itemGuid);
1047  NS_ENSURE_SUCCESS(rv, rv);
1048 
1049  PRTime timestamp = 0;
1050  rv = aEntry->GetTimestamp(&timestamp);
1051  NS_ENSURE_SUCCESS(rv, rv);
1052 
1053  char buf[30];
1054  PRUint32 len = PR_snprintf(buf, sizeof(buf), "%lld", timestamp);
1055 
1056  NS_ConvertASCIItoUTF16 timestampString(buf, len);
1057  rv = aQuery->BindStringParameter(2, timestampString);
1058  NS_ENSURE_SUCCESS(rv, rv);
1059 
1060  PRTime duration = 0;
1061  rv = aEntry->GetDuration(&duration);
1062  NS_ENSURE_SUCCESS(rv, rv);
1063 
1064  // duration is optional so if it's not present we bind to null instead of 0.
1065  if(duration) {
1066  len = PR_snprintf(buf, sizeof(buf), "%lld", duration);
1067  NS_ConvertASCIItoUTF16 durationString(buf, len);
1068 
1069  rv = aQuery->BindStringParameter(3, durationString);
1070  NS_ENSURE_SUCCESS(rv, rv);
1071  }
1072  else {
1073  rv = aQuery->BindNullParameter(3);
1074  NS_ENSURE_SUCCESS(rv, rv);
1075  }
1076 
1077  rv = aQuery->AddQuery(NS_LITERAL_STRING("select last_insert_rowid()"));
1078 
1079  return NS_OK;
1080 }
1081 
1082 nsresult
1084  sbIDatabaseQuery *aQuery,
1085  sbIPlaybackHistoryEntry *aEntry)
1086 {
1087  NS_ENSURE_ARG_POINTER(aQuery);
1088  NS_ENSURE_ARG_POINTER(aEntry);
1089 
1090  nsCOMPtr<sbIPropertyArray> annotations;
1091  nsresult rv = aEntry->GetAnnotations(getter_AddRefs(annotations));
1092  NS_ENSURE_SUCCESS(rv, rv);
1093 
1094  if(!annotations) {
1095  return NS_OK;
1096  }
1097 
1098  nsCOMPtr<sbIPropertyManager> propMan =
1099  do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
1100  NS_ENSURE_SUCCESS(rv, rv);
1101 
1102  nsCOMPtr<sbIMediaItem> item;
1103  rv = aEntry->GetItem(getter_AddRefs(item));
1104  NS_ENSURE_SUCCESS(rv, rv);
1105 
1106  nsCOMPtr<sbILibrary> library;
1107  rv = item->GetLibrary(getter_AddRefs(library));
1108  NS_ENSURE_SUCCESS(rv, rv);
1109 
1110  nsString libraryGuid;
1111  rv = library->GetGuid(libraryGuid);
1112  NS_ENSURE_SUCCESS(rv, rv);
1113 
1114  nsString itemGuid;
1115  rv = item->GetGuid(itemGuid);
1116  NS_ENSURE_SUCCESS(rv, rv);
1117 
1118  PRTime timestamp = 0;
1119  rv = aEntry->GetTimestamp(&timestamp);
1120  NS_ENSURE_SUCCESS(rv, rv);
1121 
1122  char buf[30];
1123  PRUint32 len = PR_snprintf(buf, sizeof(buf), "%lld", timestamp);
1124  NS_ConvertASCIItoUTF16 timestampString(buf, len);
1125 
1126  PRUint32 length = 0;
1127  rv = annotations->GetLength(&length);
1128  NS_ENSURE_SUCCESS(rv, rv);
1129 
1130  for(PRUint32 current = 0; current < length; ++current) {
1131  nsCOMPtr<sbIProperty> annotation;
1132  rv = annotations->GetPropertyAt(current, getter_AddRefs(annotation));
1133  NS_ENSURE_SUCCESS(rv, rv);
1134 
1135  nsString id;
1136  rv = annotation->GetId(id);
1137  NS_ENSURE_SUCCESS(rv, rv);
1138 
1139  nsString value;
1140  rv = annotation->GetValue(value);
1141  NS_ENSURE_SUCCESS(rv, rv);
1142 
1143  PRUint32 propertyId;
1144  rv = GetPropertyDBID(id, &propertyId);
1145  NS_ENSURE_SUCCESS(rv, rv);
1146 
1147  nsCOMPtr<sbIPropertyInfo> propertyInfo;
1148  rv = propMan->GetPropertyInfo(id, getter_AddRefs(propertyInfo));
1149  NS_ENSURE_SUCCESS(rv, rv);
1150 
1151  nsAutoString sortableValue;
1152  rv = propertyInfo->MakeSortable(value, sortableValue);
1153  NS_ENSURE_SUCCESS(rv, rv);
1154 
1155  rv = aQuery->AddQuery(mAddAnnotationQuery);
1156  NS_ENSURE_SUCCESS(rv, rv);
1157 
1158  rv = aQuery->BindStringParameter(0, libraryGuid);
1159  NS_ENSURE_SUCCESS(rv, rv);
1160 
1161  rv = aQuery->BindStringParameter(1, itemGuid);
1162  NS_ENSURE_SUCCESS(rv, rv);
1163 
1164  rv = aQuery->BindStringParameter(2, timestampString);
1165  NS_ENSURE_SUCCESS(rv, rv);
1166 
1167  rv = aQuery->BindInt32Parameter(3, propertyId);
1168  NS_ENSURE_SUCCESS(rv, rv);
1169 
1170  rv = aQuery->BindStringParameter(4, value);
1171  NS_ENSURE_SUCCESS(rv, rv);
1172 
1173  rv = aQuery->BindStringParameter(5, sortableValue);
1174  NS_ENSURE_SUCCESS(rv, rv);
1175  }
1176 
1177  return NS_OK;
1178 }
1179 
1180 nsresult
1182  sbIPlaybackHistoryEntry *aEntry)
1183 {
1184  NS_ENSURE_ARG_POINTER(aQuery);
1185  NS_ENSURE_ARG_POINTER(aEntry);
1186 
1187  nsCOMPtr<sbIMediaItem> item;
1188  nsresult rv = aEntry->GetItem(getter_AddRefs(item));
1189  NS_ENSURE_SUCCESS(rv, rv);
1190 
1191  nsCOMPtr<sbILibrary> library;
1192  rv = item->GetLibrary(getter_AddRefs(library));
1193  NS_ENSURE_SUCCESS(rv, rv);
1194 
1195  nsString libraryGuid;
1196  rv = library->GetGuid(libraryGuid);
1197  NS_ENSURE_SUCCESS(rv, rv);
1198 
1199  rv = aQuery->BindStringParameter(0, libraryGuid);
1200  NS_ENSURE_SUCCESS(rv, rv);
1201 
1202  nsString itemGuid;
1203  rv = item->GetGuid(itemGuid);
1204  NS_ENSURE_SUCCESS(rv, rv);
1205 
1206  rv = aQuery->BindStringParameter(1, itemGuid);
1207  NS_ENSURE_SUCCESS(rv, rv);
1208 
1209  PRTime timestamp = 0;
1210  rv = aEntry->GetTimestamp(&timestamp);
1211  NS_ENSURE_SUCCESS(rv, rv);
1212 
1213  char buf[30];
1214  PRUint32 len = PR_snprintf(buf, sizeof(buf), "%lld", timestamp);
1215 
1216  NS_ConvertASCIItoUTF16 timestampString(buf, len);
1217  rv = aQuery->BindStringParameter(2, timestampString);
1218  NS_ENSURE_SUCCESS(rv, rv);
1219 
1220  return NS_OK;
1221 }
1222 
1223 nsresult
1224 sbPlaybackHistoryService::GetItem(const nsAString &aLibraryGuid,
1225  const nsAString &aItemGuid,
1226  sbIMediaItem **aItem)
1227 {
1228  NS_ENSURE_ARG_POINTER(aItem);
1229 
1230  nsresult rv = NS_ERROR_UNEXPECTED;
1231  nsCOMPtr<sbILibrary> library;
1232  if(!mLibraries.Get(aLibraryGuid, getter_AddRefs(library))) {
1233  nsCOMPtr<sbILibraryManager> libraryManager =
1234  do_GetService(SONGBIRD_LIBRARYMANAGER_CONTRACTID, &rv);
1235  NS_ENSURE_SUCCESS(rv, rv);
1236 
1237  rv = libraryManager->GetLibrary(aLibraryGuid, getter_AddRefs(library));
1238  NS_ENSURE_SUCCESS(rv, rv);
1239 
1240  PRBool success = mLibraries.Put(aLibraryGuid, library);
1241  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1242  }
1243 
1244  nsCOMPtr<sbIMediaItem> item;
1245  rv = library->GetMediaItem(aItemGuid, getter_AddRefs(item));
1246  NS_ENSURE_SUCCESS(rv, rv);
1247 
1248  item.forget(aItem);
1249 
1250  return NS_OK;
1251 }
1252 
1253 nsresult
1254 sbPlaybackHistoryService::GetPropertyDBID(const nsAString &aPropertyID,
1255  PRUint32 *aPropertyDBID)
1256 {
1257  NS_ENSURE_ARG_POINTER(aPropertyDBID);
1258  *aPropertyDBID = 0;
1259 
1260  if (!mPropertyIDToDBID.Get(aPropertyID, aPropertyDBID)) {
1261  nsresult rv = InsertPropertyID(aPropertyID, aPropertyDBID);
1262  NS_ENSURE_SUCCESS (rv, rv);
1263  }
1264 
1265  return NS_OK;
1266 }
1267 
1268 nsresult
1269 sbPlaybackHistoryService::InsertPropertyID(const nsAString &aPropertyID,
1270  PRUint32 *aPropertyDBID)
1271 {
1272  NS_ENSURE_ARG_POINTER(aPropertyDBID);
1273 
1274  nsCOMPtr<sbIDatabaseQuery> query;
1275  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
1276  NS_ENSURE_SUCCESS(rv, rv);
1277 
1278  rv = query->AddQuery(mInsertPropertyIDQuery);
1279  NS_ENSURE_SUCCESS(rv, rv);
1280 
1281  rv = query->BindStringParameter(0, aPropertyID);
1282  NS_ENSURE_SUCCESS(rv, rv);
1283 
1284  rv = query->AddQuery(NS_LITERAL_STRING("select last_insert_rowid()"));
1285  NS_ENSURE_SUCCESS(rv, rv);
1286 
1287  PRInt32 dbOk = 0;
1288  rv = query->Execute(&dbOk);
1289  NS_ENSURE_SUCCESS(rv, rv);
1290  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1291 
1292  nsCOMPtr<sbIDatabaseResult> result;
1293  rv = query->GetResultObject(getter_AddRefs(result));
1294  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1295 
1296  nsAutoString propertyDBIDStr;
1297  rv = result->GetRowCell(0, 0, propertyDBIDStr);
1298  NS_ENSURE_SUCCESS(rv, rv);
1299 
1300  PRUint32 propertyDBID = propertyDBIDStr.ToInteger(&rv);
1301  NS_ENSURE_SUCCESS(rv, rv);
1302 
1303  *aPropertyDBID = propertyDBID;
1304 
1305  mPropertyDBIDToID.Put(propertyDBID, nsAutoString(aPropertyID));
1306  mPropertyIDToDBID.Put(nsAutoString(aPropertyID), propertyDBID);
1307 
1308  return NS_OK;
1309 }
1310 
1311 nsresult
1313 {
1314  nsresult rv = NS_ERROR_UNEXPECTED;
1315 
1316  nsCOMPtr<sbISQLSelectBuilder> builder =
1317  do_CreateInstance(SB_SQLBUILDER_SELECT_CONTRACTID, &rv);
1318  NS_ENSURE_SUCCESS(rv, rv);
1319 
1320  rv = builder->SetBaseTableName(NS_LITERAL_STRING(PLAYBACKHISTORY_PROPERTIES_TABLE));
1321  NS_ENSURE_SUCCESS(rv, rv);
1322 
1323  rv = builder->AddColumn(EmptyString(), NS_LITERAL_STRING(PROPERTY_ID_COLUMN));
1324  NS_ENSURE_SUCCESS(rv, rv);
1325 
1326  rv = builder->AddColumn(EmptyString(), NS_LITERAL_STRING(PROPERTY_NAME_COLUMN));
1327  NS_ENSURE_SUCCESS(rv, rv);
1328 
1329  nsAutoString sql;
1330  rv = builder->ToString(sql);
1331  NS_ENSURE_SUCCESS(rv, rv);
1332 
1333  nsCOMPtr<sbIDatabaseQuery> query;
1334  rv = CreateDefaultQuery(getter_AddRefs(query));
1335  NS_ENSURE_SUCCESS(rv, rv);
1336 
1337  rv = query->AddQuery(sql);
1338  NS_ENSURE_SUCCESS(rv, rv);
1339 
1340  PRInt32 dbOk = 0;
1341  rv = query->Execute(&dbOk);
1342  NS_ENSURE_SUCCESS(rv, rv);
1343  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1344 
1345  nsCOMPtr<sbIDatabaseResult> result;
1346  rv = query->GetResultObject(getter_AddRefs(result));
1347  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1348 
1349  PRUint32 rowCount;
1350  rv = result->GetRowCount(&rowCount);
1351  NS_ENSURE_SUCCESS(rv, rv);
1352 
1353  for (PRUint32 i = 0; i < rowCount; i++) {
1354  nsAutoString propertyDBIDStr;
1355  rv = result->GetRowCell(i, 0, propertyDBIDStr);
1356  NS_ENSURE_SUCCESS(rv, rv);
1357 
1358  PRUint32 propertyDBID = propertyDBIDStr.ToInteger(&rv);
1359  NS_ENSURE_SUCCESS(rv, rv);
1360 
1361  nsString propertyID;
1362  rv = result->GetRowCell(i, 1, propertyID);
1363  NS_ENSURE_SUCCESS(rv, rv);
1364 
1365  PRBool success = mPropertyDBIDToID.Put(propertyDBID, propertyID);
1366  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1367 
1368  success = mPropertyIDToDBID.Put(propertyID, propertyDBID);
1369  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1370  }
1371 
1372  return NS_OK;
1373 }
1374 
1375 nsresult
1377 {
1378  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1379 
1380  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1381  (void *)&listeners);
1382 
1383  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1384  PRInt32 count = listeners.Count();
1385 
1386  nsresult rv = NS_ERROR_UNEXPECTED;
1387  nsCOMPtr<nsIMutableArray> array =
1388  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1389  NS_ENSURE_SUCCESS(rv, rv);
1390 
1391  rv = array->AppendElement(aEntry, PR_FALSE);
1392  NS_ENSURE_SUCCESS(rv, rv);
1393 
1394  for(PRInt32 current = 0; current < count; ++current) {
1395  rv = listeners[current]->OnEntriesAdded(array);
1396 
1397 #if defined(DEBUG)
1398  NS_ENSURE_SUCCESS(rv, rv);
1399 #endif
1400  }
1401 
1402  return NS_OK;
1403 }
1404 
1405 nsresult
1407 {
1408  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1409 
1410  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1411  (void *)&listeners);
1412 
1413  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1414  PRInt32 count = listeners.Count();
1415 
1416  for(PRInt32 current = 0; current < count; ++current) {
1417  nsresult SB_UNUSED_IN_RELEASE(rv) =
1418  listeners[current]->OnEntriesAdded(aEntries);
1419 
1420 #if defined(DEBUG)
1421  NS_ENSURE_SUCCESS(rv, rv);
1422 #endif
1423  }
1424 
1425  return NS_OK;
1426 }
1427 
1428 nsresult
1430 {
1431  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1432 
1433  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1434  (void *)&listeners);
1435 
1436  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1437  PRInt32 count = listeners.Count();
1438 
1439  nsresult rv = NS_ERROR_UNEXPECTED;
1440  nsCOMPtr<nsIMutableArray> array =
1441  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1442  NS_ENSURE_SUCCESS(rv, rv);
1443 
1444  rv = array->AppendElement(aEntry, PR_FALSE);
1445  NS_ENSURE_SUCCESS(rv, rv);
1446 
1447  for(PRInt32 current = 0; current < count; ++current) {
1448  rv = listeners[current]->OnEntriesUpdated(array);
1449 
1450 #if defined(DEBUG)
1451  NS_ENSURE_SUCCESS(rv, rv);
1452 #endif
1453  }
1454 
1455  return NS_OK;
1456 }
1457 
1458 nsresult
1460 {
1461  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1462 
1463  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1464  (void *)&listeners);
1465 
1466  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1467  PRInt32 count = listeners.Count();
1468 
1469  for(PRInt32 current = 0; current < count; ++current) {
1470  nsresult SB_UNUSED_IN_RELEASE(rv) =
1471  listeners[current]->OnEntriesUpdated(aEntries);
1472 
1473 #if defined(DEBUG)
1474  NS_ENSURE_SUCCESS(rv, rv);
1475 #endif
1476  }
1477 
1478  return NS_OK;
1479 }
1480 
1481 nsresult
1483 {
1484  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1485 
1486  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1487  (void *)&listeners);
1488 
1489  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1490  PRInt32 count = listeners.Count();
1491 
1492  nsresult rv = NS_ERROR_UNEXPECTED;
1493  nsCOMPtr<nsIMutableArray> array =
1494  do_CreateInstance("@songbirdnest.com/moz/xpcom/threadsafe-array;1", &rv);
1495  NS_ENSURE_SUCCESS(rv, rv);
1496 
1497  rv = array->AppendElement(aEntry, PR_FALSE);
1498  NS_ENSURE_SUCCESS(rv, rv);
1499 
1500  for(PRInt32 current = 0; current < count; ++current) {
1501  rv = listeners[current]->OnEntriesRemoved(array);
1502 
1503 #if defined(DEBUG)
1504  NS_ENSURE_SUCCESS(rv, rv);
1505 #endif
1506  }
1507 
1508  return NS_OK;
1509 }
1510 
1511 nsresult
1513 {
1514  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1515 
1516  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1517  (void *)&listeners);
1518 
1519  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1520  PRInt32 count = listeners.Count();
1521 
1522  for(PRInt32 current = 0; current < count; ++current) {
1523  nsresult SB_UNUSED_IN_RELEASE(rv) =
1524  listeners[current]->OnEntriesRemoved(aEntries);
1525 
1526 #if defined(DEBUG)
1527  NS_ENSURE_SUCCESS(rv, rv);
1528 #endif
1529  }
1530 
1531  return NS_OK;
1532 }
1533 
1534 nsresult
1536 {
1537  nsCOMArray<sbIPlaybackHistoryListener> listeners;
1538 
1539  mListeners.EnumerateRead(AddListenersToCOMArrayCallback,
1540  (void *)&listeners);
1541 
1542  nsCOMPtr<sbIPlaybackHistoryListener> listener;
1543  PRInt32 count = listeners.Count();
1544 
1545  for(PRInt32 current = 0; current < count; ++current) {
1546  nsresult SB_UNUSED_IN_RELEASE(rv) =
1547  listeners[current]->OnEntriesCleared();
1548 
1549 #if defined(DEBUG)
1550  NS_ENSURE_SUCCESS(rv, rv);
1551 #endif
1552  }
1553 
1554  return NS_OK;
1555 }
1556 
1557 nsresult
1559 {
1560  NS_ENSURE_ARG_POINTER(aEvent);
1561 
1562  nsCOMPtr<nsIVariant> variant;
1563  nsresult rv = aEvent->GetData(getter_AddRefs(variant));
1564  NS_ENSURE_SUCCESS(rv, rv);
1565 
1566  nsCOMPtr<nsISupports> supports;
1567  rv = variant->GetAsISupports(getter_AddRefs(supports));
1568  NS_ENSURE_SUCCESS(rv, rv);
1569 
1570  nsCOMPtr<sbIMediaItem> item = do_QueryInterface(supports, &rv);
1571  NS_ENSURE_SUCCESS(rv, rv);
1572 
1573  mCurrentItem = item;
1574  mCurrentlyTracking = PR_TRUE;
1575 
1576  mCurrentStartTime = 0;
1577  mCurrentDelta = 0;
1578 
1579  return NS_OK;
1580 }
1581 
1582 nsresult
1584 {
1585  NS_ENSURE_ARG_POINTER(aEvent);
1586 
1587  nsCOMPtr<nsIVariant> variant;
1588  nsresult rv = aEvent->GetData(getter_AddRefs(variant));
1589  NS_ENSURE_SUCCESS(rv, rv);
1590 
1591  nsCOMPtr<nsISupports> supports;
1592  rv = variant->GetAsISupports(getter_AddRefs(supports));
1593  NS_ENSURE_SUCCESS(rv, rv);
1594 
1595  nsCOMPtr<sbIMediaListView> view = do_QueryInterface(supports, &rv);
1596  NS_ENSURE_SUCCESS(rv, rv);
1597 
1598  view.swap(mCurrentView);
1599 
1600  return NS_OK;
1601 }
1602 
1603 nsresult
1605 {
1606  nsAutoMonitor mon(mMonitor);
1607 
1608  NS_ENSURE_STATE(mCurrentlyTracking);
1609  NS_ENSURE_STATE(mCurrentItem);
1610  NS_ENSURE_STATE(mCurrentStartTime);
1611 
1612  if(!mCurrentlyTracking) {
1613  return NS_ERROR_UNEXPECTED;
1614  }
1615 
1616  // figure out actual playing time in milliseconds.
1617  PRTime actualPlayingTime = PR_Now() - mCurrentStartTime - mCurrentDelta;
1618  actualPlayingTime /= PR_USEC_PER_MSEC;
1619 
1620  NS_NAMED_LITERAL_STRING(PROPERTY_DURATION, SB_PROPERTY_DURATION);
1621  NS_NAMED_LITERAL_STRING(PROPERTY_PLAYCOUNT, SB_PROPERTY_PLAYCOUNT);
1622  NS_NAMED_LITERAL_STRING(PROPERTY_SKIPCOUNT, SB_PROPERTY_SKIPCOUNT);
1623  NS_NAMED_LITERAL_STRING(PROPERTY_LASTPLAYTIME, SB_PROPERTY_LASTPLAYTIME);
1624  NS_NAMED_LITERAL_STRING(PROPERTY_LASTSKIPTIME, SB_PROPERTY_LASTSKIPTIME);
1625  NS_NAMED_LITERAL_STRING(PROPERTY_EXCLUDE_FROM_HISTORY,
1627 
1628  nsString durationStr;
1629  nsresult rv = mCurrentItem->GetProperty(PROPERTY_DURATION, durationStr);
1630  NS_ENSURE_SUCCESS(rv, rv);
1631 
1632  PRInt64 duration = nsString_ToInt64(durationStr, &rv);
1633  duration /= PR_USEC_PER_MSEC;
1634  NS_ENSURE_SUCCESS(rv, rv);
1635 
1636  nsString excludeFromHistoryStr;
1637  rv = mCurrentItem->GetProperty(PROPERTY_EXCLUDE_FROM_HISTORY,
1638  excludeFromHistoryStr);
1639  NS_ENSURE_SUCCESS(rv, rv);
1640 
1641  PRBool excludeFromHistory = excludeFromHistoryStr.EqualsLiteral("1");
1642 
1643  // if we played for at least 240 seconds (matching audioscrobbler)
1644  // or more than half the track (matching audioscrobbler)
1645  if((duration && (actualPlayingTime >= (duration / 2))) ||
1646  actualPlayingTime >= (240 * 1000)) {
1647 
1648  // increment play count.
1649  nsString playCountStr;
1650  rv = mCurrentItem->GetProperty(PROPERTY_PLAYCOUNT, playCountStr);
1651  NS_ENSURE_SUCCESS(rv, rv);
1652 
1653  PRUint64 playCount = 0;
1654  if(!playCountStr.IsEmpty()) {
1655  playCount = nsString_ToUint64(playCountStr, &rv);
1656  NS_ENSURE_SUCCESS(rv, rv);
1657  }
1658  playCount++;
1659 
1660  sbAutoString newPlayCountStr(playCount);
1661  rv = mCurrentItem->SetProperty(PROPERTY_PLAYCOUNT, newPlayCountStr);
1662  NS_ENSURE_SUCCESS(rv, rv);
1663 
1664  // update last time played
1665  sbAutoString newLastPlayTimeStr((PRUint64)(mCurrentStartTime /
1666  PR_USEC_PER_MSEC));
1667  rv = mCurrentItem->SetProperty(PROPERTY_LASTPLAYTIME, newLastPlayTimeStr);
1668  NS_ENSURE_SUCCESS(rv, rv);
1669 
1670  // create new playback history entry, if appropriate
1671  if (!excludeFromHistory) {
1672  nsCOMPtr<sbIPlaybackHistoryEntry> entry;
1673  rv = CreateEntry(mCurrentItem,
1674  mCurrentStartTime,
1675  actualPlayingTime,
1676  nsnull,
1677  getter_AddRefs(entry));
1678  NS_ENSURE_SUCCESS(rv, rv);
1679 
1680  rv = AddEntry(entry);
1681  NS_ENSURE_SUCCESS(rv, rv);
1682  }
1683  }
1684  else {
1685  // update skip count.
1686  nsString skipCountStr;
1687  rv = mCurrentItem->GetProperty(PROPERTY_SKIPCOUNT, skipCountStr);
1688  NS_ENSURE_SUCCESS(rv, rv);
1689 
1690  PRUint64 skipCount = 0;
1691  if(!skipCountStr.IsEmpty()) {
1692  skipCount = nsString_ToUint64(skipCountStr, &rv);
1693  NS_ENSURE_SUCCESS(rv, rv);
1694  }
1695  skipCount++;
1696 
1697  sbAutoString newSkipCountStr(skipCount);
1698  rv = mCurrentItem->SetProperty(PROPERTY_SKIPCOUNT, newSkipCountStr);
1699  NS_ENSURE_SUCCESS(rv, rv);
1700 
1701  // update last skip time.
1702  sbAutoString newLastSkipTimeStr((PRUint64) (mCurrentStartTime /
1703  PR_USEC_PER_MSEC));
1704  rv = mCurrentItem->SetProperty(PROPERTY_LASTSKIPTIME, newLastSkipTimeStr);
1705  NS_ENSURE_SUCCESS(rv, rv);
1706  }
1707 
1708  /*
1709  Playback metrics are timing out causing the play count
1710  to fail to increment!
1711 #ifdef METRICS_ENABLED
1712  // Regardless, we update playback metrics.
1713  // rv = UpdateMetrics();
1714  // NS_ENSURE_SUCCESS(rv, rv);
1715 #endif
1716  */
1717 
1718  return NS_OK;
1719 }
1720 
1721 nsresult
1723 {
1724  nsAutoMonitor mon(mMonitor);
1725 
1726  mCurrentlyTracking = PR_FALSE;
1727  mCurrentStartTime = 0;
1728  mCurrentPauseTime = 0;
1729  mCurrentDelta = 0;
1730  mCurrentItem = nsnull;
1731 
1732  return NS_OK;
1733 }
1734 
1735 #ifdef METRICS_ENABLED
1736 nsresult
1737 sbPlaybackHistoryService::UpdateMetrics()
1738 {
1739  nsAutoMonitor mon(mMonitor);
1740 
1741  NS_ENSURE_STATE(mCurrentView);
1742  NS_ENSURE_STATE(mCurrentItem);
1743 
1744  if (!mMetrics) {
1745  // metrics not available, e.g. after library shutdown
1746  return NS_OK;
1747  }
1748 
1749  // figure out actual playing time in seconds.
1750  PRTime actualPlayingTime = PR_Now() - mCurrentStartTime - mCurrentDelta;
1751  actualPlayingTime /= PR_USEC_PER_SEC;
1752 
1753  // increment total items played.
1754  nsresult rv = mMetrics->MetricsInc(NS_LITERAL_STRING(METRIC_MEDIACORE_ROOT),
1755  NS_LITERAL_STRING(METRIC_PLAY),
1756  NS_LITERAL_STRING(METRIC_ITEM));
1757  NS_ENSURE_SUCCESS(rv, rv);
1758 
1759  // increment total play time.
1760  rv = mMetrics->MetricsAdd(NS_LITERAL_STRING(METRIC_MEDIACORE_ROOT),
1761  NS_LITERAL_STRING(METRIC_PLAYTIME),
1762  EmptyString(),
1763  actualPlayingTime);
1764  NS_ENSURE_SUCCESS(rv, rv);
1765 
1766  // increment the appropriate bitrate bucket.
1767  nsString bitRateStr;
1768  rv = mCurrentItem->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_BITRATE),
1769  bitRateStr);
1770  if(NS_FAILED(rv) || bitRateStr.IsEmpty()) {
1771  bitRateStr.AssignLiteral(METRIC_UNKNOWN);
1772  }
1773 
1774  nsString bitRateKey(NS_LITERAL_STRING(METRIC_BITRATE));
1775  bitRateKey.AppendLiteral(".");
1776  bitRateKey += bitRateStr;
1777 
1778  rv = mMetrics->MetricsInc(NS_LITERAL_STRING(METRIC_MEDIACORE_ROOT),
1779  NS_LITERAL_STRING(METRIC_PLAY),
1780  bitRateKey);
1781  NS_ENSURE_SUCCESS(rv, rv);
1782 
1783  // increment appropriate medialist total play time.
1784  nsCOMPtr<sbILibrary> library;
1785  rv = mCurrentItem->GetLibrary(getter_AddRefs(library));
1786  NS_ENSURE_SUCCESS(rv, rv);
1787 
1788  nsCOMPtr<sbIMediaList> libraryList = do_QueryInterface(library, &rv);
1789  NS_ENSURE_SUCCESS(rv, rv);
1790 
1791  nsCOMPtr<sbIMediaList> list;
1792  rv = mCurrentView->GetMediaList(getter_AddRefs(list));
1793  NS_ENSURE_SUCCESS(rv, rv);
1794 
1795  nsString listCustomType, libraryCustomType;
1796  rv = list->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_CUSTOMTYPE),
1797  listCustomType);
1798  if(NS_FAILED(rv) || listCustomType.IsEmpty()) {
1799  listCustomType.AssignLiteral("simple");
1800  }
1801 
1802  rv = library->GetProperty(NS_LITERAL_STRING(SB_PROPERTY_CUSTOMTYPE),
1803  libraryCustomType);
1804  if(NS_FAILED(rv) || listCustomType.IsEmpty()) {
1805  libraryCustomType.AssignLiteral("library");
1806  }
1807 
1808  nsString medialistKey;
1809  if(listCustomType.EqualsLiteral("dynamic")) {
1810  medialistKey.AssignLiteral(METRIC_SUBSCRIPTION);
1811  }
1812  else if(listCustomType.EqualsLiteral("local") ||
1813  listCustomType.EqualsLiteral("simple") ||
1814  libraryCustomType.EqualsLiteral("library")) {
1815  if(libraryList == list) {
1816  medialistKey.AssignLiteral(METRIC_LIBRARY);
1817  }
1818  else if(libraryCustomType.EqualsLiteral("web")) {
1819  medialistKey.AssignLiteral(METRIC_WEBPLAYLIST);
1820  }
1821  else {
1822  medialistKey.AssignLiteral("simple");
1823  }
1824  }
1825  else {
1826  medialistKey = listCustomType;
1827  }
1828 
1829  rv = mMetrics->MetricsInc(NS_LITERAL_STRING(METRIC_MEDIALIST_ROOT),
1830  NS_LITERAL_STRING(METRIC_PLAY),
1831  medialistKey);
1832  NS_ENSURE_SUCCESS(rv, rv);
1833 
1834  // increment appropriate play attempt bucket.
1835  nsCOMPtr<nsIURI> uri;
1836  rv = mCurrentItem->GetContentSrc(getter_AddRefs(uri));
1837  NS_ENSURE_SUCCESS(rv, rv);
1838 
1839  nsCString scheme;
1840  rv = uri->GetScheme(scheme);
1841  NS_ENSURE_SUCCESS(rv, rv);
1842 
1843  if(scheme.IsEmpty()) {
1844  scheme = METRIC_UNKNOWN;
1845  }
1846 
1847  nsCString extension;
1848  nsCOMPtr<nsIURL> url = do_QueryInterface(uri, &rv);
1849  if(NS_SUCCEEDED(rv)) {
1850  rv = url->GetFileExtension(extension);
1851  NS_ENSURE_SUCCESS(rv, rv);
1852  }
1853 
1854  if(extension.IsEmpty()) {
1855  extension = METRIC_UNKNOWN;
1856  }
1857 
1858  // key is attempt.<extension>.<scheme>
1859  nsString playAttemptKey(NS_LITERAL_STRING(METRIC_ATTEMPT));
1860  playAttemptKey.AppendLiteral(".");
1861  playAttemptKey += NS_ConvertUTF8toUTF16(extension);
1862  playAttemptKey.AppendLiteral(".");
1863  playAttemptKey += NS_ConvertUTF8toUTF16(scheme);
1864 
1865  rv = mMetrics->MetricsInc(NS_LITERAL_STRING(METRIC_MEDIACORE_ROOT),
1866  NS_LITERAL_STRING(METRIC_PLAY),
1867  playAttemptKey);
1868  NS_ENSURE_SUCCESS(rv, rv);
1869 
1870  // increment streaming bucket.
1871  if(scheme.EqualsLiteral("http") ||
1872  scheme.EqualsLiteral("https") ||
1873  scheme.EqualsLiteral("ftp") ||
1874  scheme.EqualsLiteral("rtsp")) {
1875  rv = mMetrics->MetricsInc(NS_LITERAL_STRING(METRIC_MEDIACORE_ROOT),
1876  NS_LITERAL_STRING(METRIC_PLAY),
1877  NS_LITERAL_STRING(METRIC_STREAMING));
1878  NS_ENSURE_SUCCESS(rv, rv);
1879  }
1880 
1881  return NS_OK;
1882 }
1883 #endif
1884 
1885 //-----------------------------------------------------------------------------
1886 // nsIObserver
1887 //-----------------------------------------------------------------------------
1888 NS_IMETHODIMP
1889 sbPlaybackHistoryService::Observe(nsISupports* aSubject,
1890  const char* aTopic,
1891  const PRUnichar* aData)
1892 {
1893  NS_ENSURE_ARG_POINTER(aTopic);
1894 
1895  nsresult rv = NS_ERROR_UNEXPECTED;
1896  nsCOMPtr<nsIObserverService> observerService =
1897  do_GetService("@mozilla.org/observer-service;1", &rv);
1898  NS_ENSURE_SUCCESS(rv, rv);
1899 
1900  if(strcmp(aTopic, SB_LIBRARY_MANAGER_READY_TOPIC) == 0) {
1901  rv = observerService->RemoveObserver(this, SB_LIBRARY_MANAGER_READY_TOPIC);
1902  NS_ENSURE_SUCCESS(rv, rv);
1903 
1905  NS_ENSURE_SUCCESS(rv, rv);
1906 
1907  rv = LoadPropertyIDs();
1908  NS_ENSURE_SUCCESS(rv, rv);
1909  }
1910  else if(strcmp(aTopic, SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC) == 0) {
1911  // Remove all library references
1912  mLibraries.Clear();
1913  mCurrentItem = nsnull;
1914  mCurrentView = nsnull;
1915 
1916 #ifdef METRICS_ENABLED
1917  // Releasing metrics prevents a leak
1918  mMetrics = nsnull;
1919  rv =
1920  observerService->RemoveObserver(this,
1922  NS_ENSURE_SUCCESS(rv, rv);
1923 #endif
1924  }
1925 
1926  return NS_OK;
1927 }
1928 
1929 //-----------------------------------------------------------------------------
1930 // sbIMediacoreEventListener
1931 //-----------------------------------------------------------------------------
1932 NS_IMETHODIMP
1933 sbPlaybackHistoryService::OnMediacoreEvent(sbIMediacoreEvent *aEvent)
1934 {
1935  NS_ENSURE_ARG_POINTER(aEvent);
1936 
1937  PRUint32 eventType = 0;
1938  nsresult rv = aEvent->GetType(&eventType);
1939  NS_ENSURE_SUCCESS(rv, rv);
1940 
1941  nsAutoMonitor mon(mMonitor);
1942 
1943  switch(eventType) {
1945  if(mCurrentlyTracking && !mCurrentStartTime) {
1946  mCurrentStartTime = PR_Now();
1947  }
1948 
1949  if(mCurrentlyTracking && mCurrentStartTime && mCurrentPauseTime) {
1950  mCurrentDelta = mCurrentDelta + (PR_Now() - mCurrentPauseTime);
1951  mCurrentPauseTime = 0;
1952  }
1953  }
1954  break;
1955 
1957  if(mCurrentlyTracking && mCurrentStartTime && !mCurrentPauseTime) {
1958  mCurrentPauseTime = PR_Now();
1959  }
1960  }
1961  break;
1962 
1965  if(mCurrentlyTracking && mCurrentStartTime) {
1967  NS_ASSERTION(NS_SUCCEEDED(rv), "Entry won't be created.");
1968 
1969  rv = ResetTrackingData();
1970  NS_ENSURE_SUCCESS(rv, rv);
1971  }
1972  }
1973  break;
1974 
1976  // already tracking, check to see if we should add an entry for the
1977  // current item before starting to track the next one.
1978  if(mCurrentlyTracking) {
1980  if(NS_FAILED(rv)) {
1981  rv = ResetTrackingData();
1982  NS_ENSURE_SUCCESS(rv, rv);
1983  }
1984  }
1985 
1986  rv = UpdateTrackingDataFromEvent(aEvent);
1987  NS_ENSURE_SUCCESS(rv, rv);
1988  }
1989  break;
1990 
1992  // we need to keep track of the current view for metrics
1993  rv = UpdateCurrentViewFromEvent(aEvent);
1994  NS_ENSURE_SUCCESS(rv, rv);
1995  }
1996  break;
1997  }
1998 
1999  return NS_OK;
2000 }
2001 
2002 //-----------------------------------------------------------------------------
2003 // sbIPlaybackHistoryService
2004 //-----------------------------------------------------------------------------
2005 NS_IMETHODIMP
2006 sbPlaybackHistoryService::GetEntries(nsISimpleEnumerator * *aEntries)
2007 {
2008  NS_ENSURE_ARG_POINTER(aEntries);
2009 
2010  nsCOMPtr<sbIDatabaseQuery> query;
2011  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2012  NS_ENSURE_SUCCESS(rv, rv);
2013 
2014  rv = query->AddQuery(mGetAllEntriesQuery);
2015  NS_ENSURE_SUCCESS(rv, rv);
2016 
2017  PRInt32 dbError = 0;
2018  rv = query->Execute(&dbError);
2019  NS_ENSURE_SUCCESS(rv, rv);
2020  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2021 
2022  nsCOMPtr<sbIDatabaseResult> result;
2023  rv = query->GetResultObject(getter_AddRefs(result));
2024  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2025 
2026  nsCOMPtr<nsIArray> array;
2027  rv = CreateEntriesFromResultSet(result, getter_AddRefs(array));
2028  NS_ENSURE_SUCCESS(rv, rv);
2029 
2030  rv = array->Enumerate(aEntries);
2031  NS_ENSURE_SUCCESS(rv, rv);
2032 
2033  return NS_OK;
2034 }
2035 
2036 NS_IMETHODIMP
2037 sbPlaybackHistoryService::GetEntryCount(PRUint64 *aEntryCount)
2038 {
2039  NS_ENSURE_ARG_POINTER(aEntryCount);
2040 
2041  nsCOMPtr<sbIDatabaseQuery> query;
2042  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2043  NS_ENSURE_SUCCESS(rv, rv);
2044 
2045  rv = query->AddQuery(mGetEntryCountQuery);
2046  NS_ENSURE_SUCCESS(rv, rv);
2047 
2048  PRInt32 dbError = 0;
2049  rv = query->Execute(&dbError);
2050  NS_ENSURE_SUCCESS(rv, rv);
2051  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2052 
2053  nsCOMPtr<sbIDatabaseResult> result;
2054  rv = query->GetResultObject(getter_AddRefs(result));
2055  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2056 
2057  PRUint32 rowCount;
2058  rv = result->GetRowCount(&rowCount);
2059  NS_ENSURE_SUCCESS(rv, rv);
2060 
2061  // Make sure we get one row back
2062  NS_ENSURE_TRUE(rowCount == 1, NS_ERROR_UNEXPECTED);
2063 
2064  nsAutoString countStr;
2065  rv = result->GetRowCell(0, 0, countStr);
2066  NS_ENSURE_SUCCESS(rv, rv);
2067 
2068  *aEntryCount = nsString_ToUint64(countStr, &rv);
2069  NS_ENSURE_SUCCESS(rv, rv);
2070 
2071  return NS_OK;
2072 }
2073 
2074 NS_IMETHODIMP
2075 sbPlaybackHistoryService::CreateEntry(sbIMediaItem *aItem,
2076  PRInt64 aTimestamp,
2077  PRInt64 aDuration,
2078  sbIPropertyArray *aAnnotations,
2079  sbIPlaybackHistoryEntry **_retval)
2080 {
2081  nsresult rv = NS_ERROR_UNEXPECTED;
2082 
2083  nsCOMPtr<sbIPlaybackHistoryEntry> entry =
2084  do_CreateInstance(SB_PLAYBACKHISTORYENTRY_CONTRACTID, &rv);
2085  NS_ENSURE_SUCCESS(rv, rv);
2086 
2087  rv = entry->Init(aItem, aTimestamp, aDuration, aAnnotations);
2088  NS_ENSURE_SUCCESS(rv, rv);
2089 
2090  entry.forget(_retval);
2091 
2092  return NS_OK;
2093 }
2094 
2095 NS_IMETHODIMP
2096 sbPlaybackHistoryService::AddEntry(sbIPlaybackHistoryEntry *aEntry)
2097 {
2098  NS_ENSURE_ARG_POINTER(aEntry);
2099 
2100  nsCOMPtr<sbIDatabaseQuery> query;
2101  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2102  NS_ENSURE_SUCCESS(rv, rv);
2103 
2104  rv = query->AddQuery(mAddEntryQuery);
2105  NS_ENSURE_SUCCESS(rv, rv);
2106 
2107  rv = FillAddQueryParameters(query, aEntry);
2108  NS_ENSURE_SUCCESS(rv, rv);
2109 
2110  rv = FillAddAnnotationsQueryParameters(query, aEntry);
2111  NS_ENSURE_SUCCESS(rv, rv);
2112 
2113  PRInt32 dbError = 0;
2114  rv = query->Execute(&dbError);
2115  NS_ENSURE_SUCCESS(rv, rv);
2116  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2117 
2118  nsCOMPtr<sbIDatabaseResult> result;
2119  rv = query->GetResultObject(getter_AddRefs(result));
2120  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2121 
2122  nsAutoString entryIdStr;
2123  rv = result->GetRowCell(0, 0, entryIdStr);
2124  NS_ENSURE_SUCCESS(rv, rv);
2125 
2126  PRInt64 entryId = nsString_ToUint64(entryIdStr, &rv);
2127  NS_ENSURE_SUCCESS(rv, rv);
2128 
2129  aEntry->SetEntryId(entryId);
2130 
2131  rv = DoEntryAddedCallback(aEntry);
2132  NS_ENSURE_SUCCESS(rv, rv);
2133 
2134  return NS_OK;
2135 }
2136 
2137 NS_IMETHODIMP
2138 sbPlaybackHistoryService::AddEntries(nsIArray *aEntries)
2139 {
2140  NS_ENSURE_ARG_POINTER(aEntries);
2141 
2142  nsCOMPtr<sbIDatabaseQuery> query;
2143  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2144  NS_ENSURE_SUCCESS(rv, rv);
2145 
2146  rv = query->AddQuery(NS_LITERAL_STRING("BEGIN"));
2147  NS_ENSURE_SUCCESS(rv, rv);
2148 
2149  PRUint32 length = 0;
2150  rv = aEntries->GetLength(&length);
2151 
2152  for(PRUint32 current = 0; current < length; ++current) {
2153  nsCOMPtr<sbIPlaybackHistoryEntry> entry =
2154  do_QueryElementAt(aEntries, current, &rv);
2155  NS_ENSURE_SUCCESS(rv, rv);
2156 
2157  rv = query->AddQuery(mAddEntryQuery);
2158  NS_ENSURE_SUCCESS(rv, rv);
2159 
2160  rv = FillAddQueryParameters(query, entry);
2161  NS_ENSURE_SUCCESS(rv, rv);
2162 
2163  rv = FillAddAnnotationsQueryParameters(query, entry);
2164  NS_ENSURE_SUCCESS(rv, rv);
2165  }
2166 
2167  rv = query->AddQuery(NS_LITERAL_STRING("COMMIT"));
2168  NS_ENSURE_SUCCESS(rv, rv);
2169 
2170  PRInt32 dbError = 0;
2171  rv = query->Execute(&dbError);
2172  NS_ENSURE_SUCCESS(rv, rv);
2173  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2174 
2175  nsCOMPtr<sbIDatabaseResult> result;
2176  rv = query->GetResultObject(getter_AddRefs(result));
2177  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2178 
2179  PRUint32 rowCount = 0;
2180  rv = result->GetRowCount(&rowCount);
2181  NS_ENSURE_SUCCESS(rv, rv);
2182 
2183  NS_ENSURE_TRUE(length == rowCount, NS_ERROR_UNEXPECTED);
2184 
2185  for(PRUint32 currentRow = 0; currentRow < rowCount; ++currentRow) {
2186  nsString entryIdStr;
2187 
2188  rv = result->GetRowCell(currentRow, 0, entryIdStr);
2189  NS_ENSURE_SUCCESS(rv, rv);
2190 
2191  nsCOMPtr<sbIPlaybackHistoryEntry> entry =
2192  do_QueryElementAt(aEntries, currentRow, &rv);
2193  NS_ENSURE_SUCCESS(rv, rv);
2194 
2195  PRInt64 entryId = nsString_ToUint64(entryIdStr, &rv);
2196  NS_ENSURE_SUCCESS(rv, rv);
2197 
2198  entry->SetEntryId(entryId);
2199  }
2200 
2201  rv = DoEntriesAddedCallback(aEntries);
2202  NS_ENSURE_SUCCESS(rv, rv);
2203 
2204  return NS_OK;
2205 }
2206 
2207 NS_IMETHODIMP
2208 sbPlaybackHistoryService::GetEntryByIndex(PRInt64 aIndex,
2209  sbIPlaybackHistoryEntry **_retval)
2210 {
2211  NS_ENSURE_ARG_POINTER(_retval);
2212 
2213  nsCOMPtr<sbIDatabaseQuery> query;
2214  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2215  NS_ENSURE_SUCCESS(rv, rv);
2216 
2217  PRInt64 actualIndex = aIndex;
2218  if(actualIndex >= 0) {
2219  rv = query->AddQuery(mGetEntriesByIndexQuery);
2220  NS_ENSURE_SUCCESS(rv, rv);
2221  }
2222  else {
2223  rv = query->AddQuery(mGetEntriesByIndexQueryAscending);
2224  NS_ENSURE_SUCCESS(rv, rv);
2225 
2226  actualIndex = PR_ABS(actualIndex) - 1;
2227  }
2228 
2229  rv = query->BindInt64Parameter(0, 1);
2230  NS_ENSURE_SUCCESS(rv, rv);
2231 
2232  rv = query->BindInt64Parameter(1, actualIndex);
2233  NS_ENSURE_SUCCESS(rv, rv);
2234 
2235  PRInt32 dbError = 0;
2236  rv = query->Execute(&dbError);
2237  NS_ENSURE_SUCCESS(rv, rv);
2238  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2239 
2240  nsCOMPtr<sbIDatabaseResult> result;
2241  rv = query->GetResultObject(getter_AddRefs(result));
2242  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2243 
2244  rv = CreateEntryFromResultSet(result, 0, _retval);
2245  NS_ENSURE_SUCCESS(rv, rv);
2246 
2247  return NS_OK;
2248 }
2249 
2250 NS_IMETHODIMP
2251 sbPlaybackHistoryService::GetEntriesByIndex(PRInt64 aStartIndex,
2252  PRUint64 aCount,
2253  nsIArray **_retval)
2254 {
2255  NS_ENSURE_ARG_POINTER(_retval);
2256 
2257  nsCOMPtr<sbIDatabaseQuery> query;
2258  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2259  NS_ENSURE_SUCCESS(rv, rv);
2260 
2261  PRInt64 actualIndex = aStartIndex;
2262  if( actualIndex >= 0) {
2263  rv = query->AddQuery(mGetEntriesByIndexQuery);
2264  NS_ENSURE_SUCCESS(rv, rv);
2265  }
2266  else {
2267  rv = query->AddQuery(mGetEntriesByIndexQueryAscending);
2268  NS_ENSURE_SUCCESS(rv, rv);
2269 
2270  actualIndex = PR_ABS(actualIndex) - 1;
2271  }
2272 
2273  rv = query->BindInt64Parameter(0, aCount);
2274  NS_ENSURE_SUCCESS(rv, rv);
2275 
2276  rv = query->BindInt64Parameter(1, actualIndex);
2277  NS_ENSURE_SUCCESS(rv, rv);
2278 
2279  PRInt32 dbError = 0;
2280  rv = query->Execute(&dbError);
2281  NS_ENSURE_SUCCESS(rv, rv);
2282  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2283 
2284  nsCOMPtr<sbIDatabaseResult> result;
2285  rv = query->GetResultObject(getter_AddRefs(result));
2286  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2287 
2288  rv = CreateEntriesFromResultSet(result, _retval);
2289  NS_ENSURE_SUCCESS(rv, rv);
2290 
2291  return NS_OK;
2292 }
2293 
2294 NS_IMETHODIMP
2295 sbPlaybackHistoryService::GetEntriesByTimestamp(PRInt64 aStartTimestamp,
2296  PRInt64 aEndTimestamp,
2297  nsIArray **_retval)
2298 {
2299  NS_ENSURE_ARG_POINTER(_retval);
2300 
2301  PRBool isAscending = aStartTimestamp > aEndTimestamp;
2302 
2303  nsCOMPtr<sbIDatabaseQuery> query;
2304  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2305  NS_ENSURE_SUCCESS(rv, rv);
2306 
2307  if(!isAscending) {
2308  rv = query->AddQuery(mGetEntriesByTimestampQuery);
2309  NS_ENSURE_SUCCESS(rv, rv);
2310 
2311  rv = query->BindInt64Parameter(0, aStartTimestamp);
2312  NS_ENSURE_SUCCESS(rv, rv);
2313 
2314  rv = query->BindInt64Parameter(1, aEndTimestamp);
2315  NS_ENSURE_SUCCESS(rv, rv);
2316  }
2317  else {
2318  rv = query->AddQuery(mGetEntriesByTimestampQueryAscending);
2319  NS_ENSURE_SUCCESS(rv, rv);
2320 
2321  rv = query->BindInt64Parameter(0, aEndTimestamp);
2322  NS_ENSURE_SUCCESS(rv, rv);
2323 
2324  rv = query->BindInt64Parameter(1, aStartTimestamp);
2325  NS_ENSURE_SUCCESS(rv, rv);
2326  }
2327 
2328  PRInt32 dbError = 0;
2329  rv = query->Execute(&dbError);
2330  NS_ENSURE_SUCCESS(rv, rv);
2331  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2332 
2333  nsCOMPtr<sbIDatabaseResult> result;
2334  rv = query->GetResultObject(getter_AddRefs(result));
2335  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2336 
2337  rv = CreateEntriesFromResultSet(result, _retval);
2338  NS_ENSURE_SUCCESS(rv, rv);
2339 
2340  return NS_OK;
2341 }
2342 
2343 NS_IMETHODIMP
2344 sbPlaybackHistoryService::RemoveEntry(sbIPlaybackHistoryEntry *aEntry)
2345 {
2346  NS_ENSURE_ARG_POINTER(aEntry);
2347 
2348  nsCOMPtr<sbIDatabaseQuery> query;
2349  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2350  NS_ENSURE_SUCCESS(rv, rv);
2351 
2352  rv = query->AddQuery(mRemoveEntriesQuery);
2353  NS_ENSURE_SUCCESS(rv, rv);
2354 
2355  rv = FillRemoveEntryQueryParameters(query, aEntry);
2356  NS_ENSURE_SUCCESS(rv, rv);
2357 
2358  rv = query->AddQuery(mRemoveAnnotationsQuery);
2359  NS_ENSURE_SUCCESS(rv, rv);
2360 
2361  PRInt64 entryId = -1;
2362  rv = aEntry->GetEntryId(&entryId);
2363  NS_ENSURE_SUCCESS(rv, rv);
2364 
2365  rv = query->BindInt64Parameter(0, entryId);
2366  NS_ENSURE_SUCCESS(rv, rv);
2367 
2368  PRInt32 dbError = 0;
2369  rv = query->Execute(&dbError);
2370  NS_ENSURE_SUCCESS(rv, rv);
2371  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2372 
2373  rv = DoEntryRemovedCallback(aEntry);
2374  NS_ENSURE_SUCCESS(rv, rv);
2375 
2376  return NS_OK;
2377 }
2378 
2379 NS_IMETHODIMP
2380 sbPlaybackHistoryService::RemoveEntryByIndex(PRInt64 aIndex)
2381 {
2382  nsCOMPtr<sbIPlaybackHistoryEntry> entry;
2383 
2384  nsresult rv = GetEntryByIndex(aIndex, getter_AddRefs(entry));
2385  NS_ENSURE_SUCCESS(rv, rv);
2386 
2387  rv = RemoveEntry(entry);
2388  NS_ENSURE_SUCCESS(rv, rv);
2389 
2390  rv = DoEntryRemovedCallback(entry);
2391  NS_ENSURE_SUCCESS(rv, rv);
2392 
2393  return NS_OK;
2394 }
2395 
2396 NS_IMETHODIMP
2397 sbPlaybackHistoryService::RemoveEntriesByIndex(PRInt64 aStartIndex,
2398  PRUint64 aCount)
2399 {
2400  nsCOMPtr<nsIArray> entries;
2401 
2402  nsresult rv = GetEntriesByIndex(aStartIndex, aCount, getter_AddRefs(entries));
2403  NS_ENSURE_SUCCESS(rv, rv);
2404 
2405  rv = RemoveEntries(entries);
2406  NS_ENSURE_SUCCESS(rv, rv);
2407 
2408  rv = DoEntriesRemovedCallback(entries);
2409  NS_ENSURE_SUCCESS(rv, rv);
2410 
2411  return NS_OK;
2412 }
2413 
2414 NS_IMETHODIMP
2415 sbPlaybackHistoryService::RemoveEntries(nsIArray *aEntries)
2416 {
2417  NS_ENSURE_ARG_POINTER(aEntries);
2418 
2419  nsCOMPtr<sbIDatabaseQuery> query;
2420  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2421  NS_ENSURE_SUCCESS(rv, rv);
2422 
2423  PRUint32 length = 0;
2424  rv = aEntries->GetLength(&length);
2425  NS_ENSURE_SUCCESS(rv, rv);
2426 
2427  rv = query->AddQuery(NS_LITERAL_STRING("BEGIN"));
2428  NS_ENSURE_SUCCESS(rv, rv);
2429 
2430  for(PRUint32 current = 0; current < length; ++current) {
2431  nsCOMPtr<sbIPlaybackHistoryEntry> entry =
2432  do_QueryElementAt(aEntries, current, &rv);
2433  NS_ENSURE_SUCCESS(rv, rv);
2434 
2435  rv = query->AddQuery(mRemoveEntriesQuery);
2436  NS_ENSURE_SUCCESS(rv, rv);
2437 
2438  rv = FillRemoveEntryQueryParameters(query, entry);
2439  NS_ENSURE_SUCCESS(rv, rv);
2440  }
2441 
2442  rv = query->AddQuery(NS_LITERAL_STRING("COMMIT"));
2443  NS_ENSURE_SUCCESS(rv, rv);
2444 
2445  PRInt32 dbError = 0;
2446  rv = query->Execute(&dbError);
2447  NS_ENSURE_SUCCESS(rv, rv);
2448  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2449 
2450  rv = DoEntriesRemovedCallback(aEntries);
2451  NS_ENSURE_SUCCESS(rv, rv);
2452 
2453  return NS_OK;
2454 }
2455 
2456 NS_IMETHODIMP
2457 sbPlaybackHistoryService::GetEntriesByAnnotation(
2458  const nsAString & aAnnotationId,
2459  const nsAString & aAnnotationValue,
2460  PRUint32 aCount,
2461  nsIArray **_retval)
2462 {
2463  NS_ENSURE_ARG_POINTER(_retval);
2464 
2465  nsString sql;
2466  sql.AssignLiteral("select entry_id, library_guid, media_item_guid, play_time, play_duration from ");
2467  sql.AppendLiteral(PLAYBACKHISTORY_ENTRIES_TABLE);
2468  sql.AppendLiteral(" where entry_id in ( ");
2469 
2470  sql.AppendLiteral("select entry_id from ");
2471  sql.AppendLiteral(PLAYBACKHISTORY_ANNOTATIONS_TABLE);
2472  sql.AppendLiteral(" where property_id = ? and obj = ? ");
2473 
2474  if(aCount > 0) {
2475  sql.AppendLiteral(" limit ?");
2476  }
2477 
2478  sql.AppendLiteral(" ) ");
2479  sql.AppendLiteral("order by play_time desc");
2480 
2481  PRUint32 propertyId = 0;
2482  nsresult rv = GetPropertyDBID(aAnnotationId, &propertyId);
2483  NS_ENSURE_SUCCESS(rv, rv);
2484 
2485  nsCOMPtr<sbIDatabaseQuery> query;
2486  rv = CreateDefaultQuery(getter_AddRefs(query));
2487  NS_ENSURE_SUCCESS(rv, rv);
2488 
2489  rv = query->AddQuery(sql);
2490  NS_ENSURE_SUCCESS(rv, rv);
2491 
2492  rv = query->BindInt32Parameter(0, propertyId);
2493  NS_ENSURE_SUCCESS(rv, rv);
2494 
2495  rv = query->BindStringParameter(1, aAnnotationValue);
2496  NS_ENSURE_SUCCESS(rv, rv);
2497 
2498  if(aCount > 0) {
2499  rv = query->BindInt32Parameter(2, aCount);
2500  }
2501 
2502  PRInt32 dbError = 0;
2503  rv = query->Execute(&dbError);
2504  NS_ENSURE_SUCCESS(rv, rv);
2505  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2506 
2507  nsCOMPtr<sbIDatabaseResult> result;
2508  rv = query->GetResultObject(getter_AddRefs(result));
2509  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2510 
2511  rv = CreateEntriesFromResultSet(result, _retval);
2512  NS_ENSURE_SUCCESS(rv, rv);
2513 
2514  return NS_OK;
2515 }
2516 
2517 NS_IMETHODIMP
2518 sbPlaybackHistoryService::GetEntriesByAnnotations(
2519  sbIPropertyArray *aAnnotations,
2520  PRUint32 aCount,
2521  nsIArray **_retval)
2522 {
2523  NS_ENSURE_ARG_POINTER(aAnnotations);
2524  NS_ENSURE_ARG_POINTER(_retval);
2525 
2526  nsString sql;
2527  sql.AssignLiteral("select entry_id, library_guid, media_item_guid, play_time, play_duration from ");
2528  sql.AppendLiteral(PLAYBACKHISTORY_ENTRIES_TABLE);
2529  sql.AppendLiteral(" where entry_id in ( ");
2530 
2531  sql.AppendLiteral("select entry_id from ");
2532  sql.AppendLiteral(PLAYBACKHISTORY_ANNOTATIONS_TABLE);
2533  sql.AppendLiteral(" where property_id = ? and obj = ? ");
2534 
2535  PRUint32 length = 0;
2536  nsresult rv = aAnnotations->GetLength(&length);
2537  NS_ENSURE_SUCCESS(rv, rv);
2538 
2539  for(PRUint32 current = 0; current < length - 1; ++current) {
2540  sql.AppendLiteral(" or property_id = ? and obj = ? ");
2541  }
2542 
2543  if(aCount > 0) {
2544  sql.AppendLiteral(" limit ?");
2545  }
2546 
2547  sql.AppendLiteral(" ) ");
2548  sql.AppendLiteral(" order by play_time desc");
2549 
2550  nsCOMPtr<sbIDatabaseQuery> query;
2551  rv = CreateDefaultQuery(getter_AddRefs(query));
2552  NS_ENSURE_SUCCESS(rv, rv);
2553 
2554  rv = query->AddQuery(sql);
2555  NS_ENSURE_SUCCESS(rv, rv);
2556 
2557  for(PRUint32 current = 0, currentEntry = 0;
2558  current < length * 2;
2559  current += 2, ++currentEntry) {
2560 
2561  nsCOMPtr<sbIProperty> property;
2562  rv = aAnnotations->GetPropertyAt(currentEntry, getter_AddRefs(property));
2563  NS_ENSURE_SUCCESS(rv, rv);
2564 
2565  nsString annotationId;
2566  rv = property->GetId(annotationId);
2567  NS_ENSURE_SUCCESS(rv, rv);
2568 
2569  nsString annotationValue;
2570  rv = property->GetValue(annotationValue);
2571  NS_ENSURE_SUCCESS(rv, rv);
2572 
2573  PRUint32 propertyId = 0;
2574  rv = GetPropertyDBID(annotationId, &propertyId);
2575  NS_ENSURE_SUCCESS(rv, rv);
2576 
2577  rv = query->BindInt32Parameter(current, propertyId);
2578  NS_ENSURE_SUCCESS(rv, rv);
2579 
2580  rv = query->BindStringParameter(current + 1, annotationValue);
2581  NS_ENSURE_SUCCESS(rv, rv);
2582  }
2583 
2584  if(aCount > 0) {
2585  rv = query->BindInt32Parameter(length * 2, aCount);
2586  }
2587 
2588  PRInt32 dbError = 0;
2589  rv = query->Execute(&dbError);
2590  NS_ENSURE_SUCCESS(rv, rv);
2591  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2592 
2593  nsCOMPtr<sbIDatabaseResult> result;
2594  rv = query->GetResultObject(getter_AddRefs(result));
2595  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2596 
2597  rv = CreateEntriesFromResultSet(result, _retval);
2598  NS_ENSURE_SUCCESS(rv, rv);
2599 
2600  return NS_OK;
2601 }
2602 
2603 NS_IMETHODIMP
2604 sbPlaybackHistoryService::Clear()
2605 {
2606  nsCOMPtr<sbIDatabaseQuery> query;
2607  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2608  NS_ENSURE_SUCCESS(rv, rv);
2609 
2610  rv = query->AddQuery(mRemoveAllEntriesQuery);
2611  NS_ENSURE_SUCCESS(rv, rv);
2612 
2613  rv = query->AddQuery(mRemoveAllAnnotationsQuery);
2614  NS_ENSURE_SUCCESS(rv, rv);
2615 
2616  PRInt32 dbError = 0;
2617  rv = query->Execute(&dbError);
2618  NS_ENSURE_SUCCESS(rv, rv);
2619  NS_ENSURE_TRUE(dbError == 0, NS_ERROR_FAILURE);
2620 
2621  rv = DoEntriesClearedCallback();
2622  NS_ENSURE_SUCCESS(rv, rv);
2623 
2624  return NS_OK;
2625 }
2626 
2627 NS_IMETHODIMP
2628 sbPlaybackHistoryService::AddListener(sbIPlaybackHistoryListener *aListener)
2629 {
2630  NS_ENSURE_ARG_POINTER(aListener);
2631 
2632  // Make a proxy for the listener that will always send callbacks to the
2633  // current thread.
2634  nsCOMPtr<nsIThread> target;
2635  nsresult rv = NS_GetCurrentThread(getter_AddRefs(target));
2636  NS_ENSURE_SUCCESS(rv, rv);
2637 
2638  nsCOMPtr<sbIPlaybackHistoryListener> proxy;
2639  rv = do_GetProxyForObject(target,
2640  NS_GET_IID(sbIPlaybackHistoryListener),
2641  aListener,
2642  NS_PROXY_SYNC | NS_PROXY_ALWAYS,
2643  getter_AddRefs(proxy));
2644  NS_ENSURE_SUCCESS(rv, rv);
2645 
2646  // Add the proxy to the hash table, using the listener as the key.
2647  PRBool success = mListeners.Put(aListener, proxy);
2648  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
2649 
2650  return NS_OK;
2651 }
2652 
2653 NS_IMETHODIMP
2654 sbPlaybackHistoryService::RemoveListener(sbIPlaybackHistoryListener *aListener)
2655 {
2656  NS_ENSURE_ARG_POINTER(aListener);
2657  mListeners.Remove(aListener);
2658  return NS_OK;
2659 }
2660 
2661 nsresult
2662 sbPlaybackHistoryService::AddOrUpdateAnnotation(
2663  PRInt64 aEntryId,
2664  const nsAString &aAnnotationId,
2665  const nsAString &aAnnotationValue)
2666 {
2667  nsresult rv = NS_ERROR_UNEXPECTED;
2668  nsCOMPtr<sbIPropertyManager> propMan =
2669  do_GetService(SB_PROPERTYMANAGER_CONTRACTID, &rv);
2670  NS_ENSURE_SUCCESS(rv, rv);
2671 
2672  nsCOMPtr<sbIPropertyInfo> propertyInfo;
2673  rv = propMan->GetPropertyInfo(aAnnotationId, getter_AddRefs(propertyInfo));
2674  NS_ENSURE_SUCCESS(rv, rv);
2675 
2676  nsAutoString sortableValue;
2677  rv = propertyInfo->MakeSortable(aAnnotationValue, sortableValue);
2678  NS_ENSURE_SUCCESS(rv, rv);
2679 
2680  PRUint32 propertyId = 0;
2681  rv = GetPropertyDBID(aAnnotationId, &propertyId);
2682  NS_ENSURE_SUCCESS(rv, rv);
2683 
2684  nsCOMPtr<sbIDatabaseQuery> query;
2685  rv = CreateDefaultQuery(getter_AddRefs(query));
2686  NS_ENSURE_SUCCESS(rv, rv);
2687 
2688  rv = query->AddQuery(mIsAnnotationPresentQuery);
2689  NS_ENSURE_SUCCESS(rv, rv);
2690 
2691  rv = query->BindInt64Parameter(0, aEntryId);
2692  NS_ENSURE_SUCCESS(rv, rv);
2693 
2694  rv = query->BindInt32Parameter(1, propertyId);
2695  NS_ENSURE_SUCCESS(rv, rv);
2696 
2697  PRInt32 dbOk = 0;
2698  rv = query->Execute(&dbOk);
2699  NS_ENSURE_SUCCESS(rv, rv);
2700  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2701 
2702  nsCOMPtr<sbIDatabaseResult> result;
2703  rv = query->GetResultObject(getter_AddRefs(result));
2704  NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2705 
2706  PRUint32 rowCount = 0;
2707  rv = result->GetRowCount(&rowCount);
2708  NS_ENSURE_SUCCESS(rv, rv);
2709 
2710  rv = query->ResetQuery();
2711  NS_ENSURE_SUCCESS(rv, rv);
2712 
2713  if(rowCount == 1) {
2714  rv = query->AddQuery(mUpdateAnnotationQuery);
2715  NS_ENSURE_SUCCESS(rv, rv);
2716 
2717  rv = query->BindInt32Parameter(0, propertyId);
2718  NS_ENSURE_SUCCESS(rv, rv);
2719 
2720  rv = query->BindStringParameter(1, aAnnotationValue);
2721  NS_ENSURE_SUCCESS(rv, rv);
2722 
2723  rv = query->BindStringParameter(2, sortableValue);
2724  NS_ENSURE_SUCCESS(rv, rv);
2725 
2726  rv = query->BindInt64Parameter(3, aEntryId);
2727  NS_ENSURE_SUCCESS(rv, rv);
2728  }
2729  else {
2730  rv = query->AddQuery(mInsertAnnotationQuery);
2731  NS_ENSURE_SUCCESS(rv, rv);
2732 
2733  rv = query->BindInt64Parameter(0, aEntryId);
2734  NS_ENSURE_SUCCESS(rv, rv);
2735 
2736  rv = query->BindInt32Parameter(1, propertyId);
2737  NS_ENSURE_SUCCESS(rv, rv);
2738 
2739  rv = query->BindStringParameter(2, aAnnotationValue);
2740  NS_ENSURE_SUCCESS(rv, rv);
2741 
2742  rv = query->BindStringParameter(3, sortableValue);
2743  NS_ENSURE_SUCCESS(rv, rv);
2744  }
2745 
2746 
2747  rv = query->Execute(&dbOk);
2748  NS_ENSURE_SUCCESS(rv, rv);
2749  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2750 
2751  return NS_OK;
2752 }
2753 
2754 nsresult
2755 sbPlaybackHistoryService::RemoveAnnotation(PRInt64 aEntryId,
2756  const nsAString &aAnnotationId)
2757 {
2758  nsCOMPtr<sbIDatabaseQuery> query;
2759  nsresult rv = CreateDefaultQuery(getter_AddRefs(query));
2760  NS_ENSURE_SUCCESS(rv, rv);
2761 
2762  rv = query->AddQuery(mRemoveAnnotationQuery);
2763  NS_ENSURE_SUCCESS(rv, rv);
2764 
2765  rv = query->BindInt64Parameter(0, aEntryId);
2766  NS_ENSURE_SUCCESS(rv, rv);
2767 
2768  PRUint32 propertyId = 0;
2769  rv = GetPropertyDBID(aAnnotationId, &propertyId);
2770  NS_ENSURE_SUCCESS(rv, rv);
2771 
2772  rv = query->BindInt32Parameter(1, propertyId);
2773  NS_ENSURE_SUCCESS(rv, rv);
2774 
2775  PRInt32 dbOk = 0;
2776  rv = query->Execute(&dbOk);
2777  NS_ENSURE_SUCCESS(rv, rv);
2778  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2779 
2780  return NS_OK;
2781 }
#define METRIC_ITEM
classDescription entry
Definition: FeedWriter.js:1427
nsresult UpdateCurrentViewFromEvent(sbIMediacoreEvent *aEvent)
nsresult FillAddQueryParameters(sbIDatabaseQuery *aQuery, sbIPlaybackHistoryEntry *aEntry)
#define NS_APPSTARTUP_CATEGORY
return NS_OK
_updateCookies aPath
#define SB_PLAYBACKHISTORYSERVICE_DESCRIPTION
#define METRIC_MEDIACORE_ROOT
#define SB_PROPERTY_PLAYCOUNT
const SB_LIBRARY_MANAGER_READY_TOPIC
#define SONGBIRD_DATABASEQUERY_CONTRACTID
Definition: DatabaseQuery.h:63
static nsCOMPtr< nsIObserverService > observerService
Definition: UnityProxy.cpp:6
nsresult DoEntryRemovedCallback(sbIPlaybackHistoryEntry *aEntry)
nsresult DoEntryUpdatedCallback(sbIPlaybackHistoryEntry *aEntry)
menuItem id
Definition: FeedWriter.js:971
#define METRIC_SUBSCRIPTION
#define OBJ_SORTABLE
inArray array
PRUint64 nsString_ToUint64(const nsAString &str, nsresult *rv)
nsresult CreateAnnotationsFromEntryId(PRInt64 aEntryId, sbIPropertyArray **aAnnotations)
#define SB_PLAYBACKHISTORYENTRY_CONTRACTID
const unsigned long TRACK_CHANGE
Track playing has changed.
#define ENTRY_ID_COLUMN
#define OBJ_COLUMN
#define METRIC_PLAYTIME
Total Playtime, in seconds.
#define SB_THREADSAFE_ARRAY_CONTRACTID
Definition: sbArrayUtils.h:40
#define SB_SQLBUILDER_INSERT_CONTRACTID
nsresult DoEntriesRemovedCallback(nsIArray *aEntry)
#define METRIC_ATTEMPT
#define SB_MUTABLEPROPERTYARRAY_CONTRACTID
const unsigned long MATCH_LESSEQUAL
#define MEDIA_ITEM_GUID_COLUMN
nsresult FillRemoveEntryQueryParameters(sbIDatabaseQuery *aQuery, sbIPlaybackHistoryEntry *aEntry)
nsresult do_GetProxyForObject(nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
#define SB_PROPERTY_EXCLUDE_FROM_HISTORY
#define SB_PROPERTY_LASTPLAYTIME
nsresult GetPropertyDBID(const nsAString &aPropertyID, PRUint32 *aPropertyDBID)
nsresult DoEntriesAddedCallback(nsIArray *aEntries)
const unsigned long STREAM_STOP
Stream was stopped.
readonly attribute nsISimpleEnumerator entries
Enumerator of all entries in the playback history service.
nsresult FillAddAnnotationsQueryParameters(sbIDatabaseQuery *aQuery, sbIPlaybackHistoryEntry *aEntry)
#define METRIC_UNKNOWN
#define SB_PROPERTY_BITRATE
#define PROPERTY_NAME_COLUMN
nsresult CreateDefaultQuery(sbIDatabaseQuery **aQuery)
NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_SBIMEDIACOREEVENTLISTENER static NS_DECL_SBIPLAYBACKHISTORYSERVICE NS_METHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
NS_IMPL_THREADSAFE_ISUPPORTS3(sbPlaybackHistoryService, sbIPlaybackHistoryService, sbIMediacoreEventListener, nsIObserver) sbPlaybackHistoryService
#define SB_PROPERTYMANAGER_CONTRACTID
const sbCreateProxiedComponent do_ProxiedCreateInstance(const nsCID &aCID, nsresult *error=0)
nsresult CreateEntriesFromResultSet(sbIDatabaseResult *aResult, nsIArray **aEntries)
#define SB_SQLBUILDER_DELETE_CONTRACTID
Definition of the sbIMediacoreEvent interface.
#define PLAYBACKHISTORY_DB_GUID
#define PLAY_DURATION_COLUMN
#define SB_SQLBUILDER_SELECT_CONTRACTID
_hideDatepicker duration
const unsigned long STREAM_START
Stream has started.
var count
Definition: test_bug7406.js:32
#define LIBRARY_GUID_COLUMN
#define SCHEMA_URL
#define METRIC_STREAMING
const unsigned long VIEW_CHANGE
Sequencer view changed.
#define SB_PROPERTY_DURATION
var libraryManager
#define SB_PLAYBACKHISTORYSERVICE_CONTRACTID
#define METRIC_LIBRARY
An object containing the results of a database SELECT query.
nsresult InsertPropertyID(const nsAString &aPropertyID, PRUint32 *aPropertyDBID)
const PR_UINT32_MAX
Definition: httpd.js:55
const unsigned long STREAM_PAUSE
Stream is now paused.
const unsigned long MATCH_GREATEREQUAL
var getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('Songbird SBProperties playCount
Definition: tuner2.js:40
function url(spec)
var uri
Definition: FeedWriter.js:1135
countRef value
Definition: FeedWriter.js:1423
#define PLAYBACKHISTORY_PROPERTIES_TABLE
#define PLAYBACKHISTORY_ANNOTATIONS_TABLE
static already_AddRefed< nsILocalFile > GetDBFolder()
PRInt64 nsString_ToInt64(const nsAString &str, nsresult *rv)
An object responsible for executing SQL queries on the database.
#define PLAYBACKHISTORY_ENTRIES_TABLE
#define SB_MEDIACOREMANAGER_CONTRACTID
nsresult UpdateTrackingDataFromEvent(sbIMediacoreEvent *aEvent)
#define SB_PROPERTY_LASTSKIPTIME
#define CONVERTER_BUFFER_SIZE
Interface that defines a single item of media in the system.
restoreHistoryPrecursor aCount
#define PROPERTY_ID_COLUMN
#define METRIC_PLAY
nsresult GetItem(const nsAString &aLibraryGuid, const nsAString &aItemGuid, sbIMediaItem **aItem)
#define PLAY_TIME_COLUMN
#define SB_PROPERTY_CUSTOMTYPE
#define PLAYBACKHISTORY_COUNT_ENTRIES
nsresult DoEntryAddedCallback(sbIPlaybackHistoryEntry *aEntry)
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
const unsigned long STREAM_END
End of stream.
#define SONGBIRD_LIBRARYMANAGER_CONTRACTID
Definition: sbLibraryCID.h:28
#define METRIC_MEDIALIST_ROOT
_getSelectedPageStyle s i
nsresult DoEntriesUpdatedCallback(nsIArray *aEntry)
#define METRIC_WEBPLAYLIST
#define SB_PROPERTY_SKIPCOUNT
#define SB_UNUSED_IN_RELEASE(decl)
Definition: sbDebugUtils.h:55
nsresult CreateEntryFromResultSet(sbIDatabaseResult *aResult, PRUint32 aRow, sbIPlaybackHistoryEntry **aEntry)
const SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC
const unsigned long MATCH_EQUALS
_updateTextAndScrollDataForFrame aData
static PLDHashOperator PR_CALLBACK AddListenersToCOMArrayCallback(nsISupportsHashKey::KeyType aKey, sbIPlaybackHistoryListener *aEntry, void *aUserData)
var file
#define METRIC_BITRATE
Songbird Database Object Definition.