27 Components.utils.import(
"resource://gre/modules/XPCOMUtils.jsm");
28 Components.utils.import(
"resource://app/jsmodules/ArrayConverter.jsm");
29 Components.utils.import(
"resource://app/jsmodules/sbProperties.jsm");
30 Components.utils.import(
"resource://app/jsmodules/sbLibraryUtils.jsm");
32 const Cc = Components.classes;
33 const Ci = Components.interfaces;
34 const Cr = Components.results;
36 const SB_NS =
"http://songbirdnest.com/data/1.0#";
71 this._started =
false;
72 this._scheduledLists = {};
73 this._ignoreLibraryNotifications = {};
74 this._libraryBatch =
new LibraryUtils.MultiBatchHelper();
75 this._libraryRefreshPending = {};
77 var obs =
Cc[
"@mozilla.org/observer-service;1"]
78 .getService(
Ci.nsIObserverService);
86 classID: Components.ID(
"{10a07ef5-8ab6-4728-9172-4e609f65b4a2}"),
87 contractID:
"@songbirdnest.com/Songbird/Library/DynamicPlaylistService;1"
91 XPCOMUtils.generateQI([
92 Ci.sbIDynamicPlaylistService,
95 Ci.sbILibraryManagerListener,
96 Ci.sbIMediaListListener
103 function sbDynamicPlaylistService__startup()
105 TRACE(
"sbDynamicPlaylistService::_startup\n");
112 var propMan =
Cc[
"@songbirdnest.com/Songbird/Properties/PropertyManager;1"]
113 .getService(
Ci.sbIPropertyManager);
115 var prop =
Cc[
"@songbirdnest.com/Songbird/Properties/Info/Boolean;1"]
116 .createInstance(
Ci.sbIBooleanPropertyInfo);
118 prop.userViewable =
false;
119 prop.userEditable =
false;
120 prop.remoteReadable =
true;
121 prop.remoteWritable =
true;
122 propMan.addPropertyInfo(prop);
124 prop =
Cc[
"@songbirdnest.com/Songbird/Properties/Info/URI;1"]
125 .createInstance(
Ci.sbIURIPropertyInfo);
127 prop.userViewable =
false;
128 prop.userEditable =
false;
129 prop.remoteReadable =
true;
130 prop.remoteWritable =
true;
131 propMan.addPropertyInfo(prop);
133 var prop =
Cc[
"@songbirdnest.com/Songbird/Properties/Info/Number;1"]
134 .createInstance(
Ci.sbINumberPropertyInfo);
136 prop.userViewable =
false;
137 prop.userEditable =
false;
138 prop.remoteReadable =
true;
139 prop.remoteWritable =
true;
141 propMan.addPropertyInfo(prop);
143 var prop =
Cc[
"@songbirdnest.com/Songbird/Properties/Info/Number;1"]
144 .createInstance(
Ci.sbINumberPropertyInfo);
146 prop.userViewable =
false;
147 prop.userEditable =
false;
148 prop.remoteReadable =
true;
149 prop.remoteWritable =
true;
151 propMan.addPropertyInfo(prop);
154 this.
_timer =
Cc[
"@mozilla.org/timer;1"].createInstance(
Ci.nsITimer);
155 this.
_timer.initWithCallback(
this,
157 Ci.nsITimer.TYPE_REPEATING_SLACK);
161 .getService(
Ci.sbILibraryManager);
162 libraryManager.addListener(
this);
165 var libraries = libraryManager.getLibraries();
166 while (libraries.hasMoreElements()) {
167 var library = libraries.getNext();
168 this.onLibraryRegistered(library);
173 this._updateSubscriptions(
false);
175 this._started =
true;
179 function sbDynamicPlaylistService__shutdown()
181 var obs =
Cc[
"@mozilla.org/observer-service;1"]
182 .getService(
Ci.nsIObserverService);
193 .getService(
Ci.sbILibraryManager);
194 libraryManager.removeListener(
this);
197 var libraries = libraryManager.getLibraries();
198 while (libraries.hasMoreElements()) {
199 this.onLibraryUnregistered(libraries.getNext());
203 this._started =
false;
207 function sbDynamicPlaylistService__scheduleLibrary(aLibrary)
213 onEnumerationBegin:
function() {
215 onEnumeratedItem:
function(list, item) {
216 self._scheduledLists[
FIX(item.guid)] = item;
218 onEnumerationEnd:
function() {
222 var pa =
Cc[
"@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
223 .createInstance(
Ci.sbIMutablePropertyArray);
224 pa.appendProperty(
SB_NS +
"isList",
"1");
227 aLibrary.enumerateItemsByProperties(pa, listener);
232 function sbDynamicPlaylistService__isDynamicPlaylist(aMediaList)
238 function sbDynamicPlaylistService__removeListsFromLibrary(aLibrary)
240 for each (var list
in this._scheduledLists) {
241 if (list.library.equals(aLibrary)) {
242 delete this._scheduledLists[
FIX(list.guid)];
248 function sbDynamicPlaylistService__updateSubscriptions(aForce)
250 var
now = (
new Date()).getTime() * 1000;
251 for each (var list
in this._scheduledLists) {
258 nextRun = this._setNextRun(list);
263 if (aForce || (interval && now > nextRun)) {
265 this._updateList(list);
269 Components.utils.reportError(e);
276 function sbDynamicPlaylistService__updateList(aList)
279 var manager =
Cc[
"@songbirdnest.com/Songbird/PlaylistReaderManager;1"]
280 .getService(
Ci.sbIPlaylistReaderManager);
281 var listener =
Cc[
"@songbirdnest.com/Songbird/PlaylistReaderListener;1"]
282 .createInstance(
Ci.sbIPlaylistReaderListener);
284 var
ioService =
Cc[
"@mozilla.org/network/io-service;1"]
285 .getService(
Ci.nsIIOService);
288 var
observer =
new sbPlaylistReaderListenerObserver(
this, aList);
291 manager.loadPlaylist(uri, aList,
null,
true, listener);
295 function sbDynamicPlaylistService__setNextRun(aList)
297 var now = (
new Date()).getTime() * 1000;
301 var nextRun = now + (interval * 1000 * 1000);
307 function sbDynamicPlaylistService__beginIgnore(aLibrary)
309 var
count = this._ignoreLibraryNotifications[
FIX(aLibrary.guid)];
311 this._ignoreLibraryNotifications[
FIX(aLibrary.guid)] = count + 1;
313 this._ignoreLibraryNotifications[
FIX(aLibrary.guid)] = 1;
317 function sbDynamicPlaylistService__endIgnore(aLibrary)
319 var count = this._ignoreLibraryNotifications[
FIX(aLibrary.guid)];
321 this._ignoreLibraryNotifications[
FIX(aLibrary.guid)] = count - 1;
323 throw Cr.NS_ERROR_FAILURE;
327 function sbDynamicPlaylistService__ignore(aLibrary)
329 var count = this._ignoreLibraryNotifications[
FIX(aLibrary.guid)];
330 return count && count > 0;
335 function sbDynamicPlaylistService_createList(aLibrary,
338 aDestinationDirectory)
342 aIntervalSeconds == 0 ||
343 (aDestinationDirectory && !aDestinationDirectory.isDirectory()))
344 throw Cr.NS_ERROR_INVALID_ARG;
347 this._beginIgnore(aLibrary);
348 var list = aLibrary.createMediaList(
"dynamic");
349 this._scheduledLists[
FIX(list.guid)] = list;
350 this.updateList(list, aUri, aIntervalSeconds, aDestinationDirectory);
353 this._endIgnore(aLibrary);
359 function sbDynamicPlaylistService_createPodcast(aLibrary,
363 if (!aLibrary || !aUri)
364 throw Cr.NS_ERROR_INVALID_ARG;
368 this._beginIgnore(aLibrary);
372 Cc[
"@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
373 .createInstance(
Ci.sbIMutablePropertyArray);
375 var propertyCount = aProperties.length;
376 for (var
i = 0;
i < propertyCount;
i++) {
377 var
property = aProperties.getPropertyAt(
i);
378 properties.appendProperty(property.id, property.value);
383 properties.appendProperty(SBProperties.customType,
"podcast");
384 var list = aLibrary.createMediaList(
"dynamic", properties);
388 list.name = aUri.host;
395 this._endIgnore(aLibrary);
401 function sbDynamicPlaylistService_updateList(aMediaList,
404 aDestinationDirectory)
407 !this._isDynamicPlaylist(aMediaList) ||
409 aIntervalSeconds == 0 ||
410 (aDestinationDirectory && !aDestinationDirectory.isDirectory()))
411 throw Cr.NS_ERROR_INVALID_ARG;
414 this._beginIgnore(aMediaList.library);
418 if (aDestinationDirectory) {
419 var ioService =
Cc[
"@mozilla.org/network/io-service;1"]
420 .getService(
Ci.nsIIOService);
421 var destinationUri = ioService.newFileURI(aDestinationDirectory);
426 this._endIgnore(aMediaList.library);
432 function sbDynamicPlaylistService_updateAllNow()
434 this._updateSubscriptions(
true);
438 function sbDynamicPlaylistService_updateNow(aMediaList)
443 this._updateList(aMediaList);
445 throw Cr.NS_ERROR_INVALID_ARG;
449 function sbDynamicPlaylistService_scheduledLists()
452 for each (var list
in this._scheduledLists) {
456 return ArrayConverter.enumerator(a);
461 function sbDynamicPlaylistService_onLibraryRegistered(aLibrary)
463 TRACE(
"sbDynamicPlaylistService::onLibraryRegistered");
468 aLibrary.addListener(
this,
470 Ci.sbIMediaList.LISTENER_FLAGS_ALL &
471 ~
Ci.sbIMediaList.LISTENER_FLAGS_AFTERITEMREMOVED,
475 this._scheduleLibrary(aLibrary);
479 function sbDynamicPlaylistService_onLibraryUnregistered(aLibrary)
481 TRACE(
"sbDynamicPlaylistService::onLibraryUnregistered");
483 if (aLibrary instanceof
Ci.sbILibrary) {
484 this._removeListsFromLibrary(aLibrary);
487 aLibrary.removeListener(
this);
493 function sbDynamicPlaylistService_onItemAdded(aMediaList,
497 if (this._ignore(aMediaList.library))
502 if (this._libraryBatch.isActive(aMediaList.library)) {
503 this._libraryRefreshPending[
FIX(aMediaList.library.guid)] =
true;
508 if (this._isDynamicPlaylist(aMediaItem)) {
512 this._setNextRun(aMediaItem);
514 this._scheduledLists[
FIX(aMediaItem.guid)] = aMediaItem;
515 d(
"A new dynamic playlist was added");
521 function sbDynamicPlaylistService_onBeforeItemRemoved(aMediaList,
525 if (this._ignore(aMediaList.library))
530 if (this._libraryBatch.isActive(aMediaList.library)) {
531 this._libraryRefreshPending[
FIX(aMediaList.library.guid)] =
true;
535 delete this._scheduledLists[
FIX(aMediaItem.guid)];
539 function sbDynamicPlaylistService_onAfterItemRemoved(aMediaList,
547 function sbDynamicPlaylistService_onItemUpdated(aMediaList,
551 if (this._ignore(aMediaList.library))
556 if (this._libraryBatch.isActive(aMediaList.library)) {
557 this._libraryRefreshPending[
FIX(aMediaList.library.guid)] =
true;
562 this._scheduledLists[
FIX(aMediaItem.guid)] = aMediaItem;
566 function sbDynamicPlaylistService_onItemMoved(aMediaList,
574 function sbDynamicPlaylistService_onBeforeListCleared(aMediaList,
581 function sbDynamicPlaylistService_onListCleared(aMediaList,
584 if (this._ignore(aMediaList.library))
589 if (this._libraryBatch.isActive(aMediaList.library)) {
590 this._libraryRefreshPending[
FIX(aMediaList.library.guid)] =
true;
595 this._removeListsFromLibrary(aMediaList.library);
599 function sbDynamicPlaylistService_onBatchBegin(aMediaList)
601 this._libraryBatch.begin(aMediaList.library);
605 function sbDynamicPlaylistService_onBatchEnd(aMediaList)
607 var library = aMediaList.library;
608 this._libraryBatch.end(library);
610 if (!this._libraryBatch.isActive(library)) {
613 if (this._libraryRefreshPending[
FIX(library.guid)]) {
615 d(
"Refreshing dynamic playlists in library " + library);
616 this._removeListsFromLibrary(library);
617 this._scheduleLibrary(library);
619 this._libraryRefreshPending[
FIX(library.guid)] =
false;
626 function sbDynamicPlaylistService_notify(aTimer)
628 this._updateSubscriptions(
false);
633 function sbDynamicPlaylistService_observe(aSubject, aTopic,
aData)
643 function sbPlaylistReaderListenerObserver(aService, aList) {
644 this._service = aService;
646 this._oldLength = aList.length;
649 sbPlaylistReaderListenerObserver.prototype.observe =
650 function sbPlaylistReaderListenerObserver_observe(aSubject, aTopic,
aData)
652 var ioService =
Cc[
"@mozilla.org/network/io-service;1"]
653 .getService(
Ci.nsIIOService);
656 TRACE(
"Updated list with uri " + uri.spec);
659 this._service._setNextRun(this._list);
667 destinationDir = ioService.newURI(destination,
null,
null)
668 .QueryInterface(
Ci.nsIFileURL).file;
669 if (!destinationDir.isDirectory())
670 destinationDir =
null;
674 destinationDir =
null;
680 var
array =
Cc[
"@songbirdnest.com/moz/xpcom/threadsafe-array;1"].createInstance(
Ci.nsIMutableArray);
681 for (var
i = this._oldLength;
i < this._list.length;
i++) {
682 var item = this._list.getItemByIndex(
i);
683 if (destinationDir) {
684 var itemUri = item.contentSrc;
687 if (itemUri instanceof
Ci.nsIURL) {
688 var dest = destinationDir.clone();
689 dest.append(itemUri.QueryInterface(
Ci.nsIURL).fileName);
690 var destUri = ioService.newFileURI(dest);
694 array.appendElement(item,
false);
697 var metadataService =
Cc[
"@songbirdnest.com/Songbird/FileMetadataService;1"]
698 .getService(
Ci.sbIFileMetadataService);
699 var metadataJob = metadataService.read(array);
703 Cc[
"@songbirdnest.com/Songbird/DownloadDeviceHelper;1"]
704 .getService(
Ci.sbIDownloadDeviceHelper);
705 ddh.downloadSome(array.enumerate());
710 return XPCOMUtils.generateModule([
713 function(aCompMgr, aFileSpec, aLocation) {
714 XPCOMUtils.categoryManager.addCategoryEntry(
const SB_LIBRARY_MANAGER_READY_TOPIC
const SB_PROP_ISSUBSCRIPTION
const SB_DEVICE_MANAGER_READY_TOPIC
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
sbDynamicPlaylistService prototype _startup
const SB_PROP_DESTINATION
sbDeviceFirmwareAutoCheckForUpdate prototype classDescription
const SB_FINAL_UI_STARTUP_TOPIC
sbDeviceFirmwareAutoCheckForUpdate prototype _timer
const SB_PROP_SUBSCRIPTIONINTERVAL
const SB_PROP_SUBSCRIPTIONNEXTRUN
const SB_PROP_SUBSCRIPTIONURL
function sbDynamicPlaylistService()
sbDeviceFirmwareAutoCheckForUpdate prototype classID
Javascript wrappers for common library tasks.
_getSelectedPageStyle s i
Array filter(tab.attributes, function(aAttr){return(_this.xulAttributes.indexOf(aAttr.name) >-1);}).forEach(tab.removeAttribute
const SB_LIBRARY_MANAGER_BEFORE_SHUTDOWN_TOPIC
_updateTextAndScrollDataForFrame aData