25 const SB_NS =
'http://songbirdnest.com/data/1.0#';
27 Components.utils.import(
"resource://app/jsmodules/StringUtils.jsm");
28 Components.utils.import(
"resource://app/jsmodules/sbLibraryUtils.jsm");
29 Components.utils.import(
"resource://app/jsmodules/kPlaylistCommands.jsm");
30 Components.utils.import(
"resource://app/jsmodules/ArrayConverter.jsm");
31 Components.utils.import(
"resource://app/jsmodules/sbCDDeviceUtils.jsm");
32 Components.utils.import(
"resource://app/jsmodules/sbProperties.jsm");
33 Components.utils.import(
"resource://gre/modules/XPCOMUtils.jsm");
35 if (typeof(
Cc) ==
"undefined")
36 var
Cc = Components.classes;
37 if (typeof(
Ci) ==
"undefined")
38 var
Ci = Components.interfaces;
39 if (typeof(
Cu) ==
"undefined")
40 var
Cu = Components.utils;
41 if (typeof(
Cr) ==
"undefined")
42 var
Cr = Components.results;
106 _mediaListView:
null,
112 _deviceLibrary:
null,
115 _onDeviceManagerEventClosure:
null,
118 _transcodePrefBranch:
null,
120 _supportedProfiles:
null,
123 logoTimerEnabled:
false,
124 _lookupDelayTimer:
null,
126 _libraryListener:
null,
128 onLoad:
function cdripController_onLoad() {
130 this._device = this._getDevice();
133 this._getDeviceLibrary();
137 if (!this._device || !this._deviceLibrary) {
139 browser.getTabForDocument(document).backWithDefault();
144 this._updateHeaderView();
145 this._toggleRipStatus(
false);
147 this._logoTimer = Cc[
"@mozilla.org/timer;1"]
148 .createInstance(Ci.nsITimer);
149 this._lookupDelayTimer = Cc[
"@mozilla.org/timer;1"]
150 .createInstance(Ci.nsITimer);
152 this._toggleLookupNotification(
false);
154 var
eventTarget = this._device.QueryInterface(Ci.sbIDeviceEventTarget);
155 eventTarget.addEventListener(
this);
158 this._onDeviceManagerEventClosure =
159 function cdripController__onDeviceManagerEventClosure(aEvent)
160 {
self._onDeviceManagerEvent(aEvent); };
161 var deviceManagerSvc = Cc[
"@songbirdnest.com/Songbird/DeviceManager;2"]
162 .getService(Ci.sbIDeviceManager2);
163 deviceManagerSvc.addEventListener(this._onDeviceManagerEventClosure);
166 this._updateRipSettings();
167 this._togglePlayerControls(
true);
168 this._loadPlaylist();
170 var servicePaneNode =
171 Cc[
"@songbirdnest.com/servicepane/device;1"]
172 .getService(Ci.sbIDeviceServicePaneService)
173 .getNodeForDevice(this._device);
174 if (servicePaneNode) {
175 document.title = servicePaneNode.displayName;
179 document.title =
SBString(
"cdrip.service.default.node_name");
183 this._transcodePrefBranch = Cc[
"@mozilla.org/preferences-service;1"]
184 .getService(Ci.nsIPrefService)
185 .getBranch(
"songbird.cdrip.transcode_profile.")
186 .QueryInterface(Ci.nsIPrefBranch2);
187 this._transcodePrefBranch.addObserver(
"",
this,
false);
199 this._checkIfNeedsLookup();
202 onUnload:
function cdripController_onUnload() {
204 this._mediaListView.mediaList.removeListener(this._libraryListener);
205 this._libraryListener =
null;
207 if (this._onDeviceManagerEventClosure) {
208 var deviceManagerSvc = Cc[
"@songbirdnest.com/Songbird/DeviceManager;2"]
209 .getService(Ci.sbIDeviceManager2);
210 deviceManagerSvc.removeEventListener(this._onDeviceManagerEventClosure);
213 this._togglePlayerControls(
false);
215 var
eventTarget = this._device.QueryInterface(Ci.sbIDeviceEventTarget);
216 eventTarget.removeEventListener(
this);
217 this._device.removeEventListener(
this);
220 this._transcodePrefBranch.removeObserver(
"",
this,
false);
221 this._transcodePrefBranch =
null;
224 onDeviceEvent:
function cdripController_onDeviceEvent(aEvent) {
225 switch (aEvent.type) {
226 case Ci.sbIDeviceEvent.EVENT_DEVICE_READY:
227 this._checkIfNeedsLookup();
231 case Ci.sbICDDeviceEvent.EVENT_CDLOOKUP_INITIATED:
232 this._toggleLookupNotification(
true);
236 case Ci.sbICDDeviceEvent.EVENT_CDLOOKUP_COMPLETED:
237 this._toggleLookupNotification(
false);
240 case Ci.sbIDeviceEvent.EVENT_DEVICE_STATE_CHANGED:
241 var device = aEvent.origin.QueryInterface(Ci.sbIDevice);
242 if (device.id.toString() == this._deviceID) {
243 this._updateHeaderView();
247 case Ci.sbICDDeviceEvent.EVENT_CDRIP_COMPLETED:
248 this._toggleRipStatus(
true);
257 if (
topic ==
'timer-callback') {
258 if (subject == this._logoTimer) {
259 this.logoTimerEnabled =
false;
261 if (this._device.state != Ci.sbICDDeviceEvent.STATE_LOOKINGUPCD)
262 this._toggleLookupNotification(
false);
263 }
else if (subject == this._lookupDelayTimer) {
265 if (this._device.state == Ci.sbICDDeviceEvent.STATE_LOOKINGUPCD) {
266 this._toggleLookupLabel(
true);
271 this._updateRipSettings();
275 showCDRipSettings:
function cdripController_showCDRipSettings() {
276 Cc[
"@mozilla.org/appshell/window-mediator;1"]
277 .getService(Ci.nsIWindowMediator)
278 .getMostRecentWindow(
"Songbird:Main")
279 .SBOpenPreferences(
"paneCDRip");
282 _onDeviceManagerEvent:
283 function cdripController__onDeviceManagerEvent(aEvent) {
284 switch (aEvent.type) {
285 case Ci.sbIDeviceEvent.EVENT_DEVICE_REMOVED :
287 var device = aEvent.data.QueryInterface(Ci.sbIDevice);
288 if (device.id.toString() == this._deviceID) {
290 browser.getTabForDocument(document).backWithDefault();
299 _toggleLookupNotification:
function
300 cdripController_toggleLookupNotification(show) {
302 var manager = Cc[
"@songbirdnest.com/Songbird/MetadataLookup/manager;1"]
303 .getService(Ci.sbIMetadataLookupManager);
305 var provider = manager.defaultProvider;
306 var providerLogo = provider.logoURL;
307 var providerName = provider.name;
308 var providerURL = provider.infoURL;
311 this._showLookupVendorInfo(providerLogo, providerName, providerURL);
314 this._logoTimer.init(
this,
316 Ci.nsITimer.TYPE_ONE_SHOT);
317 this.logoTimerEnabled =
true;
325 this._lookupDelayTimer.init(
this,
327 Ci.nsITimer.TYPE_ONE_SHOT);
337 if (!this.logoTimerEnabled) {
338 this._hideLookupVendorInfo();
341 this._toggleLookupLabel(
false);
348 this._updateHeaderView();
351 _toggleLookupLabel:
function cdripController_lookupLabel(show) {
358 "chrome://songbird/skin/base-elements/icon-loading-large.png");
360 SBString(
"cdrip.mediaview.status.lookup"));
377 this._updateHeaderView();
380 _toggleRipStatus:
function cdripController_toggleRipStatus(aShouldShow) {
391 var status = this._getLastTranscodeStatus();
392 var statusLabel =
"";
393 var statusImageSrc =
"";
396 statusLabel =
"cdrip.mediaview.status.rip_success";
397 statusImageSrc =
"chrome://songbird/skin/device/icon-complete.png";
401 statusLabel =
"cdrip.mediaview.status.rip_failed";
402 statusImageSrc =
"chrome://songbird/skin/device/icon-warning.png";
406 statusLabel =
"cdrip.mediaview.status.rip_partial";
407 statusImageSrc =
"chrome://songbird/skin/device/icon-warning.png";
411 statusLabel.Truncate();
412 statusImageSrc.Truncate();
416 Cu.reportError(
"Unhandled transcode state!");
431 _updateHeaderView:
function cdripController_updateHeaderView() {
432 switch (this._device.state) {
434 case Ci.sbICDDeviceEvent.STATE_LOOKINGUPCD:
439 case Ci.sbIDevice.STATE_TRANSCODE:
441 this._showSettingsView();
442 this._toggleRipStatus(
false);
457 this._showSettingsView();
472 _updateRipSettings:
function cdripController_updateRipSettings() {
473 var profileId = this._device.getPreference(
"transcode_profile.profile_id");
477 var profiles = this._findSupportedProfiles();
480 profile = this._profileFromProfileId(profileId, profiles);
481 bitrate = parseInt(this._device.getPreference(
482 "transcode_profile.audio_properties.bitrate"));
485 var highestPriority = 0;
489 for (var
i = 0;
i < profiles.length;
i++) {
490 var current = profiles[
i];
491 if (!profile || current.priority > highestPriority) {
493 highestPriority = profile.priority;
498 var hasBitrate =
false;
499 var propertiesArray = profile.audioProperties;
500 if (propertiesArray) {
501 for (var
i = 0;
i < propertiesArray.length;
i++) {
502 var prop = propertiesArray.queryElementAt(
i,
503 Ci.sbITranscodeProfileProperty);
504 if (prop.propertyName ==
"bitrate") {
507 bitrate = parseInt(prop.value);
516 bitrateLabel.setAttribute(
"value",
"" + (bitrate / 1000) +
" kbps");
523 formatLabel.setAttribute(
"value", profile.description);
526 _findSupportedProfiles:
527 function cdripController_findSupportedProfiles()
529 if (this._supportedProfiles)
530 return this._supportedProfiles;
532 this._supportedProfiles = [];
534 var transcodeManager =
535 Cc[
"@songbirdnest.com/Songbird/Mediacore/TranscodeManager;1"]
536 .getService(Ci.sbITranscodeManager);
537 var profiles = transcodeManager.getTranscodeProfiles(
538 Ci.sbITranscodeProfile.TRANSCODE_TYPE_AUDIO);
540 for (var
i = 0;
i < profiles.length;
i++) {
541 var profile = profiles.queryElementAt(
i, Ci.sbITranscodeProfile);
543 if (profile.type == Ci.sbITranscodeProfile.TRANSCODE_TYPE_AUDIO)
545 this._supportedProfiles.push(profile);
548 return this._supportedProfiles;
551 _profileFromProfileId:
552 function cdripController_profileFromProfileId(aId, aProfiles)
554 for (var
i = 0;
i < aProfiles.length;
i++) {
555 var profile = aProfiles[
i];
556 if (profile.id == aId)
562 disableTags : [
'sb-player-back-button',
'sb-player-playpause-button',
563 'sb-player-forward-button',
'sb-player-volume-slider',
564 'sb-player-shuffle-button',
'sb-player-repeat-button'],
565 disableMenuControls : [
'play',
'next',
'prev',
'shuf',
'repx',
567 _togglePlayerControls:
function
568 cdripController_togglePlayerControls(disabled) {
571 var mainWin = Cc[
"@mozilla.org/appshell/window-mediator;1"]
572 .getService(Ci.nsIWindowMediator)
573 .getMostRecentWindow(
"Songbird:Main");
579 for (var
i in this.disableTags) {
580 var elements = mainWin.document.getElementsByTagName(this.disableTags[
i]);
581 for (var j=0; j<elements.length; j++) {
583 elements[j].setAttribute(
'disabled',
'true');
585 elements[j].removeAttribute(
'disabled');
591 var pls = document.getElementById(
"sb-cdrip-playlist");
592 var playMenuItem = mainWin.document.getElementById(
"menuitem_control_play");
594 pls.addEventListener(
"Play", this._onPlay,
false);
595 mainWin.addEventListener(
"keypress", this._onKeypress,
true);
596 for each (var
i in this.disableMenuControls) {
597 var
menuItem = mainWin.document.getElementById(
"menuitem_control_" + i);
598 menuItem.setAttribute(
"disabled",
"true");
601 pls.removeEventListener(
"Play", this._onPlay,
false);
602 mainWin.removeEventListener(
"keypress", this._onKeypress,
true);
603 playMenuItem.removeAttribute(
"disabled");
604 for each (var i
in this.disableMenuControls) {
605 var
menuItem = mainWin.document.getElementById(
"menuitem_control_" + i);
606 menuItem.removeAttribute(
"disabled");
611 _onPlay:
function(e) {
616 _onKeypress:
function(e) {
618 if (document.commandDispatcher.focusedWindow !=
window ||
619 (document.commandDispatcher.focusedElement &&
620 document.commandDispatcher.focusedElement.id !=
"sb-playlist-tree"))
625 if (e.charCode != KeyboardEvent.DOM_VK_SPACE ||
626 e.ctrlKey || e.altKey || e.metaKey || e.altGraphKey)
636 _ejectDevice:
function cdripController_ejectDevice() {
638 this._device.eject();
642 _startRip:
function cdripController_startRip() {
646 Cu.reportError(
"No device defined to start rip on.");
650 _stopRip:
function cdripController_stopRip() {
652 this._device.cancelRequests();
654 Cu.reportError(
"No device defined to stop rip on.");
658 _hideSettingsView:
function cdripController_hideSettingsView() {
668 ripStatusHbox.setAttribute(
"flex",
"1");
670 ripStatusHbox.style.minHeight = settingsHeight +
"px";
672 this._isSettingsViewVisible =
false;
675 _showSettingsView:
function cdripController_showSettingsView() {
680 ripStatusHbox.removeAttribute(
"flex");
683 this._isSettingsViewVisible =
true;
686 _hideElement:
function cdripController_hideElement(aElementId) {
687 document.getElementById(aElementId).setAttribute(
"hidden",
"true");
690 _showElement:
function cdripController_showElement(aElementId) {
691 document.getElementById(aElementId).removeAttribute(
"hidden");
694 _isElementHidden:
function cdripController_isElementHidden(aElementId) {
695 return document.getElementById(aElementId).hasAttribute(
"hidden");
698 _disableCommand:
function cdripController_disableCommand(aElementId) {
699 document.getElementById(aElementId).setAttribute(
"disabled",
"true");
702 _enableCommand:
function cdripController_enableCommand(aElementId) {
703 document.getElementById(aElementId).removeAttribute(
"disabled");
706 _setLabelValue:
function cdripController_setLabelValue(aElementId,
aValue) {
707 document.getElementById(aElementId).value =
aValue;
710 _setImageSrc:
function cdripController_setImageSrc(aElementId,
aValue) {
711 document.getElementById(aElementId).src =
aValue;
714 _setToolTip:
function cdripController_setToolTip(aElementId,
aValue) {
715 document.getElementById(aElementId).setAttribute(
'tooltiptext',
aValue);
718 _showLookupVendorInfo:
function
719 cdripController_showLookupLogo(aProviderLogoSrc,
722 if (aProviderLogoSrc) {
743 _hideLookupVendorInfo:
function cdripController_hideLookupVendorInfo() {
750 _setLogoURLListener:
function cdripController_setLogoURLListener(aElementId, aURL) {
751 var
element = document.getElementById(aElementId);
753 element.setAttribute(
'class',
"sb-cdrip-link");
754 element.addEventListener(
'click',
function(
event) {
761 _loadPlaylist:
function cdripController_loadPlaylist() {
762 this._mediaListView = this._getMediaListView();
763 if (!this._mediaListView) {
764 Cu.reportError(
"Unable to get media list view for device.");
771 this._clearFilterLists();
774 this._mediaListView.mediaList.setProperty(
775 "http://songbirdnest.com/data/1.0#dontWriteMetadata", 1);
778 this._playlist.disableDrag =
true;
780 this._playlist.disableDrop =
true;
783 if (!this._mediaListView.mediaList.getProperty(SBProperties.columnSpec)) {
784 this._mediaListView.mediaList.setProperty(SBProperties.columnSpec,
785 "http://songbirdnest.com/data/1.0#shouldRip 25 " +
786 "http://songbirdnest.com/data/1.0#trackNumber 50 a " +
787 "http://songbirdnest.com/data/1.0#cdRipStatus 75 " +
788 "http://songbirdnest.com/data/1.0#trackName 255 " +
789 "http://songbirdnest.com/data/1.0#duration 70 " +
790 "http://songbirdnest.com/data/1.0#artistName 122 " +
791 "http://songbirdnest.com/data/1.0#albumName 122 " +
792 "http://songbirdnest.com/data/1.0#genre 70");
798 Components.classes[
"@songbirdnest.com/Songbird/PlaylistCommandsManager;1"]
799 .createInstance(Components.interfaces.sbIPlaylistCommandsManager);
800 var cmds = mgr.request(kPlaylistCommands.MEDIALIST_CDDEVICE_LIBRARY);
803 this._playlist.bind(this._mediaListView, cmds);
806 this._libraryListener =
807 new CDRipLibraryListener(
this, this._playlist);
808 var
flags = Ci.sbIMediaList.LISTENER_FLAGS_ITEMUPDATED;
809 this._mediaListView.mediaList.addListener(this._libraryListener,
817 _getMediaListView:
function cdripController_getMediaListView() {
822 var lib = this._getDeviceLibrary();
824 Cu.reportError(
"Unable to get library for device: " + this._device.id);
829 return lib.createView();
835 _clearFilterLists:
function cdripController_clearFilterLists() {
836 this._mediaListView.filterConstraint =
843 _checkIfNeedsLookup:
function cdripController_checkIfNeedsLookup() {
848 var lib = this._getDeviceLibrary();
850 Cu.reportError(
"Unable to get library for device: " + this._device.id);
854 var deviceNeedsLookupPref =
"songbird.cdrip." + lib.guid +
".needsLookup";
855 if (
Application.prefs.has(deviceNeedsLookupPref)) {
856 var shouldLookup =
Application.prefs.getValue(deviceNeedsLookupPref,
false);
858 Application.prefs.setValue(deviceNeedsLookupPref,
false);
867 _getLastTranscodeStatus:
function cdripController_getLastTranscodeStatus() {
873 var deviceLibrary = this._getDeviceLibrary();
878 Cc[
"@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
879 .createInstance(Ci.sbIMutablePropertyArray);
881 propArray.appendProperty(SBProperties.cdRipStatus,
"4|100");
882 propArray.appendProperty(SBProperties.shouldRip,
"1");
884 var abortedItems = deviceLibrary.getItemsByProperties(propArray);
885 abortCount = abortedItems.length;
887 catch (err
if err.result == Cr.NS_ERROR_NOT_AVAILABLE) {
892 Cu.reportError(
"ERROR GETTING TRANSCODE ERROR COUNT " + err);
901 Cc[
"@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1"]
902 .createInstance(Ci.sbIMutablePropertyArray);
903 propArray.appendProperty(SBProperties.cdRipStatus,
"3|100");
904 propArray.appendProperty(SBProperties.shouldRip,
"1");
906 var rippedItems = deviceLibrary.getItemsByProperties(propArray);
907 errorCount = rippedItems.length;
909 catch (err
if err.result == Cr.NS_ERROR_NOT_AVAILABLE) {
914 Cu.reportError(
"ERROR GETTING TRANSCODE ERROR COUNT " + err);
918 if (errorCount > 0) {
921 deviceLibrary.getItemsByProperty(SBProperties.shouldRip,
"1");
922 if (errorCount == shouldRipItems.length)
931 _getDeviceLibrary:
function cdripController_getDeviceLibrary() {
932 if (this._deviceLibrary)
933 return this._deviceLibrary;
940 var libraries = this._device.content.libraries;
941 if (libraries.length < 1) {
943 Cu.reportError(
"Device " + this._device +
" has no libraries!");
948 this._deviceLibrary = libraries.queryElementAt(0, Ci.sbIMediaList);
949 if (!this._deviceLibrary) {
950 Cu.reportError(
"Unable to get library for device: " + aDevice.id);
954 return this._deviceLibrary;
960 _getDevice:
function cdripController_getDevice() {
962 var queryMap = this._parseQueryString();
964 this._deviceID = queryMap[
"device-id"];
967 var deviceManager = Cc[
"@songbirdnest.com/Songbird/DeviceManager;2"]
968 .getService(Ci.sbIDeviceManager2);
971 return deviceManager.getDevice(Components.ID(
this._deviceID));
973 Cu.reportError(
"Device: " + this._deviceID +
" does not exist");
983 _parseQueryString:
function cdripController_parseQueryString() {
984 var queryString = (location.search ||
"?").substr(1).split(
"&");
985 var queryObject = {};
987 for each (var pair
in queryString) {
1000 get mediaListView() {
1001 return window.cdripController._mediaListView;
1003 set mediaListView(
value) {},
1005 get isOnlyView()
true,
1007 highlightItem:
function(aIndex) {
1008 window.cdripController._playlist.highlightItem(aIndex);
1011 canDrop:
function(aEvent, aSession) {
1014 onDrop:
function(aEvent, aSession) {
1026 function CDRipLibraryListener(aCallback, aPlaylistObject)
1028 this._mCallback = aCallback;
1029 this._mPlaylist = aPlaylistObject;
1030 this._mTreeBoxObject = aPlaylistObject.tree.boxObject;
1033 CDRipLibraryListener.prototype =
1036 _mTreeBoxObject:
null,
1042 onItemAdded:
function(aMediaList, aMediaItem, aIndex) {
1046 onBeforeItemRemoved:
function(aMediaList, aMediaItem, aIndex) {
1050 onAfterItemRemoved:
function(aMediaList, aMediaItem, aIndex) {
1054 onItemUpdated:
function(aMediaList, aMediaItem, aProperties) {
1056 for (var
i = 0;
i < aProperties.length;
i++) {
1057 if (aProperties.getPropertyAt(
i).id == SBProperties.isReadOnly) {
1058 this._mTreeBoxObject.invalidate();
1059 this._mPlaylist.refreshCommands(
false);
1067 onItemMoved:
function(aMediaList, aFromIndex, aToIndex) {
1071 onBeforeListCleared:
function(aMediaList, aExcludeLists) {
1075 onListCleared:
function(aMediaList, aExcludeLists) {
1079 onBatchBegin:
function(aMediaList) {
1083 onBatchEnd:
function(aMediaList) {
function SBFormattedString(aKey, aParams, aDefault, aStringBundle)
sbDeviceFirmwareAutoCheckForUpdate prototype flags
sbOSDControlService prototype QueryInterface
function SBString(aKey, aDefault, aStringBundle)
Javascript wrappers for common library tasks.
function onUnload()
onUnload - called when the cover preview window unloads.
_getSelectedPageStyle s i
sbDeviceFirmwareAutoCheckForUpdate prototype observe