deviceControl.js
Go to the documentation of this file.
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4  *=BEGIN SONGBIRD GPL
5  *
6  * This file is part of the Songbird web player.
7  *
8  * Copyright(c) 2005-2011 POTI, Inc.
9  * http://www.songbirdnest.com
10  *
11  * This file may be licensed under the terms of of the
12  * GNU General Public License Version 2 (the ``GPL'').
13  *
14  * Software distributed under the License is distributed
15  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
16  * express or implied. See the GPL for the specific language
17  * governing rights and limitations.
18  *
19  * You should have received a copy of the GPL along with this
20  * program. If not, go to http://www.gnu.org/licenses/gpl.html
21  * or write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  *=END SONGBIRD GPL
25  */
26 
32 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
34 //
35 // Device control widget.
36 //
37 //------------------------------------------------------------------------------
38 //------------------------------------------------------------------------------
39 
40 //------------------------------------------------------------------------------
41 //
42 // Device control imported services.
43 //
44 //------------------------------------------------------------------------------
45 
46 // Songbird imports.
47 Components.utils.import("resource://app/jsmodules/DOMUtils.jsm");
48 Components.utils.import("resource://app/jsmodules/StringUtils.jsm");
49 Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
50 Components.utils.import("resource://app/jsmodules/WindowUtils.jsm");
51 
52 Components.utils.import("resource://app/jsmodules/sbLibraryUtils.jsm");
53 Components.utils.import("resource://app/jsmodules/ArrayConverter.jsm");
54 
55 
56 //------------------------------------------------------------------------------
57 //
58 // Device control services defs.
59 //
60 //------------------------------------------------------------------------------
61 
62 // Component manager defs.
63 if (typeof(Cc) == "undefined")
64  var Cc = Components.classes;
65 if (typeof(Ci) == "undefined")
66  var Ci = Components.interfaces;
67 if (typeof(Cr) == "undefined")
68  var Cr = Components.results;
69 if (typeof(Cu) == "undefined")
70  var Cu = Components.utils;
71 
72 
73 //------------------------------------------------------------------------------
74 //
75 // Device control services.
76 //
77 //------------------------------------------------------------------------------
78 
86 function deviceControlWidget(aWidget) {
87  this._widget = aWidget;
88 }
89 
90 // Set the constructor.
91 deviceControlWidget.prototype.constructor = deviceControlWidget;
92 
93 // Define the object.
94 deviceControlWidget.prototype = {
95  //
96  // Device control object fields.
97  //
98  // _widget Device control widget.
99  // _device Device bound to device control widget.
100  // _deviceLibrary Bound device library.
101  // _boundElem Element bound to device control widget.
102  // _domEventListenerSet Set of DOM event listeners.
103  // _deviceListenerAdded True if a device listener has been added.
104  // _currentState Current device operational state.
105  // _currentReadOnly Current device read only state.
106  // _currentImageMgmtType Current device image sync management type.
107  //
108 
109  _widget: null,
110  _device: null,
111  _deviceLibrary: null,
112  _boundElem: null,
113  _domEventListenerSet: null,
114  _deviceListenerAdded: false,
115  _currentState: Ci.sbIDevice.STATE_IDLE,
116  _currentReadOnly: false,
117  _currentImageMgmtType: Ci.sbIDeviceLibraryMediaSyncSettings.SYNC_MGMT_NONE,
118 
119 
120  //----------------------------------------------------------------------------
121  //
122  // Device control services.
123  //
124  //----------------------------------------------------------------------------
125 
130  bindDevice: function deviceControlWidget_bindDevice() {
131  // If the device library GUID is specified, check if it has changed.
132  // Otherwise, check if the device ID has changed.
133  let devLibGUID = this._widget.getAttribute("dev-lib-guid");
134  let devLib;
135  let deviceID;
136  let device;
137  if (devLibGUID) {
138  // Just return if the device library GUID has not changed.
139  if (devLibGUID == this._widget.devLibGUID)
140  return;
141 
142  // Get the device library.
143  let libMgr = Cc["@songbirdnest.com/Songbird/library/Manager;1"]
144  .getService(Ci.sbILibraryManager);
145  devLib = libMgr.getLibrary(devLibGUID);
146 
147  // Get the device info from the device library.
148  if (devLib)
149  device = devLib.device;
150  if (device)
151  deviceID = device.id;
152  }
153  else {
154  // Get the device ID. Just return if it has not changed or has not been
155  // specified.
156  deviceID = this._widget.getAttribute("device-id");
157  if (!deviceID || (deviceID == this._widget.deviceID))
158  return;
159 
160  // Get the device object.
161  let deviceManager = Cc["@songbirdnest.com/Songbird/DeviceManager;2"]
162  .getService(Ci.sbIDeviceManager2);
163  device = deviceManager.getDevice(Components.ID(deviceID));
164 
165  // Get the device default library info.
166  if (device)
167  devLib = device.defaultLibrary;
168  if (devLib)
169  devLibGUID = devLib.guid;
170  }
171 
172  // Determine whether a new device or device library has been bound.
173  let deviceBound = device != this._widget.device;
174  let devLibBound = devLib != this._widget.devLib;
175 
176  // Set some widget fields.
177  this._widget.device = device;
178  this._widget.deviceID = deviceID;
179  this._widget.devLib = devLib;
180  this._widget.devLibGUID = devLibGUID;
181 
182  // Re-initialize the device control widget services.
183  this.finalize(true);
184  this.initialize();
185 
186  // Send a device bound event. It doesn't bubble, and it can't be cancelled.
187  if (deviceBound) {
188  let event = document.createEvent("Events");
189  event.initEvent("deviceBound", false, false);
190  this._widget.dispatchEvent(event);
191  }
192 
193  // Send a device library bound event. It doesn't bubble, and it can't be
194  // cancelled.
195  if (devLibBound) {
196  let event = document.createEvent("Events");
197  event.initEvent("devLibBound", false, false);
198  this._widget.dispatchEvent(event);
199  }
200  },
201 
202 
207  initialize: function deviceControlWidget_initialize() {
208  var _this = this;
209  var func;
210 
211  // Initialize object fields.
212  this._device = this._widget.device;
213  this._deviceLibrary = this._widget.devLib;
214 
215  // Get the bound element.
216  this._getBoundElem();
217 
218  // Create a DOM event listener set.
219  this._domEventListenerSet = new DOMEventListenerSet();
220 
221  // Add a DOM command event handler.
222  func = function(aEvent) { _this.onAction(aEvent); };
223  this._domEventListenerSet.add(this._boundElem, "command", func, false);
224 
225  // Add device event listener.
226  if (this._widget.getAttribute("listentodevice") == "true") {
227  var deviceEventTarget = this._device.QueryInterface
228  (Ci.sbIDeviceEventTarget);
229  deviceEventTarget.addEventListener(this);
230  this._deviceListenerAdded = true;
231  }
232 
233  // Only attempt to migrate sync settings if we have a device library.
234  if (this._deviceLibrary) {
235  // Migrate the old preference if available
236  var prefs = Cc["@mozilla.org/preferences-service;1"]
237  .getService(Ci.nsIPrefBranch);
238 
239  var syncPlaylistPrefKey = "songbird.device." + this._widget.deviceID +
240  ".preferences.library." + this._deviceLibrary.guid +
241  ".sync.playlists"
242 
243  var syncPlaylistPrefs = null;
244  if (prefs.prefHasUserValue(syncPlaylistPrefKey))
245  syncPlaylistPrefs = prefs.getCharPref(syncPlaylistPrefKey);
246 
247  // Migration starts.
248  if (syncPlaylistPrefs) {
249  // Get the list of the guid
250  var guidList = syncPlaylistPrefs.split(",");
251  var syncAudioPlaylists = "";
252  var syncVideoPlaylists = "";
253  var mediaList;
254  for (var i = 0; i < guidList.length; ++i) {
255  try {
256  mediaList = LibraryUtils.mainLibrary.getMediaItem(guidList[i])
257  var contentType = mediaList.getListContentType();
258  if (contentType & Ci.sbIMediaList.CONTENTTYPE_AUDIO)
259  syncAudioPlaylists += guidList[i] + ",";
260  if (contentType & Ci.sbIMediaList.CONTENTTYPE_VIDEO)
261  syncVideoPlaylists += guidList[i] + ",";
262  }
263  catch (ex) {
264  }
265  }
266 
267  prefs.setCharPref(syncPlaylistPrefKey + ".audio", syncAudioPlaylists);
268  prefs.setCharPref(syncPlaylistPrefKey + ".video", syncVideoPlaylists);
269 
270  // Reset the old preference so that migration only happans once.
271  prefs.setCharPref(syncPlaylistPrefKey, "");
272  }
273  }
274 
275  // Force an update of the widget.
276  this._update(true);
277  },
278 
279 
285  finalize: function deviceControlWidget_finalize(aReset) {
286  // Remove DOM event listeners.
287  if (this._domEventListenerSet) {
288  this._domEventListenerSet.removeAll();
289  }
290  this._domEventListenerSet = null;
291 
292  // Remove device event listener.
293  if (this._deviceListenerAdded) {
294  var deviceEventTarget = this._device.QueryInterface
295  (Ci.sbIDeviceEventTarget);
296  deviceEventTarget.removeEventListener(this);
297  }
298  this._deviceListenerAdded = false;
299 
300  // Clear object fields.
301  this._device = null;
302  this._deviceLibrary = null;
303  this._boundElem = null;
304  if (!aReset)
305  this._widget = null;
306  },
307 
308 
309  //----------------------------------------------------------------------------
310  //
311  // Device control event handling services.
312  //
313  //----------------------------------------------------------------------------
314 
321  onAction: function deviceControlWidget_onAction(aEvent) {
322  // Do nothing if not bound to a device.
323  if (!this._device)
324  return;
325 
326  // Dispatch processing of action.
327  switch (aEvent.target.getAttribute("action")) {
328  case "cancel" :
329  this._device.cancelRequests();
330  break;
331 
332  case "eject" :
333  this._device.eject();
334  break;
335 
336  case "format" :
337  this._device.format();
338  break;
339 
340  case "ignore" :
341  this._ignoreDevice();
342  break;
343 
344  case "get_info" :
345  this._getDeviceInfo();
346  break;
347 
348  case "new_playlist" :
349  this._createPlaylist();
350  break;
351 
352  case "rename" :
353  this._renameDevice();
354  break;
355 
356  case "sync" :
357  // Sync specific device library or all libraries on device.
358  if (this._deviceLibrary) {
359  this._deviceLibrary.sync();
360  }
361  else {
362  this._device.syncLibraries();
363  }
364  break;
365 
366  case "rip" :
367  sbCDDeviceUtils.doCDRip(this._device);
368  break;
369 
370  case "rescan" :
371  sbCDDeviceUtils.doCDLookUp(this._device);
372  break;
373 
374  default :
375  break;
376  }
377  },
378 
383  _createPlaylist: function deviceControlWidget__createPlaylist() {
384  var libSPS = Cc["@songbirdnest.com/servicepane/library;1"]
385  .getService(Ci.sbILibraryServicePaneService);
386 
387  // Create the playlist.
388  var mediaList = this._deviceLibrary.createMediaList("simple");
389  mediaList.name = libSPS.suggestNameForNewPlaylist(this._deviceLibrary);
390 
391  // Edit the playlist service pane node.
392  if (gServicePane) {
393  var libDSPS = Cc["@songbirdnest.com/servicepane/device;1"]
394  .getService(Ci.sbIDeviceServicePaneService);
395  var node = libSPS.getNodeForLibraryResource(mediaList);
396  var deviceNode = libDSPS.getNodeForDevice(this._device);
397  deviceNode.appendChild(node);
398  gServicePane.startEditingNode(node);
399  }
400  },
401 
406  _renameDevice: function deviceControlWidget__renameDevice() {
407  // Get the service pane node associated with the widget.
408  var servicePaneNode = this._getServicePaneNode();
409 
410  // Edit the service pane node if specified. Otherwise, present a rename
411  // dialog.
412  if (servicePaneNode && (typeof(gServicePane) != "undefined")) {
413  gServicePane.startEditingNode(servicePaneNode);
414  } else {
415  // Get the device friendly name.
416  var friendlyName = null;
417  try { friendlyName = this._device.properties.friendlyName; } catch(ex) {}
418 
419  // Get the device vendor/model name.
420  var vendorModelName = "";
421  var vendorName = null;
422  var modelNumber = null;
423  try { vendorName = this._device.properties.vendorName; } catch(ex) {}
424  try { modelNumber = this._device.properties.modelNumber; } catch(ex) {}
425  if (!modelNumber)
426  modelNumber = SBString("device.default.model.number");
427  if (vendorName)
428  vendorModelName += vendorName + " ";
429  vendorModelName += modelNumber;
430 
431  // Prompt user for new name.
432  var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
433  .getService(Ci.nsIPromptService);
434  var newName = { value: friendlyName };
435  var ok = promptService.prompt
436  (window,
437  SBString("device.dialog.rename.title"),
438  SBFormattedString("device.dialog.rename.message",
439  [vendorModelName]),
440  newName,
441  null,
442  {});
443 
444  // Set new device name.
445  if (ok) {
446  try {
447  this._device.properties.friendlyName = newName.value;
448  } catch (ex) {
449  Cu.reportError("Cannot write device name.\n");
450  }
451  }
452  }
453  },
454 
460  _ignoreDevice: function deviceControlWidget__ignoreDevice() {
461  var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
462  .getService(Ci.nsIPromptService);
463 
464  window.focus();
465  var buttonPressed = promptService.confirmEx(window,
466  SBString('device.dialog.setup.ignoreDeviceTitle'),
467  SBString('device.dialog.setup.ignoreDevice'),
468  promptService.STD_YES_NO_BUTTONS,
469  null, null, null,
470  null, {});
471  // don't set the pref unless they press OK
472  acceptedBlacklist = (buttonPressed == 0);
473  if (acceptedBlacklist) {
474  var ignoreList = Application.prefs
475  .getValue("songbird.device.ignorelist", "");
476  // Append a separator if necessary.
477  if (ignoreList != "") {
478  ignoreList += ";";
479  }
480  ignoreList += this._device.id;
481  Application.prefs.setValue("songbird.device.ignorelist", ignoreList);
482 
483  // Remove the device from the application
484  var manager = Cc["@songbirdnest.com/Songbird/DeviceManager;2"]
485  .getService(Ci.sbIDeviceManager2);
486  var controller = manager.getController(this._device.controllerId);
487  controller.releaseDevice(this._device);
488  }
489  return acceptedBlacklist;
490  },
491 
496  _getDeviceInfo: function deviceControlWidget__getDeviceInfo() {
497  // Show the device info dialog.
498  WindowUtils.openModalDialog
499  (window,
500  "chrome://songbird/content/xul/device/deviceInfoDialog.xul",
501  "",
502  "chrome,centerscreen",
503  [ this._device ],
504  null);
505  },
506 
507 
508  //----------------------------------------------------------------------------
509  //
510  // Device control sbIDeviceEventListener services.
511  //
512  //----------------------------------------------------------------------------
513 
520  onDeviceEvent: function DeviceSyncWidget_onDeviceEvent(aEvent) {
521  // Dispatch processing of the event.
522  switch(aEvent.type)
523  {
524  case Ci.sbIDeviceEvent.EVENT_DEVICE_PREFS_CHANGED :
525  this._update();
526  break;
527 
528  case Ci.sbIDeviceEvent.EVENT_DEVICE_STATE_CHANGED :
529  this._update();
530  break;
531 
532  default :
533  break;
534  }
535  },
536 
537 
538  //----------------------------------------------------------------------------
539  //
540  // Internal device control device services.
541  //
542  //----------------------------------------------------------------------------
543 
550  _getProductName: function deviceControlWidget__getProductName() {
551  // Get the device product name.
552  var productName = null;
553  try { productName = this._device.productName; } catch(err) {}
554  if (productName == null)
555  productName = SBString("device.info.unknown");
556 
557  return productName;
558  },
559 
560 
567  _getDeviceModelCap: function deviceControlWidget__getDeviceModelCap() {
568  // Get the device product name.
569  var productName = null;
570  try { productName = this._device.productName; } catch(err) {}
571  if (productName == null)
572  productName = SBString("device.info.unknown");
573 
574  // Get the device capacity.
575  var capacity = "";
576  if (this._deviceLibrary) {
577  try {
578  storageConverter =
579  Cc["@songbirdnest.com/Songbird/Properties/UnitConverter/Storage;1"]
580  .createInstance(Ci.sbIPropertyUnitConverter);
581  capacity = this._deviceLibrary.getProperty
582  ("http://songbirdnest.com/device/1.0#capacity");
583  capacity = storageConverter.autoFormat(capacity, -1, 1);
584  } catch (ex) {};
585  }
586 
587  return SBFormattedString("device.info.model_cap",
588  [ productName, capacity ]);
589  },
590 
591 
598  _isReadOnly: function deviceControlWidget__isReadOnly() {
599  var readOnly;
600 
601  // If device is read-only, return true.
602  var accessCompatibility;
603  var deviceProperties = this._device.properties.properties;
604  try {
605  accessCompatibility =
606  deviceProperties.getPropertyAsAString("http://songbirdnest.com/" +
607  "device/1.0#accessCompatibility");
608  } catch (ex) {}
609  if (accessCompatibility == "ro")
610  return true;
611 
612  // Treat device as read-only if it doesn't have a library.
613  if (!this._deviceLibrary)
614  return true;
615 
616  // If we're formatting treat the device as readOnly
617  if (this._device.state == Ci.sbIDevice.STATE_FORMATTING)
618  return true;
619 
620  // This is just preventative measure in case the library is being
621  // destroyed or bad state, we'll just treat as readOnly
622  try {
623  // Treat device as read-only if its library is read-only.
624  if (this._deviceLibrary.getProperty(SBProperties.isReadOnly) == "1")
625  readOnly = true;
626  else
627  readOnly = false;
628  }
629  catch (ex) {
630  // This is just preventative measure in case the library is being
631  // destroyed or bad state, we'll just treat as readOnly
632  readOnly = true;
633  }
634  return readOnly;
635  },
636 
637 
638  //----------------------------------------------------------------------------
639  //
640  // Internal device control services.
641  //
642  //----------------------------------------------------------------------------
643 
651  _update: function deviceControlWidget__update(aForce) {
652  // Get the device state.
653  var state = this._device.state;
654  var readOnly = this._isReadOnly();
655  var supportsReformat = this._device.supportsReformat;
656  var supportsPlaylist = this._supportsPlaylist();
657  var msc = (this._device.parameters.getProperty("DeviceType") == "MSCUSB");
658 
659  var imagesMgmtType = Ci.sbIDeviceLibraryMediaSyncSettings.SYNC_MGMT_NONE;
660  if (this._deviceLibrary) {
661  let currSettings = this._deviceLibrary.syncSettings;
662  imagesMgmtType =
663  currSettings.getMediaSettings(this._deviceLibrary.MEDIATYPE_IMAGE)
664  .mgmtType;
665  }
666 
667  // Do nothing if no device state changed and update is not forced.
668  if (!aForce &&
669  (this._currentImageMgmtType == imagesMgmtType) &&
670  (this._currentState == state) &&
671  (this._currentReadOnly == readOnly) &&
672  (this._currentSupportsReformat == supportsReformat) &&
673  (this._currentSupportsPlaylist == supportsPlaylist) &&
674  (this._currentMsc == msc)) {
675  return;
676  }
677 
678  // Update the current state.
679  this._currentImageMgmtType = imagesMgmtType;
680  this._currentState = state;
681  this._currentReadOnly = readOnly;
682  this._currentSupportsReformat = supportsReformat;
683  this._currentSupportsPlaylist = supportsPlaylist;
684  this._currentMsc = msc;
685 
686  // Update widget attributes.
687  var updateAttributeList = [];
688  this._updateAttribute("accesskey", updateAttributeList);
689  this._updateAttribute("action", updateAttributeList);
690  this._updateAttribute("disabled", updateAttributeList);
691  this._updateAttribute("label", updateAttributeList);
692  this._updateAttribute("hidden", updateAttributeList);
693  this._updateAttribute("checked", updateAttributeList);
694 
695  // Update bound element attributes.
696  if (this._boundElem != this._widget) {
697  DOMUtils.copyAttributes(this._widget,
698  this._boundElem,
699  updateAttributeList,
700  true);
701  }
702  },
703 
709  _supportsPlaylist: function deviceControlWidget__supportsPlaylist() {
710  var capabilities = this._device.capabilities;
711  var sbIDC = Ci.sbIDeviceCapabilities;
712  try {
713  if (capabilities.supportsContent(sbIDC.FUNCTION_DEVICE,
714  sbIDC.CONTENT_PLAYLIST) ||
715  capabilities.supportsContent(sbIDC.FUNCTION_AUDIO_PLAYBACK,
716  sbIDC.CONTENT_PLAYLIST)) {
717  return true;
718  }
719  } catch (e) {}
720 
721  // couldn't find PLAYLIST support in either the DEVICE
722  // or AUDIO_PLAYBACK category
723  return false;
724  },
725 
735  _updateAttribute: function deviceControlWidget__updateAttribute(aAttrName,
736  aAttrList) {
737  // Get the attribute value for the current state.
738  var attrVal = {};
739  if (this._currentReadOnly &&
740  this._getStateAttribute(attrVal, aAttrName, "readonly")) {}
741  else if (!this._currentReadOnly &&
742  this._getStateAttribute(attrVal, aAttrName, "readwrite")) {}
743  else if ((this._currentState == Ci.sbIDevice.STATE_CANCEL) &&
744  this._getStateAttribute(attrVal, aAttrName, "cancel")) {}
745  else if ((this._currentState == Ci.sbIDevice.STATE_COPYING) &&
746  this._getStateAttribute(attrVal, aAttrName, "copy")) {}
747  else if ((this._currentState == Ci.sbIDevice.STATE_DELETING) &&
748  this._getStateAttribute(attrVal, aAttrName, "delete")) {}
749  else if ((this._currentState == Ci.sbIDevice.STATE_MOUNTING) &&
750  this._getStateAttribute(attrVal, aAttrName, "mount")) {}
751  else if ((this._currentState == Ci.sbIDevice.STATE_SYNCING) &&
752  this._getStateAttribute(attrVal, aAttrName, "sync")) {}
753  else if ((this._currentState == Ci.sbIDevice.STATE_UPDATING) &&
754  this._getStateAttribute(attrVal, aAttrName, "update")) {}
755  else if ((this._currentState == Ci.sbIDevice.STATE_TRANSCODE) &&
756  this._getStateAttribute(attrVal, aAttrName, "transcode")) {}
757  else if ((this._currentState == Ci.sbIDevice.STATE_FORMATTING) &&
758  this._getStateAttribute(attrVal, aAttrName, "format")) {}
759  else if ((this._currentState != Ci.sbIDevice.STATE_IDLE) &&
760  this._getStateAttribute(attrVal, aAttrName, "busy")) {}
761  else if ((this._currentState == Ci.sbIDevice.STATE_IDLE) &&
762  this._getStateAttribute(attrVal, aAttrName, "idle")) {}
763  else if (this._deviceLibrary && this._canTriggerSync() &&
764  this._getStateAttribute(attrVal, aAttrName, "can_trigger_sync")) {}
765  else if (this._currentSupportsReformat &&
766  this._getStateAttribute(attrVal,
767  aAttrName,
768  "supports_reformat")) {}
769  else if (this._currentMsc &&
770  this._getStateAttribute(attrVal, aAttrName, "msc")) {}
771  else if (this._currentSupportsPlaylist &&
772  this._getStateAttribute(attrVal,
773  aAttrName,
774  "supports_playlist")) {}
775  else if (!this._currentSupportsPlaylist &&
776  this._getStateAttribute(attrVal,
777  aAttrName,
778  "not_supports_playlist")) {}
779  else if (this._getStateAttribute(attrVal, aAttrName, "default")) {}
780  else this._getStateAttribute(attrVal, aAttrName, null);
781 
782  // Do nothing if no attribute value to set.
783  if ((typeof(attrVal.value) == "undefined") || (attrVal.value == null))
784  return;
785  attrVal = attrVal.value;
786 
787  // If attribute value is "remove_attribute", remove the attribute instead
788  // of setting it.
789  var removeAttr = false;
790  if (attrVal == "remove_attribute")
791  removeAttr = true;
792 
793  // Replace "product_name" in attribute value with the device product name
794  // string.
795  if (attrVal.match(/product_name/)) {
796  var productName = this._getProductName();
797  attrVal = attrVal.replace(/product_name/g, productName);
798  }
799 
800  // Replace "device_model_cap" in attribute value with the device
801  // model/capacity string.
802  if (attrVal.match(/device_model_cap/)) {
803  var deviceModelCap = this._getDeviceModelCap();
804  attrVal = attrVal.replace(/device_model_cap/g, deviceModelCap);
805  }
806 
807  // Update attribute value.
808  if (!removeAttr)
809  this._widget.setAttribute(aAttrName, attrVal);
810  else
811  this._widget.removeAttribute(aAttrName);
812  aAttrList.push(aAttrName);
813  },
814 
815 
831  _getStateAttribute: function deviceControlWidget__getStateAttribute
832  (aAttrVal,
833  aAttrName,
834  aAttrState) {
835  // Get the state attribute name.
836  var stateAttrName = aAttrName;
837  if (aAttrState)
838  stateAttrName += "_" + aAttrState;
839 
840  // Return false if no state attribute value available.
841  if (!this._widget.hasAttribute(stateAttrName))
842  return false;
843 
844  // Return the state attribute value.
845  aAttrVal.value = this._widget.getAttribute(stateAttrName);
846  return true;
847  },
848 
849 
855  _getBoundElem: function deviceControlWidget__getBoundElem() {
856  var boundElem;
857 
858  // Get the bound element from the bind element attributes.
859  boundElem = this._getElementFromSpec(this._widget, "bindforward");
860  boundElem = this._getElementFromSpec(boundElem, "bindelem");
861 
862  // Set the bound element.
863  this._boundElem = boundElem;
864  this._widget.boundElem = boundElem;
865  },
866 
867 
878  _getElementFromSpec: function deviceControlWidget__getElement(aElementStart,
879  aElementSpec) {
880  // Get the element from the spec.
881  var element;
882  var elementSpec = this._widget.getAttribute(aElementSpec).split("=");
883  switch (elementSpec[0]) {
884  case "prev" :
885  element = aElementStart.previousSibling;
886  while (element && (element.nodeType != Node.ELEMENT_NODE)) {
887  element = element.previousSibling;
888  }
889  break;
890 
891  case "next" :
892  element = aElementStart.nextSibling;
893  while (element && (element.nodeType != Node.ELEMENT_NODE)) {
894  element = element.nextSibling;
895  }
896  break;
897 
898  case "parent" :
899  element = aElementStart.parentNode;
900  break;
901 
902  default :
903  element = aElementStart;
904  break;
905  }
906 
907  return element;
908  },
909 
910 
917  _getServicePaneNode: function deviceControlWidget__getServicePaneNode() {
918  // Get the service pane node ID.
919  var servicePaneNodeID = this._widget.getAttribute("service_pane_node_id");
920  if (!servicePaneNodeID)
921  return null;
922 
923  // Get the service pane node.
924  var servicePaneService = Cc["@songbirdnest.com/servicepane/service;1"]
925  .getService(Ci.sbIServicePaneService);
926  servicePaneNode = servicePaneService.getNode(servicePaneNodeID);
927 
928  return servicePaneNode;
929  },
930 
931  _canTriggerSync: function deviceControlWidget__canTriggerSync() {
932  // Can not sync if there is no library.
933  if (!this._deviceLibrary)
934  return false;
935 
936  // Check photo sync settings since they are separate from the other types
937  let syncSettings = this._deviceLibrary.syncSettings;
938 
939  // Can not sync if there are no settings.
940  if (!syncSettings)
941  return false;
942 
943  let mediaSettings = syncSettings.getMediaSettings(
944  this._deviceLibrary.MEDIATYPE_IMAGE);
945  // Can not sync if there are no settings for IMAGE media type.
946  if (!mediaSettings)
947  return false;
948 
949  return (mediaSettings.mgmtType !=
950  Ci.sbIDeviceLibraryMediaSyncSettings.SYNC_MGMT_NONE);
951  }
952 };
const Cu
function Fx prototype initialize
const Cc
var Application
Definition: sbAboutDRM.js:37
function SBFormattedString(aKey, aParams, aDefault, aStringBundle)
var event
function DOMEventListenerSet()
Definition: DOMUtils.jsm:766
function SBString(aKey, aDefault, aStringBundle)
Definition: StringUtils.jsm:93
let window
var _this
return null
Definition: FeedWriter.js:1143
let node
function deviceControlWidget(aWidget)
var prefs
Definition: FeedWriter.js:1169
countRef value
Definition: FeedWriter.js:1423
const Cr
let promptService
const Ci
Javascript wrappers for common library tasks.
var gServicePane
Definition: mainWinInit.js:39
_getSelectedPageStyle s i
var sbCDDeviceUtils