sbLibraryUtils.jsm
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 Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
27 Components.utils.import("resource://app/jsmodules/sbColumnSpecParser.jsm");
28 
29 EXPORTED_SYMBOLS = ["LibraryUtils"];
30 
31 const Cc = Components.classes;
32 const Ci = Components.interfaces;
33 const Cr = Components.results;
34 
39 var LibraryUtils = {
40 
41  get manager() {
42  var manager = Cc["@songbirdnest.com/Songbird/library/Manager;1"].
43  getService(Ci.sbILibraryManager);
44  if (manager) {
45  // Succeeded in getting the library manager, don't do this again.
46  this.__defineGetter__("manager", function() {
47  return manager;
48  });
49  }
50  return manager;
51  },
52 
53  get mainLibrary() {
54  return this.manager.mainLibrary;
55  },
56 
57  get webLibrary() {
58  var webLibraryGUID = Cc["@mozilla.org/preferences-service;1"].
59  getService(Ci.nsIPrefBranch).
60  getCharPref("songbird.library.web");
61  var webLibrary = this.manager.getLibrary(webLibraryGUID);
62  delete webLibraryGUID;
63 
64  if (webLibrary) {
65  // Succeeded in getting the web library, don't ever do this again.
66  this.__defineGetter__("webLibrary", function() {
67  return webLibrary;
68  });
69  }
70 
71  return webLibrary;
72  },
73 
74  getMediaListByGUID: function(aLibraryGUID, aMediaListGUID) {
75  var mediaList = (aLibraryGUID instanceof Ci.sbILibrary) ?
76  aLibraryGUID :
77  this.manager.getLibrary( aLibraryGUID );
78 
79  // Are we loading the root library or a media list within it?
80  if (aMediaListGUID && aLibraryGUID != aMediaListGUID) {
81  mediaList = mediaList.getMediaItem( aMediaListGUID );
82  }
83  return mediaList;
84  },
85 
86  _standardFilterConstraint: null,
87  get standardFilterConstraint() {
88  if (!this._standardFilterConstraint) {
89  this._standardFilterConstraint = this.createConstraint([
90  [
91  [SBProperties.isList, ["0"]]
92  ],
93  [
94  [SBProperties.hidden, ["0"]]
95  ]
96  ]);
97  }
98  return this._standardFilterConstraint;
99  },
100 
101  createConstraint: function(aObject) {
102  var builder = Cc["@songbirdnest.com/Songbird/Library/ConstraintBuilder;1"]
103  .createInstance(Ci.sbILibraryConstraintBuilder);
104  aObject.forEach(function(aGroup, aIndex) {
105  aGroup.forEach(function(aPair) {
106  var property = aPair[0];
107  var values = aPair[1];
108  var enumerator = {
109  a: values,
110  i: 0,
111  hasMore: function() {
112  return this.i < this.a.length;
113  },
114  getNext: function() {
115  return this.a[this.i++];
116  }
117  };
118  builder.includeList(property, enumerator);
119  });
120  if (aIndex < aObject.length - 1) {
121  builder.intersect();
122  }
123  });
124  return builder.get();
125  },
126 
127  createStandardSearchConstraint: function(aSearchString) {
128  if (aSearchString == "" || !aSearchString)
129  return null;
130  var builder = Cc["@songbirdnest.com/Songbird/Library/ConstraintBuilder;1"]
131  .createInstance(Ci.sbILibraryConstraintBuilder);
132  var a = aSearchString.split(" ");
133  var first = true;
134  for (var i = 0; i < a.length; i++) {
135  if (a[i] && a[i] != "") {
136  if (!first) {
137  builder.intersect();
138  }
139  builder.include(SBProperties.artistName, a[i]);
140  builder.include(SBProperties.albumName, a[i]);
141  builder.include(SBProperties.trackName, a[i]);
142  first = false;
143  }
144  }
145  return builder.get();
146  },
147 
166  createStandardMediaListView: function(aMediaList, aSearchString) {
167  var mediaList = aMediaList.QueryInterface(Ci.sbIMediaList);
168  var mediaListView = mediaList.createView();
169 
170  // Get the sort for this list by parsing the list's column spec. Then hit
171  // the property manager to see if there is a special sort profile for this
172  // ID
173  var parser = new ColumnSpecParser(aMediaList, null);
174  if (parser.sortID) {
175  var propertyArray =
176  Cc["@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"].
177  createInstance(Ci.sbIMutablePropertyArray);
178  propertyArray.strict = false;
179  propertyArray.appendProperty(parser.sortID,
180  (parser.sortIsAscending ? "a" : "d"));
181  mediaListView.setSort(propertyArray);
182  }
183 
184  // By default, we never want to show lists and hidden
185  // things in the playlist
186  mediaListView.filterConstraint = LibraryUtils.standardFilterConstraint;
187 
188  // Set up a standard search filter.
189  // It can always be replaced later.
190  var filter = mediaListView.cascadeFilterSet;
191  filter.appendSearch(["*"], 1);
192 
193  if (aSearchString) {
194  // Set the search
195  var searchArray = aSearchString.split(" ");
196  filter.set(0, searchArray, searchArray.length);
197  } else {
198  // Or not.
199  filter.set(0, [], 0);
200  }
201 
202  return mediaListView;
203  },
204 
205  createConstrainedMediaListView: function(aMediaList, aConstraint,
206  aSearchString) {
207  var mediaListView = this.createStandardMediaListView(aMediaList,
208  aSearchString);
209 
210  // Take the existing filter constraint and intersect it with the
211  // additional constraint we're about to apply
212  var constraintBuilder =
213  Cc["@songbirdnest.com/Songbird/Library/ConstraintBuilder;1"]
214  .createInstance(Ci.sbILibraryConstraintBuilder);
215  constraintBuilder.includeConstraint(mediaListView.filterConstraint);
216  constraintBuilder.intersect();
217  constraintBuilder.include(aConstraint[0], aConstraint[1]);
218  mediaListView.filterConstraint = constraintBuilder.get();
219 
220  return mediaListView;
221  },
222 
229  isMediaTabURL: function(aURL, aBrowser) {
230  if (!aURL) {
231  return Components.results.NS_ERROR_INVALID_ARG;
232  }
233  if (aBrowser && !aBrowser.mediaTab) {
234  // no media tab, can't be a media tab url
235  return false;
236  }
237  var url = aURL;
238  if (aURL instanceof Components.interfaces.nsIURI) {
239  url = aURL.spec;
240  }
241  if (!(/chrome:\/\//.test(url))) {
242  // not chrome
243  return false;
244  }
245 
246  const PREF_FIRSTRUN_URL = "songbird.url.firstrunpage";
247  const Application = Cc["@mozilla.org/fuel/application;1"].getService();
248  var firstRunURL = Application.prefs.getValue(PREF_FIRSTRUN_URL, null);
249  if (url == firstRunURL) {
250  // first run url, sure this can be a media tab
251  return true;
252  }
253  var service =
254  Components.classes['@songbirdnest.com/servicepane/service;1']
255  .getService(Components.interfaces.sbIServicePaneService);
256  var node = service.getNodeForURL(url,
257  Ci.sbIServicePaneService.URL_MATCH_PREFIX);
258  if (!node) return false;
259  return true;
260  },
261 
271  getMainLibraryOriginItem: function(aMediaItem) {
272  var originGUID = aMediaItem.getProperty(SBProperties.originItemGuid);
273  if (!originGUID) {
274  return null;
275  }
276  try {
277  var foundItem = this.mainLibrary.getMediaItem(originGUID);
278  return foundItem;
279  }
280  catch (e) {
281  // item couldn't be found, return null
282  return null;
283  }
284  }
285 
286 }
287 
288 
289 
295 LibraryUtils.BatchHelper = function() {
296  this._depth = 0;
297 }
298 
299 LibraryUtils.BatchHelper.prototype.begin =
300 function BatchHelper_begin()
301 {
302  this._depth++;
303 }
304 
305 LibraryUtils.BatchHelper.prototype.end =
306 function BatchHelper_end()
307 {
308  this._depth--;
309  if (this._depth < 0) {
310  throw new Error("Invalid batch depth!");
311  }
312 }
313 
314 LibraryUtils.BatchHelper.prototype.depth =
315 function BatchHelper_depth()
316 {
317  return this._depth;
318 }
319 
320 LibraryUtils.BatchHelper.prototype.isActive =
321 function BatchHelper_isActive()
322 {
323  return this._depth > 0;
324 }
325 
326 
327 
333 LibraryUtils.MultiBatchHelper = function() {
334  this._libraries = {};
335 }
336 
337 LibraryUtils.MultiBatchHelper.prototype.get =
338 function MultiBatchHelper_get(aLibrary)
339 {
340  var batch = this._libraries[aLibrary.guid];
341  if (!batch) {
342  batch = new LibraryUtils.BatchHelper();
343  this._libraries[aLibrary.guid] = batch;
344  }
345  return batch;
346 }
347 
348 LibraryUtils.MultiBatchHelper.prototype.begin =
349 function MultiBatchHelper_begin(aLibrary)
350 {
351  var batch = this.get(aLibrary);
352  batch.begin();
353 }
354 
355 LibraryUtils.MultiBatchHelper.prototype.end =
356 function MultiBatchHelper_end(aLibrary)
357 {
358  var batch = this.get(aLibrary);
359  batch.end();
360 }
361 
362 LibraryUtils.MultiBatchHelper.prototype.depth =
363 function MultiBatchHelper_depth(aLibrary)
364 {
365  var batch = this.get(aLibrary);
366  return batch.depth();
367 }
368 
369 LibraryUtils.MultiBatchHelper.prototype.isActive =
370 function MultiBatchHelper_isActive(aLibrary)
371 {
372  var batch = this.get(aLibrary);
373  return batch.isActive();
374 }
375 
376 
377 
378 
384 LibraryUtils.RemovalMonitor = function(aCallback) {
385  //dump("RemovalMonitor: RemovalMonitor()\n");
386 
387  if (!aCallback || !aCallback.onMediaListRemoved) {
388  throw new Error("RemovalMonitor() requires a callback object");
389  }
390 
391  this._callback = aCallback;
392 }
393 
394 LibraryUtils.RemovalMonitor.prototype = {
395 
396  // An object with an onMediaListRemoved function
397  _callback: null,
398 
399  // MediaList GUID to monitor for removal
400  _targetGUID: null,
401 
402  // Library that owns the target MediaList
403  _library: null,
404 
406  _batchHelper: null,
407 
408  // Flag to indicate that the target item
409  // was deleted in a batch operation
410  _removedInBatch: false,
411 
412 
417  setMediaList: function RemovalMonitor_setMediaList(aMediaList) {
418  //dump("RemovalMonitor: RemovalMonitor.setMediaList()\n");
419  this._removedInBatch = false;
420 
421  // If passed a medialist, hook up listeners
422  if (aMediaList instanceof Ci.sbIMediaList) {
423 
424  // Listen to the library if we aren't doing so already
425  if (aMediaList.library != this._library) {
426  if (this._library && this._library.guid != this._targetGUID) {
427  this._library.removeListener(this);
428  }
429 
430  this._library = aMediaList.library
431 
432  // If this is a list within a library, then
433  // we need to listen for clear/remove in the
434  // library
435  if (!(aMediaList instanceof Ci.sbILibrary)) {
436  this._batchHelper = new LibraryUtils.BatchHelper();
437 
438  var flags = Ci.sbIMediaList.LISTENER_FLAGS_BATCHBEGIN |
439  Ci.sbIMediaList.LISTENER_FLAGS_BATCHEND |
440  Ci.sbIMediaList.LISTENER_FLAGS_BEFOREITEMREMOVED |
441  Ci.sbIMediaList.LISTENER_FLAGS_AFTERITEMREMOVED |
442  Ci.sbIMediaList.LISTENER_FLAGS_LISTCLEARED;
443 
444  this._library.addListener(this, false, flags, null);
445  }
446  }
447 
448  if (!this._libraryManager) {
449  this._libraryManager = Cc["@songbirdnest.com/Songbird/library/Manager;1"]
450  .getService(Ci.sbILibraryManager);
451  this._libraryManager.addListener(this);
452  }
453 
454  // Remember which medialist we are supposed to watch
455  this._targetGUID = aMediaList.guid;
456 
457 
458  // If set to null, shut down any listeners
459  } else {
460  if (this._libraryManager) {
461  this._libraryManager.removeListener(this);
462  this._libraryManager = null;
463  }
464 
465  if (this._library) {
466  this._library.removeListener(this);
467  this._library = null;
468  }
469  this._batchHelper = null;
470  this._targetGUID = null;
471  }
472  },
473 
474 
478  _onBeforeMediaListRemoved: function RemovalMonitor_onBeforeMediaListRemoved()
479  {
480  // Notify
481  this._callback.onBeforeMediaListRemoved();
482  },
483 
484 
489  _onMediaListRemoved: function RemovalMonitor_onMediaListRemoved() {
490  //dump("RemovalMonitor: RemovalMonitor.onMediaListRemoved()\n");
491 
492  // Our list has been removed. Stop tracking.
493  this.setMediaList(null);
494 
495  // Notify
496  this._callback.onMediaListRemoved();
497  },
498 
499 
503  onItemAdded: function(aMediaList, aMediaItem, aIndex) { return true; },
504  onItemUpdated: function(aMediaList, aMediaItem, aProperties) { return true },
505  onItemMoved: function(aMediaList, aFromIndex, aToIndex) { return true },
506  onBeforeItemRemoved: function (aMediaList, aMediaItem, aIndex) {
507  // Do no more if in a batch
508  if (this._batchHelper.isActive()) {
509  if (aMediaItem.guid == this._targetGUID) {
510  this._removedInBatch = true;
511  }
512  return true;
513  }
514 
515  // If our list is about to be removed, notify
516  if (aMediaItem.guid == this._targetGUID) {
517  this._onBeforeMediaListRemoved();
518  }
519 
520  return false;
521  },
522  onAfterItemRemoved: function RemovalMonitor_onAfterItemRemoved(aMediaList,
523  aMediaItem,
524  aIndex)
525  {
526  //dump("RemovalMonitor: RemovalMonitor.onAfterItemRemoved()\n");
527 
528  // Do no more if in a batch
529  if (this._batchHelper.isActive()) {
530  if (aMediaItem.guid == this._targetGUID) {
531  this._removedInBatch = true;
532  }
533  return true;
534  }
535 
536  // If our list was removed, notify
537  if (aMediaItem.guid == this._targetGUID) {
538  this._onMediaListRemoved();
539  }
540 
541  return false;
542  },
543  onBeforeListCleared: function RemovalMonitor_onBeforeListCleared
544  (aMediaList,
545  aExcludeLists)
546  {
547  //dump("RemovalMonitor: RemovalMonitor.onBeforeListCleared()\n");
548 
549  return true;
550  },
551  onListCleared: function RemovalMonitor_onListCleared(aMediaList,
552  aExcludeLists)
553  {
554  //dump("RemovalMonitor: RemovalMonitor.onListCleared()\n");
555 
556  // Do no more if in a batch
557  if (this._batchHelper.isActive()) {
558  this._removedInBatch = true;
559  return true;
560  }
561 
562  // The current media list must have been removed, so notify
563  this._onMediaListRemoved();
564 
565  return false;
566  },
567 
568  onBatchBegin: function RemovalMonitor_onBatchBegin(aMediaList)
569  {
570  this._batchHelper.begin();
571  },
572  onBatchEnd: function RemovalMonitor_onBatchEnd(aMediaList)
573  {
574  //dump("RemovalMonitor: RemovalMonitor.onBatchEnd()\n");
575 
576  this._batchHelper.end();
577  // If the batch is still in progress do nothing
578  if (this._batchHelper.isActive()) {
579  return;
580  }
581 
582  var removed = false;
583 
584  // If we know our target was removed during the batch, notify
585  if (this._removedInBatch) {
586  removed = true;
587 
588  // If we don't know for sure, we need to check
589  } else if (this._targetGUID != this._library.guid) {
590 
591  // Check if our media list was removed
592  try {
593  this._library.getMediaItem(this._targetGUID);
594  } catch (e) {
595  removed = true;
596  }
597  }
598 
599  this._removedInBatch = false;
600 
601  if (removed) {
602  this._onMediaListRemoved();
603  }
604  },
605 
609  onLibraryRegistered: function(aLibrary) {},
610  onLibraryUnregistered: function RemovalMonitor_onLibraryUnregistered(aLibrary)
611  {
612  //dump("RemovalMonitor: RemovalMonitor.onLibraryUnregistered()\n");
613  // If the current library was unregistered, notify
614  if (this._library && this._library.equals(aLibrary)) {
615  this._onMediaListRemoved();
616  }
617  },
618 
619 
623  QueryInterface: function RemovalMonitor_QueryInterface(aIID) {
624  if (!aIID.equals(Components.interfaces.nsISupports) &&
625  !aIID.equals(Components.interfaces.sbILibraryManagerListener) &&
626  !aIID.equals(Components.interfaces.sbIMediaListListener)) {
627  throw Components.results.NS_ERROR_NO_INTERFACE;
628  }
629  return this;
630  }
631 }
632 
637 LibraryUtils.MediaListEnumeratorToArray = function() {
638 }
639 
640 LibraryUtils.MediaListEnumeratorToArray.prototype = {
641  //
642  // Media list enumeration array listener fields.
643  //
644  // array Enumeration array.
645  //
646 
647  array: null,
648 
649 
658  onEnumerationBegin: function DSW_MLEAL_onEnumerationBegin(aMediaList) {
659  // Initialize the enumeration array.
660  this.array = [];
661  return Ci.sbIMediaListEnumerationListener.CONTINUE;
662  },
663 
664 
674  onEnumeratedItem: function DSW_MLEAL_onEnumeratedItem(aMediaList,
675  aMediaItem) {
676  // Add the item to the enumeration array.
677  this.array.push(aMediaItem);
678  return Ci.sbIMediaListEnumerationListener.CONTINUE;
679  },
680 
681 
689  onEnumerationEnd: function DSW_MLEAL_onEnumerationEnd(aMediaList,
690  aStatusCode) {
691  }
692 }
693 
704 LibraryUtils.GlobalMediaListListener = function(aListener,
705  aOwnsWeak,
706  aFlags,
707  aPropFilter,
708  aOnlyThisLibrary) {
709  if (aFlags === undefined) {
710  aFlags = Components.interfaces.sbIMediaList.LISTENER_FLAGS_ALL;
711  }
712 
713  this.listener = aListener;
714  this.ownsWeak = aOwnsWeak;
715  this.propFilter = aPropFilter;
716  this.listenerFlags = aFlags;
717 
718  this.libraryManager =
719  Cc["@songbirdnest.com/Songbird/library/Manager;1"]
720  .getService(Ci.sbILibraryManager);
721 
722  this.listListener = {
723  cb: this,
724  onitemadded_skipbatch : false,
725  onitemadded_stack : [],
726  onafteritemremoved_skipbatch : false,
727  onafteritemremoved_stack : [],
728  batchcount : 0,
729  onItemAdded: function(aMediaList, aMediaItem, aIndex) {
730  if (aMediaItem instanceof Ci.sbIMediaList)
731  this.cb.addMediaListListener(aMediaItem);
732  if (this.batchcount > 0 && this.onitemadded_skipbatch)
733  return Ci.sbIMediaListEnumerationListener.CONTINUE;
734  if (this.cb.listener.onItemAdded(aMediaList, aMediaItem, aIndex) !=
735  Ci.sbIMediaListEnumerationListener.CONTINUE) {
736  this.onitemadded_skipbatch = true;
737  }
738  return Ci.sbIMediaListEnumerationListener.CONTINUE;
739  },
740  onBeforeItemRemoved: function(aMediaList, aMediaItem, aIndex) {
741  return this.cb.listener.onBeforeItemRemoved(aMediaList, aMediaItem, aIndex);
742  },
743  onAfterItemRemoved: function(aMediaList, aMediaItem, aIndex) {
744  if (aMediaItem instanceof Ci.sbIMediaList)
745  this.cb.removeMediaListListener(aMediaItem);
746  if (this.onafteritemremoved_skipbatch)
747  return Ci.sbIMediaListEnumerationListener.CONTINUE;
748  if (this.cb.listener.onAfterItemRemoved(aMediaList, aMediaItem, aIndex) !=
749  Ci.sbIMediaListEnumerationListener.CONTINUE) {
750  this.onafteritemremoved_skipbatch = true;
751  }
752  return Ci.sbIMediaListEnumerationListener.CONTINUE;
753  },
754  onItemUpdated: function(aMediaList, aMediaItem, aProperties) {
755  return this.cb.listener.onItemUpdated(aMediaList, aMediaItem, aProperties);
756  },
757  onItemMoved: function(aMediaList, aFromIndex, aToIndex) {
758  return this.cb.listener.onItemMoved(aMediaList, aFromIndex, aToIndex);
759  },
760  onBeforeListCleared: function(aMediaList, aExcludeLists) {
761  return this.cb.listener.onBeforeListCleared(aMediaList, aExcludeLists);
762  },
763  onListCleared: function(aMediaList, aExcludeLists) {
764  return this.cb.listener.onListCleared(aMediaList, aExcludeLists);
765  },
766  onBatchBegin: function(aMediaList) {
767  ++this.batchcount;
768  this.onitemadded_stack.push(this.onitemadded_skipbatch);
769  this.onitemadded_skipbatch = false;
770  this.onafteritemremoved_stack.push(this.onafteritemremoved_skipbatch);
771  this.onafteritemremoved_skipbatch = false;
772  return this.cb.listener.onBatchBegin(aMediaList);
773  },
774  onBatchEnd: function(aMediaList) {
775  --this.batchcount;
776  this.onitemadded_skipbatch = this.onitemadded_stack.pop();
777  this.onafteritemremoved_skipbatch = this.onafteritemremoved_stack.pop();
778  return this.cb.listener.onBatchEnd(aMediaList);
779  },
780  QueryInterface: function(iid) {
781  if (iid.equals(Components.interfaces.sbIMediaListListener) ||
782  iid.equals(Components.interfaces.nsISupports))
783  return this;
784  throw Components.results.NS_ERROR_NO_INTERFACE;
785  }
786  };
787 
788 
789  var enumListener = {
790  cb: this,
791  onEnumerationBegin: function(aMediaList) { },
792  onEnumerationEnd: function(aMediaList) { },
793  onEnumeratedItem: function(aMediaList, aMediaItem) {
794  this.cb.addMediaListListener(aMediaItem);
795  return Components.interfaces.sbIMediaListEnumerationListener.CONTINUE;
796  },
797  QueryInterface: function(iid) {
798  if (iid.equals(Components.interfaces.sbIMediaListEnumerationListener) ||
799  iid.equals(Components.interfaces.nsISupports))
800  return this;
801  throw Components.results.NS_ERROR_NO_INTERFACE;
802  }
803  };
804 
805  var libs = this.libraryManager.getLibraries();
806  while (libs.hasMoreElements()) {
807  var library = libs.getNext();
808  if (aOnlyThisLibrary &&
809  library != aOnlyThisLibrary)
810  continue;
811  enumListener.onEnumeratedItem(library, library);
812  library.
813  enumerateItemsByProperty(
814  SBProperties.isList,
815  "1",
816  enumListener,
817  Components.interfaces.sbIMediaList.ENUMERATIONTYPE_LOCKING);
818  }
819 
820  if (!aOnlyThisLibrary) {
821  this.managerListener = {
822  cb: this,
823  onLibraryRegistered: function(aLibrary) {
824  this.cb.addMediaListListener(aLibrary);
825  this.cb.listener.onItemAdded(null, aLibrary, 0);
826  },
827  onLibraryUnregistered: function(aLibrary) {
828  this.cb.listener.onBeforeItemRemoved(null, aLibrary, 0);
829  this.cb.removeMediaListListener(aLibrary);
830  this.cb.listener.onAfterItemRemoved(null, aLibrary, 0);
831  },
832  QueryInterface: function(iid) {
833  if (iid.equals(Components.interfaces.sbILibraryManagerListener) ||
834  iid.equals(Components.interfaces.nsISupports))
835  return this;
836  throw Components.results.NS_ERROR_NO_INTERFACE;
837  }
838  };
839 
840  this.libraryManager.addListener(this.managerListener);
841  }
842 }
843 
844 LibraryUtils.GlobalMediaListListener.prototype = {
845  listener : null,
846  listento : [],
847  managerListener : null,
848  listListener : null,
849  ownsWeak : null,
850  propFilter : null,
851  listenerFlags : 0,
852 
853  shutdown: function() {
854  for (var i=0;i<this.listento.length;i++)
855  this.listento[i].removeListener(this.listListener);
856 
857  this.listento = [];
858  this.listListener = null;
859 
860  this.listener = null;
861  this.propFilter = null;
862 
863  if (this.managerListener)
864  this.libraryManager.removeListener(this.managerListener);
865  this.managerListener = null;
866 
867  this.libraryManager = null;
868  },
869 
870  addMediaListListener: function(aList) {
871  if (this.listento.indexOf(aList) >= 0)
872  return;
873  aList.addListener(this.listListener,
874  this.ownsWeak,
875  this.listenerFlags,
876  this.propFilter);
877  this.listento.push(aList);
878  },
879 
880  removeMediaListListener: function(aList) {
881  aList.removeListener(this.listListener);
882  var p = this.listento.indexOf(aList);
883  if (p >= 0) this.listento.splice(p, 1);
884  }
885 }
886 
896 LibraryUtils.canEditMetadata = function (aItem) {
897  var editable = aItem.userEditable;
898  if (editable) {
899  try {
900  var contentSrc = aItem.contentSrc;
901  if (contentSrc.scheme == "x-mtp")
902  editable = false;
903  } catch (e) {
904  // Errors means it's not x-mtp and edtible
905  }
906  }
907  return editable;
908 }
return foundItem
id service()
var Application
Definition: sbAboutDRM.js:37
const PREF_FIRSTRUN_URL
inArray array
sbDeviceFirmwareAutoCheckForUpdate prototype flags
sidebarFactory createInstance
Definition: nsSidebar.js:351
sbOSDControlService prototype QueryInterface
sbDownloadDeviceServicePaneModule prototype shutdown
const Cr
getService(Ci.sbIFaceplateManager)
var libraryManager
const Cc
return null
Definition: FeedWriter.js:1143
let node
const Ci
EXPORTED_SYMBOLS
function url(spec)
StringArrayEnumerator prototype hasMore
_updateTextAndScrollDataForTab aBrowser
sbAutoDownloader prototype _libraryManager
Javascript wrappers for common library tasks.
__defineGetter__("Application", function(){delete this.Application;return this.Application=Cc["@mozilla.org/fuel/application;1"].getService(Ci.fuelIApplication);})
_getSelectedPageStyle s i
Array filter(tab.attributes, function(aAttr){return(_this.xulAttributes.indexOf(aAttr.name) >-1);}).forEach(tab.removeAttribute
sbAutoDownloader prototype _library
return first
var getMainLibraryOriginItem
Find an item in the main library whose guid matches the originItemGuid of the param aMediaItem and re...