29 Cu.import(
"resource://app/jsmodules/DOMUtils.jsm");
32 if (typeof LastFm ==
'undefined') {
36 if (typeof(gBrowser) ==
"undefined") {
37 var gBrowser =
Cc[
'@mozilla.org/appshell/window-mediator;1']
38 .getService(
Ci.nsIWindowMediator)
39 .getMostRecentWindow(
'Songbird:Main')
44 busy:
'chrome://sb-lastfm/skin/busy.png',
45 disabled:
'chrome://sb-lastfm/skin/disabled.png',
46 disabled_libre:
'chrome://sb-lastfm/skin/librefm_disabled.png',
47 logged_in_libre:
'chrome://sb-lastfm/skin/librefm.png',
48 logged_in:
'chrome://sb-lastfm/skin/as.png',
49 logged_out:
'chrome://sb-lastfm/skin/disabled.png',
50 error:
'chrome://sb-lastfm/skin/error.png',
51 login_error:
'chrome://sb-lastfm/skin/error.png'
54 LastFm.URL_SIGNUP =
'http://www.last.fm/join/';
55 LastFm.URL_PASSWORD =
'http://www.last.fm/settings/lostpassword';
59 LastFm.onLoad =
function() {
61 this._strings = document.getElementById(
"lastfmStrings");
64 this._service = Components.classes[
'@songbirdnest.com/lastfm;1']
65 .getService().wrappedJSObject;
67 this._service.listeners.add(
this);
69 #ifdef METRICS_ENABLED
71 this.metrics =
Cc[
'@songbirdnest.com/Songbird/Metrics;1']
72 .getService(
Ci.sbIMetrics);
78 this._menuLogin = document.getElementById(
'lastfmMenuLogin');
79 this._menuLogout = document.getElementById(
'lastfmMenuLogout');
80 this._menuEnableScrobbling =
81 document.getElementById(
'lastfmMenuEnableScrobbling');
84 this._statusIcon = document.getElementById(
'lastfmStatusIcon');
87 this._panelBinding = document.getElementById(
'lastfmLoginPanel');
90 this._panel = this._getElement(this._panelBinding,
'loginPanel');
91 this._tagPanel = document.getElementById(
'lastfmTagPanel');
94 this._deck = this._getElement(this._panelBinding,
'loginDeck');
97 this._login = this._getElement(this._panelBinding,
'loginBox');
99 this._username = this._getElement(this._panelBinding,
'username');
101 this._password = this._getElement(this._panelBinding,
'password');
103 this._loginAutoLogin = this._getElement(this._panelBinding,
106 this._abortButton = this._getElement(this._panelBinding,
109 this._loginButton = this._getElement(this._panelBinding,
'loginButton');
111 this._loginError = this._getElement(this._panelBinding,
'loginError');
113 this._newAccountGroupbox = this._getElement(this._panelBinding,
114 'newAccountGroupbox');
116 this._signupButton = this._getElement(this._panelBinding,
'signupButton');
118 this._forgotpass = this._getElement(this._panelBinding,
'forgotpass');
119 this._forgotpass.textContent =
120 this._strings.getString(
'lastfm.forgotpass.label');
123 this._loggingIn = this._getElement(this._panelBinding,
'loginProgressBox');
126 this._profile = this._getElement(this._panelBinding,
'profileBox');
128 this._image = this._getElement(this._panelBinding,
'image');
130 this._realname = this._getElement(this._panelBinding,
'realname');
132 this._tracks = this._getElement(this._panelBinding,
'profileDescription');
134 this._scrobble = this._getElement(this._panelBinding,
'profileCheckbox');
136 this._profileAutoLogin = this._getElement(this._panelBinding,
144 var onMenuLogin =
function(
event) {
145 #ifdef METRICS_ENABLED
146 self.metrics.metricsInc(
'lastfm',
'menu',
'login');
150 this._domEventListenerSet.add(this._menuLogin,
156 var onMenuLogout =
function(
event) {
157 #ifdef METRICS_ENABLED
158 self.metrics.metricsInc(
'lastfm',
'menu',
'logout');
162 this._domEventListenerSet.add(this._menuLogout,
168 var onMenuEnableScrobbling =
function(
event) {
169 self.metrics.metricsInc(
'lastfm',
'menu',
'scrobble');
170 self.toggleShouldScrobble();
172 this._domEventListenerSet.add(this._menuEnableScrobbling,
174 onMenuEnableScrobbling,
179 var onStatusIconClicked =
function(
event) {
181 if (
event.button != 0)
return;
183 #ifdef METRICS_ENABLED
184 self.metrics.metricsInc(
'lastfm',
'icon',
'click');
187 if (
self._service.loggedIn) {
189 self.toggleShouldScrobble();
195 this._domEventListenerSet.add(this._statusIcon,
202 var onStatusIconContextMenu =
function(
event) {
203 #ifdef METRICS_ENABLED
204 self.metrics.metricsInc(
'lastfm',
'icon',
'context');
209 this._domEventListenerSet.add(this._statusIcon,
211 onStatusIconContextMenu,
216 var onAbortButtonClicked =
function(
event) {
self._panel.hidePopup(); };
217 this._domEventListenerSet.add(this._abortButton,
219 onAbortButtonClicked,
225 var onSignupButtonClicked =
function(
event) {
228 this._domEventListenerSet.add(this._signupButton,
230 onSignupButtonClicked,
235 var onForgotpass =
function(
event) {
236 self.loadURI(
self.URL_PASSWORD,
event);
238 this._domEventListenerSet.add(this._forgotpass,
245 var onProfileUrlClicked =
function(
event) {
246 self.loadURI(
self._service.profileurl,
event);
248 this._domEventListenerSet.add(this._image,
253 this._domEventListenerSet.add(this._realname,
259 var onTracksUrlClicked =
function(
event) {
260 self.loadURI(
'http://www.last.fm/user/' +
261 self._service.username +
'/charts/',
event);
263 this._domEventListenerSet.add(this._tracks,
270 var onAutoLoginToggled =
function(
event) {
self.toggleAutoLogin(); };
271 this._domEventListenerSet.add(this._loginAutoLogin,
276 this._domEventListenerSet.add(this._profileAutoLogin,
283 var onScrobbleToggled =
function(
event) {
self.toggleShouldScrobble(); };
284 this._domEventListenerSet.add(this._scrobble,
290 var onButtonClicked =
function(
event) {
self._handleUIEvents(
event); };
291 this._domEventListenerSet.add(this._panelBinding,
292 'login-button-clicked',
296 this._domEventListenerSet.add(this._panelBinding,
297 'cancel-button-clicked',
301 this._domEventListenerSet.add(this._panelBinding,
302 'logout-button-clicked',
308 this._username.value = this._service.username;
309 this._password.value = this._service.password;
312 if (!this._username.value || !
this._password.value) {
313 this._loginButton.disabled =
true;
317 var faceplateParent = document.getElementById(
'faceplate-tool-bar');
318 if (faceplateParent) {
319 this._faceplate = document.createElement(
'hbox');
320 this._faceplate.setAttribute(
'id',
'lastfmFaceplate');
321 faceplateParent.insertBefore(this._faceplate, faceplateParent.firstChild);
322 this._faceplateLove = document.createElement(
'image');
323 this._faceplateLove.setAttribute(
'id',
'lastfmFaceplateLove');
324 this._faceplateLove.setAttribute(
'mousethrough',
'never');
325 this._faceplateLove.setAttribute(
'tooltiptext',
326 this._strings.getString(
'lastfm.faceplate.love.tooltip'));
328 var onFaceplateLoveClicked =
function(
event) {
329 #ifdef METRICS_ENABLED
330 self.metrics.metricsInc(
'lastfm',
'faceplate',
'love');
333 if (
self._service.loveTrack &&
self._service.love) {
335 self._service.loveBan(
null,
false);
338 self._service.loveBan(
gMM.sequencer.currentItem,
true);
341 this._domEventListenerSet.add(this._faceplateLove,
343 onFaceplateLoveClicked,
346 this._faceplate.appendChild(this._faceplateLove);
348 this._faceplateBan = document.createElement(
'image');
349 this._faceplateBan.setAttribute(
'id',
'lastfmFaceplateBan');
350 this._faceplateBan.setAttribute(
'mousethrough',
'never');
351 this._faceplateBan.setAttribute(
'tooltiptext',
352 this._strings.getString(
'lastfm.faceplate.ban.tooltip'));
354 var onFaceplateBanClicked =
function(
event) {
355 #ifdef METRICS_ENABLED
356 self.metrics.metricsInc(
'lastfm',
'faceplate',
'ban');
359 if (
self._service.loveTrack && !
self._service.love) {
361 self._service.loveBan(
null,
false);
364 self._service.loveBan(
gMM.sequencer.currentItem,
false);
365 gMM.sequencer.next();
368 this._domEventListenerSet.add(this._faceplateBan,
370 onFaceplateBanClicked,
373 this._faceplate.appendChild(this._faceplateBan);
375 this._faceplateTag = document.createElement(
'image');
376 this._faceplateTag.setAttribute(
'id',
'lastfmFaceplateTag');
377 this._faceplateTag.setAttribute(
'mousethrough',
'never');
378 this._faceplateTag.setAttribute(
'tooltiptext',
379 this._strings.getString(
'lastfm.faceplate.tag.tooltip'));
381 var onFaceplateTagClicked =
function(
event) {
382 #ifdef METRICS_ENABLED
383 self.metrics.metricsInc(
'lastfm',
'faceplate',
'tag');
386 self._tagPanel.openPopup(
event.target);
387 var globalTags = document.getElementById(
"global-tags");
388 var userTags = document.getElementById(
"user-tags");
390 while (userTags.firstChild)
391 userTags.removeChild(userTags.firstChild);
392 while (globalTags.firstChild)
393 globalTags.removeChild(globalTags.firstChild);
396 for (var
tag in
self._service.userTags) {
397 var removable =
self._service.userTags[
tag];
398 var hbox =
self.showOneMoreTag(
tag, removable);
399 userTags.appendChild(hbox);
401 for (var
tag in
self._service.globalTags) {
402 var removable =
self._service.globalTags[
tag];
403 var hbox =
self.showOneMoreTag(
tag, removable);
404 globalTags.appendChild(hbox);
407 if (!userTags.firstChild) {
408 document.getElementById(
"label-user-tags")
409 .style.visibility =
"collapse";
411 if (!globalTags.firstChild) {
412 document.getElementById(
"label-global-tags")
413 .style.visibility =
"collapse";
416 this._domEventListenerSet.add(this._faceplateTag,
418 onFaceplateTagClicked,
421 this._faceplate.appendChild(this._faceplateTag);
424 this.
prefs =
Cc[
"@mozilla.org/preferences-service;1"]
425 .getService(
Ci.nsIPrefService)
426 .getBranch(
"extensions.lastfm.")
427 .QueryInterface(
Ci.nsIPrefBranch2);
428 this.
prefs.addObserver(
"", this.prefObserver,
false);
432 Cc[
'@songbirdnest.com/Songbird/Mediacore/Manager;1']
433 .getService(
Ci.sbIMediacoreManager)
437 this.setLoginError(
null);
439 this.onAutoLoginChanged(this._service.autoLogin);
441 this.onShouldScrobbleChanged(this._service.shouldScrobble);
443 this.onLoggedInStateChanged();
448 if (this._service.shouldAutoLogin()) {
449 this._service.login();
453 this._domEventListenerSet.add(
window,
455 this.showCurrentTrack,
460 LastFm._getElement =
function(aWidget, aElementID) {
461 return document.getAnonymousElementByAttribute(aWidget,
"sbid", aElementID);
464 LastFm.onMediacoreEvent =
function(aEvent) {
465 switch(aEvent.type) {
466 case Ci.sbIMediacoreEvent.TRACK_CHANGE:
468 var mediaItem = aEvent.data;
469 if (mediaItem.getProperty(SBProperties.contentType) !=
"audio") {
470 document.getElementById(
"lastfmFaceplate").hidden =
true;
472 document.getElementById(
"lastfmFaceplate").hidden =
false;
478 LastFm.showOneMoreTag =
function(tagName, removable) {
479 var hbox = document.createElement(
'hbox');
480 hbox.setAttribute(
"align",
"center");
481 var delTag = document.createElement(
'image');
482 delTag.setAttribute(
"mousethrough",
"never");
483 delTag.setAttribute(
'id', tagName);
484 hbox.appendChild(delTag);
485 var onDelTagClicked =
null;
487 onDelTagClicked =
function(
event) {
488 var tagName =
event.target.id;
489 dump(
"removing tag: " + tagName +
"\n");
490 self._service.removeTag(
gMM.sequencer.currentItem, tagName);
491 this.parentNode.parentNode.removeChild(this.parentNode);
492 if (!this.parentNode.parentNode.firstChild) {
493 document.getElementById(
"label-user-tags")
494 .style.visibility =
"collapse";
498 this._domEventListenerSet.add(delTag,
503 delTag.setAttribute(
'class',
'tag-remove');
505 onDelTagClicked =
function(
event) {
506 var tagName =
event.target.id;
507 dump(
"adding tag: " + tagName +
"\n");
508 self.addThisTag(
gMM.sequencer.currentItem, tagName);
510 this._domEventListenerSet.add(delTag,
515 delTag.setAttribute(
'class',
'tag-add');
518 var
label = document.createElement(
'label');
519 label.setAttribute(
'value', tagName);
520 label.setAttribute(
'class',
'tag-link');
522 label.setAttribute(
'href',
'/user/' + LastFm._service.username +
525 label.setAttribute(
'href',
'/tag/' + tagName);
528 var onLabelClicked =
function(
event) {
530 gBrowser.loadOneTab(
"http://www.last.fm"+this.
getAttribute(
'href'));
532 this._domEventListenerSet.add(label,
538 hbox.appendChild(label);
542 LastFm.addTags =
function(
event) {
544 var textbox =
event.target;
545 var tagString = textbox.value;
546 LastFm.addThisTag(
gMM.sequencer.currentItem, tagString,
function() {
551 LastFm.addThisTag =
function(mediaItem, tagString, success, failure) {
553 this._service.addTags(mediaItem, tagString,
function() {
555 var tagBox = document.getElementById(
"user-tags");
556 var tags = tagString.split(
",");
557 for (var
i in tags) {
558 var
tag = tags[
i].replace(/^\s*/,
"").replace(/\s*$/,
"");
559 var hbox = LastFm.showOneMoreTag(tag,
true);
560 tagBox.appendChild(hbox);
561 LastFm._service.userTags[
tag] =
true;
564 if (tagBox.firstChild) {
565 document.getElementById(
"label-user-tags").style.visibility =
"visible";
567 if (typeof(success) ==
"function")
570 alert(LastFm._strings.getString(
'lastfm.tags.add_fail'));
571 if (typeof(failure) ==
"function")
576 LastFm.onUnload =
function() {
578 this._service.listeners.remove(
this);
579 this.
prefs.removeObserver(
"", this.prefObserver,
false);
582 if (this._domEventListenerSet) {
583 this._domEventListenerSet.removeAll();
584 this._domEventListenerSet =
null;
588 Cc[
'@songbirdnest.com/Songbird/Mediacore/Manager;1']
589 .getService(
Ci.sbIMediacoreManager)
590 .removeListener(
this);
593 LastFm.showCurrentTrack =
function(e) {
594 var
gMM =
Cc[
'@songbirdnest.com/Songbird/Mediacore/Manager;1']
595 .getService(
Ci.sbIMediacoreManager);
596 var item = gMM.sequencer.currentItem;
598 item.getProperty(
"http://www.songbirdnest.com/lastfm#artistPage");
600 dump(
"artist page: " + artistPage +
"\n");
602 Components.classes[
'@mozilla.org/appshell/window-mediator;1']
603 .getService(Components.interfaces.nsIWindowMediator)
604 .getMostRecentWindow(
'Songbird:Main');
605 if (mainWin && mainWin.gBrowser)
606 mainWin.gBrowser.loadOneTab(artistPage);
612 LastFm.showPanel =
function LastFm_showPanel() {
613 this._panel.openPopup(this._statusIcon);
618 LastFm._handleUIEvents =
function(aEvent) {
619 switch (aEvent.type) {
620 case "login-button-clicked":
621 this._service.userLoggedOut =
false;
622 this._service.username = this._username.value;
623 this._service.password = this._password.value;
625 this._service.login(
true);
627 case "cancel-button-clicked":
628 this._service.cancelLogin();
629 this._service.userLoggedOut =
true;
631 case "logout-button-clicked":
632 this.onLogoutClick(aEvent);
638 if (this._service.userLoggedOut) {
639 this._newAccountGroupbox.removeAttribute(
'loggedOut');
641 this._newAccountGroupbox.setAttribute(
'loggedOut',
'false');
645 LastFm.onLogoutClick =
function(
event) {
646 this._service.userLoggedOut =
true;
647 this._service.logout();
648 this.setLoginError(
null);
653 LastFm.loadURI =
function(
uri,
event) {
655 this._panel.hidePopup();
658 LastFm.toggleAutoLogin =
function() {
659 this._service.autoLogin = !this._service.autoLogin;
662 LastFm.toggleShouldScrobble =
function() {
663 this._service.shouldScrobble = !this._service.shouldScrobble;
667 LastFm.onLoggedInStateChanged =
function LastFm_onLoggedInStateChanged() {
668 if (this._service.loggedIn) {
672 this._menuEnableScrobbling.parentNode.insertBefore(this._menuLogout,
673 this._menuEnableScrobbling);
675 if (this._menuLogin.parentNode) {
676 this._menuLogin.parentNode.removeChild(this._menuLogin);
679 this._menuEnableScrobbling.disabled =
false;
682 this._deck.selectedPanel = this._profile;
685 document.getElementById(
"lastfmFaceplate").hidden =
false;
688 if (this._service.userLoggedOut) {
690 this._menuLogout.parentNode.removeChild(this._menuLogout);
692 this._menuEnableScrobbling.parentNode.insertBefore(this._menuLogin,
693 this._menuEnableScrobbling);
695 this._menuEnableScrobbling.disabled =
true;
698 document.getElementById(
"lastfmFaceplate").hidden =
true;
702 this._deck.selectedPanel = this._login;
707 LastFm.onLoginBegins =
function LastFm_onLoginBegins() {
708 this._deck.selectedPanel = this._loggingIn;
709 this.setStatusIcon(this.
Icons.busy);
710 this.setStatusTextId(
'lastfm.state.logging_in');
712 LastFm.onLoginCancelled =
function LastFm_onLoginCancelled() {
714 this.setLoginError(
null);
717 LastFm.onLoginFailed =
function LastFm_onLoginFailed() {
719 this.setLoginError(this._strings.getString(
'lastfm.error.login_failed'));
724 LastFm.onLoginSucceeded =
function LastFm_onLoginSucceeded() {
726 this.setLoginError(
null);
730 LastFm.onProfileUpdated =
function LastFm_onProfileUpdated() {
731 var avatar =
'chrome://sb-lastfm/skin/default-avatar.png';
732 if (this._service.avatar) {
733 avatar = this._service.avatar;
735 this._image.setAttributeNS(
'http://www.w3.org/1999/xlink',
'href', avatar);
736 if (this._service.realname &&
this._service.realname.length) {
737 this._realname.textContent = this._service.realname;
739 this._realname.textContent = this._service.username;
741 this._tracks.textContent =
742 this._strings.getFormattedString(
'lastfm.profile.numtracks',
743 [this._service.playcount]);
747 LastFm.onAutoLoginChanged =
function LastFm_onAutoLoginChanged(
val) {
749 this._loginAutoLogin.setAttribute(
'checked',
'true');
750 this._profileAutoLogin.setAttribute(
'checked',
'true');
752 this._loginAutoLogin.removeAttribute(
'checked');
753 this._profileAutoLogin.removeAttribute(
'checked');
758 LastFm.onShouldScrobbleChanged =
function LastFm_onShouldScrobbleChanged(
val) {
760 this._menuEnableScrobbling.setAttribute(
'checked',
'true');
761 this._scrobble.setAttribute(
'checked',
'true');
763 this._menuEnableScrobbling.removeAttribute(
'checked');
764 this._scrobble.removeAttribute(
'checked');
770 LastFm.onUserLoggedOutChanged =
function LastFm_onUserLoggedOutChanged(
val) {
775 LastFm.setStatusIcon =
function LastFm_setStatusIcon(aIcon) {
776 this._statusIcon.setAttribute(
'src', aIcon);
780 LastFm.updateStatus =
function LastFm_updateStatus() {
782 if (this._service.error) {
783 if (this._service.loggedIn) {
786 stateName =
'login_error';
789 if (this._service.loggedIn) {
790 if (this._service.shouldScrobble) {
791 if (
Application.prefs.getValue(
"extensions.lastfm.auth_url",
"")
792 .indexOf(
"libre.fm") >= 0)
794 stateName =
'logged_in_libre'
796 stateName =
'logged_in';
799 if (
Application.prefs.getValue(
"extensions.lastfm.auth_url",
"")
800 .indexOf(
"libre.fm") >= 0)
802 stateName =
'disabled_libre';
804 stateName =
'disabled';
808 stateName =
'logged_out';
811 this.setStatusIcon(this.
Icons[stateName]);
812 this.setStatusTextId(
'lastfm.state.'+stateName.replace(
"_libre",
""));
814 if (stateName ==
'logged_in') {
815 this._faceplate.removeAttribute(
'hidden');
817 this._faceplate.setAttribute(
'hidden',
'true');
822 LastFm.setStatusText =
function LastFm_setStatusText(aText) {
823 this._statusIcon.setAttribute(
'tooltiptext', aText);
827 LastFm.setStatusTextId =
function LastFm_setStatusTextId(aId) {
828 this.setStatusText(this._strings.getString(aId));
832 LastFm.setLoginError =
function LastFm_setLoginError(aText) {
834 this._loginError.textContent = aText;
835 this._loginError.style.visibility =
'visible';
837 this._loginError.textContent =
'';
838 this._loginError.style.visibility =
'collapse';
842 LastFm.onErrorChanged =
function LastFm_onErrorChanged(aError) {
843 this.setLoginError(aError);
849 LastFm.onLoveBan =
function LastFm_onLoveBan(aItem, love) {
850 if (this._service.loveTrack) {
852 this._faceplate.setAttribute(
'loveban', this._service.love?
'love':
'ban');
854 this._faceplate.removeAttribute(
'loveban');
858 LastFm.onAuthorisationSuccess =
function LastFm_onAuthorisationSuccess() { }
860 LastFm.prefObserver = {
862 if (subject instanceof Components.interfaces.nsIPrefBranch &&
863 data ==
"show_radio_node")
866 Cc[
'@songbirdnest.com/servicepane/service;1']
867 .getService(
Ci.sbIServicePaneService)
868 .getNodeForURL(
"chrome://sb-lastfm/content/tuner2.xhtml");
870 if (lastFmNode !=
null) {
872 "extensions.lastfm.show_radio_node",
true);
875 var radioNode = lastFmNode.parentNode;
876 var
enum = radioNode.childNodes;
877 var visibleFlag =
false;
881 var
node =
enum.getNext();
888 radioNode.hidden = !visibleFlag;
894 window.addEventListener(
"load",
function(e) { LastFm.onLoad(e); },
false);
895 window.addEventListener(
"unload",
function(e) { LastFm.onUnload(e); },
false);
function DOMEventListenerSet()
this _contentSandbox label
this _dialogInput val(dateText)
SimpleArrayEnumerator prototype hasMoreElements
return aWindow document documentElement getAttribute(aAttribute)||dimension
dataSBGenres SBProperties tag
_getSelectedPageStyle s i
sbDeviceFirmwareAutoCheckForUpdate prototype observe