home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog 112
/
FreelogNo112-NovembreDecembre2012.iso
/
Multimedia
/
Songbird
/
Songbird_2.0.0-2311_windows-i686-msvc8.exe
/
components
/
sbGlobalHotkeys.js
< prev
next >
Wrap
Text File
|
2012-06-08
|
23KB
|
749 lines
/*
*=BEGIN SONGBIRD GPL
*
* This file is part of the Songbird web player.
*
* Copyright(c) 2005-2009 POTI, Inc.
* http://www.songbirdnest.com
*
* This file may be licensed under the terms of of the
* GNU General Public License Version 2 (the ``GPL'').
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the GPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the GPL along with this
* program. If not, go to http://www.gnu.org/licenses/gpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*=END SONGBIRD GPL
*/
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
const SB_HOTKEY_SERVICE_CLASSNAME = "sbHotkeyService"
const SB_HOTKEY_SERVICE_DESC = "Songbird Global Hotkey Service";
const SB_HOTKEY_SERVICE_CONTRACTID = "@songbirdnest.com/Songbird/HotkeyService;1";
const SB_HOTKEY_SERVICE_CID = "{8264dc94-1dd2-11b2-ab4a-8b3dfb1072fb}";
const SB_DEFGLOBALHKACTIONS_CLASSNAME = "sbDefaultGlobalHotkeyActions";
const SB_DEFGLOBALHKACTIONS_DESC = "Songbird Default Global Hotkey Actions";
const SB_DEFGLOBALHKACTIONS_CONTRACTID = "@songbirdnest.com/Songbird/DefaultGlobalHotkeyActions;1";
const SB_DEFGLOBALHKACTIONS_CID = "{76512c09-7f02-48f5-86c0-c3a8670ead3f}";
const SB_HOTKEY_CONFIGURATION_CLASSNAME = "sbHotkeyConfiguration";
const SB_HOTKEY_CONFIGURATION_DESC = "Songbird Hotkey Configuration";
const SB_HOTKEY_CONFIGURATION_CONTRACTID = "@songbirdnest.com/Songbird/HotkeyConfiguration;1";
const SB_HOTKEY_CONFIGURATION_CID = "{5c6b204c-1dd2-11b2-8005-83725e03a0d0}";
const SB_HOTKEYMANAGER_CONTRACTID = "@songbirdnest.com/Songbird/GlobalHotkeys;1";
const SB_HOTKEYACTIONS_CONTRACTID = "@songbirdnest.com/Songbird/HotkeyActions;1";
const SB_COMMANDLINE_CONTRACTID = "@songbirdnest.com/commandlinehandler/general-startup;1?type=songbird";
const STARTUP_TOPIC = "final-ui-startup";
const SHUTDOWN_TOPIC = "quit-application";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://app/jsmodules/SBDataRemoteUtils.jsm");
Cu.import("resource://app/jsmodules/SBTimer.jsm");
/**
* Global getter for the Global Hotkey Manager
*/
__defineGetter__("HotkeyManager", function() {
delete HotkeyManager;
if (SB_HOTKEYMANAGER_CONTRACTID in Cc) {
HotkeyManager = Cc[SB_HOTKEYMANAGER_CONTRACTID]
.getService(Ci.sbIGlobalHotkeys);
} else {
HotkeyManager = null;
}
return HotkeyManager;
});
/**
* Global getter for Global Hotkey Actions Service
*/
__defineGetter__("HotkeyActions", function() {
delete HotkeyActions;
if (SB_HOTKEYACTIONS_CONTRACTID in Cc) {
HotkeyActions = Cc[SB_HOTKEYACTIONS_CONTRACTID]
.getService(Ci.sbIHotkeyActions);
} else {
HotkeyActions = null;
}
return HotkeyActions;
});
/**
* Global getter for the Command Line Service
*/
__defineGetter__("CommandLine", function() {
delete CommandLine;
if (SB_COMMANDLINE_CONTRACTID in Cc) {
CommandLine = Cc[SB_COMMANDLINE_CONTRACTID]
.getService(Ci.nsICommandLineHandler)
.QueryInterface(Ci.sbICommandLineManager);
} else {
CommandLine = null;
}
return CommandLine;
});
/**
* Global getter for Observer Service
*/
__defineGetter__("ObserverService", function() {
delete ObserverService;
ObserverService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
return ObserverService;
});
function sbHotkeyService() {
ObserverService.addObserver(this, STARTUP_TOPIC, false);
}
sbHotkeyService.prototype =
{
_dataRemoteHotkeysChanged: null,
_dataRemoteHotkeysEnabled: null,
_dataRemoteObserver: null,
_platform: null,
_metaKeyString: null,
_hotkeyHandler: null,
///////////////////////////////////////////////////////////////////
// nsIObserver
///////////////////////////////////////////////////////////////////
observe: function(aSubject, aTopic, aData) {
switch(aTopic) {
case STARTUP_TOPIC: {
ObserverService.removeObserver(this, STARTUP_TOPIC);
this._init();
}
break;
case SHUTDOWN_TOPIC: {
ObserverService.removeObserver(this, SHUTDOWN_TOPIC);
this._shutdown();
}
break;
}
},
///////////////////////////////////////////////////////////////////
// sbIHotkeyService
///////////////////////////////////////////////////////////////////
getHotkeys: function() {
var count = SBDataGetIntValue("globalhotkeys.count");
var hotkeyConfigList = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
.createInstance(Ci.nsIMutableArray);
for (var i = 0; i < count; i++) {
var hotkeyConfig = Cc[SB_HOTKEY_CONFIGURATION_CONTRACTID]
.createInstance(Ci.sbIHotkeyConfiguration);
var keyBase = "globalhotkey." + i + ".";
hotkeyConfig.key = SBDataGetStringValue(keyBase + "key");
hotkeyConfig.keyReadable = SBDataGetStringValue(keyBase + "key.readable");
hotkeyConfig.action = SBDataGetStringValue(keyBase + "action");
if (!this._configListContainsKey(hotkeyConfigList, hotkeyConfig.key))
hotkeyConfigList.appendElement(hotkeyConfig, false);
}
return hotkeyConfigList;
},
getHotkey: function(aKey) {
var hotkeyConfigList = this.getHotkeys();
for (var i = 0; i < hotkeyConfigList.length; i++) {
var hotkeyConfig =
hotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
if (hotkeyConfig.key == aKey)
return hotkeyConfig;
}
return null;
},
setHotkeys: function(aHotkeyConfigList) {
SBDataDeleteBranch("globalhotkey");
for (var i = 0; i < aHotkeyConfigList.length; i++) {
var hotkeyConfig =
aHotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
var keyBase = "globalhotkey." + i + ".";
SBDataSetStringValue(keyBase + "key", hotkeyConfig.key);
SBDataSetStringValue(keyBase + "key.readable", hotkeyConfig.keyReadable);
SBDataSetStringValue(keyBase + "action", hotkeyConfig.action);
}
SBDataSetIntValue("globalhotkeys.count", aHotkeyConfigList.length);
this._loadHotkeysFromPrefs();
},
addHotkey: function(aHotkeyConfig) {
var hotkeyConfigList = this.getHotkeys();
this._removeHotkeyFromConfigList(hotkeyConfigList, aHotkeyConfig.key);
hotkeyConfigList.appendElement(aHotkeyConfig, false);
this.setHotkeys(hotkeyConfigList);
},
removeHotkeyByKey: function(aKey) {
var hotkeyConfigList = this.getHotkeys();
this._removeHotkeyFromConfigList(hotkeyConfigList, aKey);
this.setHotkeys(hotkeyConfigList);
},
removeHotkeysByAction: function(aAction) {
var hotkeyConfigList = this.getHotkeys();
for (var i = hotkeyConfigList.length - 1; i >= 0; i--) {
var hotkeyConfig =
hotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
if (hotkeyConfig.action == aAction)
hotkeyConfigList.removeElementAt(i);
}
this.setHotkeys(hotkeyConfigList);
},
get hotkeysEnabled() {
return SBDataGetBoolValue("globalhotkeys.enabled");
},
set hotkeysEnabled(aEnabled) {
SBDataSetBoolValue("globalhotkeys.enabled", aEnabled);
this._loadHotkeysFromPrefs();
},
get hotkeysEnabledDRKey() {
return "globalhotkeys.enabled";
},
///////////////////////////////////////////////////////////////////
// Internal Methods
///////////////////////////////////////////////////////////////////
_init: function() {
if(!HotkeyManager) {
Cu.reportError("Global Hotkey Manager is not available.");
return;
}
this._initPlatform();
this._initMetaKeyString();
this._initHotkeyHandler();
this._loadDefaultHotkeys();
this._loadHotkeysFromPrefs();
if(!HotkeyActions) {
Cu.reportError("Global Hotkey Actions Service is not available.");
return;
}
// Register the default set of actions.
var defaultActions = Cc[SB_DEFGLOBALHKACTIONS_CONTRACTID]
.createInstance(Ci.sbIHotkeyActionBundle);
HotkeyActions.registerHotkeyActionBundle(defaultActions);
// Register observer for application shutdown to clean up.
ObserverService.addObserver(this, SHUTDOWN_TOPIC, false);
// Indicate that the service is ready.
var serviceManager = Cc["@songbirdnest.com/Songbird/ServiceManager;1"]
.getService(Ci.sbIServiceManager);
serviceManager.setServiceReady(SB_HOTKEY_SERVICE_CONTRACTID, true);
},
_shutdown: function() {
// Indicate that the service is no longer ready.
var serviceManager = Cc["@songbirdnest.com/Songbird/ServiceManager;1"]
.getService(Ci.sbIServiceManager);
serviceManager.setServiceReady(SB_HOTKEY_SERVICE_CONTRACTID, false);
if (CommandLine) {
CommandLine.removeFlagHandler(this._hotkeyHandler, "hotkey");
}
this._hotkeyHandler = null;
if (HotkeyManager) {
HotkeyManager.removeAllHotkeys();
}
},
_initPlatform: function() {
try {
var sysInfo =
Components.classes["@mozilla.org/system-info;1"]
.getService(Components.interfaces.nsIPropertyBag2);
this._platform = sysInfo.getProperty("name");
}
catch (e) {
Cu.reportError(e);
var user_agent = navigator.userAgent;
if (user_agent.indexOf("Windows") != -1)
this._platform = "Windows_NT";
else if (user_agent.indexOf("Mac OS X") != -1)
this._platform = "Darwin";
else if (user_agent.indexOf("Linux") != -1)
this._platform = "Linux";
else if (user_agent.indexOf("SunOS") != -1)
this._platform = "SunOS";
}
},
_initMetaKeyString: function() {
switch(this._platform) {
case "Windows_NT": this._metaKeyString = "win"; break;
case "Darwin": this._metaKeyString = "command"; break;
case "Linux": this._metaKeyString = "meta"; break;
default: this._metaKeyString = "meta";
}
},
_initHotkeyHandler: function() {
if (!CommandLine) {
Cu.reportError("Command Line Handler is not available.");
return;
}
if (!this._hotkeyHandler) {
/**
* The default hotkey handler
*/
this._hotkeyHandler = {
onHotkey: function (aHotkeyId) {
aHotkeyId = aHotkeyId.toLowerCase();
// look through the action bundles to find the right action to trigger
for (var i = 0;i < HotkeyActions.bundleCount; i++)
{
var bundle = HotkeyActions.enumBundle(i);
for (var j=0;j<bundle.actionCount;j++)
{
var id = bundle.enumActionID(j);
if (id.toLowerCase() == aHotkeyId) {
bundle.onAction(j);
return;
}
}
}
},
handleFlag: function(aFlag, aParam)
{
var ids = aParam.split(",");
for (var i = 0; i < ids.length; i++) {
this.onHotkey(ids[i]);
}
return true;
},
QueryInterface : XPCOMUtils.generateQI([Ci.sbIGlobalHotkeyCallback,
Ci.sbICommandLineFlagHandler,
Ci.nsISupportsWeakReference])
};
}
CommandLine.addFlagHandler(this._hotkeyHandler, "hotkey");
},
/**
* \brief Load the hotkeys saved in the users prefs
*/
_loadHotkeysFromPrefs: function() {
this._removeHotkeyBindings();
var enabled = SBDataGetBoolValue("globalhotkeys.enabled");
if (!enabled) {
return;
}
var count = SBDataGetIntValue("globalhotkeys.count");
for (var i = 0;i < count; i++) {
// Read hotkey binding from user preferences
let root = "globalhotkey." + i + ".";
let keycombo = SBDataGetStringValue(root + "key");
let action = SBDataGetStringValue(root + "action");
// Split key combination string
let keys = keycombo.split("-");
// Parse its components
let alt = false;
let ctrl = false;
let shift = false;
let meta = false;
let keyCode = 0;
for (var j = 0; j < keys.length; j++) {
keys[j] = keys[j].toLowerCase();
switch (keys[j]) {
case "alt": alt = true; break;
case "shift": shift = true; break;
case "ctrl": ctrl = true; break;
case "meta": meta = true; break;
default: keyCode = this._stringToKeyCode(keys[j]);
}
}
// If we had a key code (and possibly modifiers), register the corresponding action for it
if (keyCode != 0) {
HotkeyManager.addHotkey(keyCode,
alt,
ctrl,
shift,
meta,
action,
this._hotkeyHandler);
}
}
},
/**
* \brief Load the default set of hotkeys
*/
_loadDefaultHotkeys: function() {
// Global Hotkeys have already changed, don't load the default set.
if (SBDataGetBoolValue("globalhotkeys.changed")) {
return;
}
// Indicate that the global hotkeys have changed and are enabled
SBDataSetBoolValue("globalhotkeys.changed", true);
SBDataSetBoolValue("globalhotkeys.enabled", true);
// Hot key list
var metaKey = this._metaKeyString;
var hotkeyConfigList =
[
// Media keys
{ key: "$176",
keyReadable: "nexttrack",
action: "playback.nexttrack" },
{ key: "$177",
keyReadable: "prevtrack",
action: "playback.previoustrack" },
{ key: "$179",
keyReadable: "playpause",
action: "playback.playpause" },
// Regular keys
{ key: "meta-$190",
keyReadable: metaKey + " - .",
action: "playback.volumeup" },
{ key: "meta-$188",
keyReadable: metaKey + " - ,",
action: "playback.volumedown" },
{ key: "meta-$221",
keyReadable: metaKey + " - ]",
action: "playback.nexttrack" },
{ key: "meta-$219",
keyReadable: metaKey + " - [",
action: "playback.previoustrack" },
{ key: "meta-$220",
keyReadable: metaKey + " - \\",
action: "playback.playpause" },
{ key: "$178",
keyReadable: "stop",
action: "playback.stop" }
];
// Build an array of hot key configurations
var hotkeyConfigArray = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
.createInstance(Ci.nsIMutableArray);
for (var i = 0; i < hotkeyConfigList.length; i++) {
var hotkeyConfiguration = Cc[SB_HOTKEY_CONFIGURATION_CONTRACTID]
.createInstance(Ci.sbIHotkeyConfiguration);
hotkeyConfiguration.key = hotkeyConfigList[i].key;
hotkeyConfiguration.keyReadable = hotkeyConfigList[i].keyReadable;
hotkeyConfiguration.action = hotkeyConfigList[i].action;
hotkeyConfigArray.appendElement(hotkeyConfiguration, false);
}
// Set the default hot keys
this.setHotkeys(hotkeyConfigArray);
},
/**
* \brief Remove all hotkeys currently bound
*/
_removeHotkeyBindings: function() {
if (HotkeyManager) {
HotkeyManager.removeAllHotkeys();
}
},
_stringToKeyCode: function(aStr) {
if (aStr.slice(0, 1) == '$') {
return aStr.slice(1);
}
return 0;
},
_configListContainsKey: function(aHotkeyConfigList, aKey) {
for (var i = 0; i < aHotkeyConfigList.length; i++) {
var hotkeyConfig =
aHotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
if (hotkeyConfig.key == aKey)
return true;
}
return false;
},
_removeHotkeyFromConfigList: function(aHotkeyConfigList, aKey) {
for (var i = aHotkeyConfigList.length - 1; i >= 0; i--) {
var hotkeyConfig =
aHotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
if (hotkeyConfig.key == aKey)
aHotkeyConfigList.removeElementAt(i);
}
},
className: SB_HOTKEY_SERVICE_CLASSNAME,
classDescription: SB_HOTKEY_SERVICE_DESC,
classID: Components.ID(SB_HOTKEY_SERVICE_CID),
contractID: SB_HOTKEY_SERVICE_CONTRACTID,
_xpcom_categories: [
{
category: "app-startup",
entry: SB_HOTKEY_SERVICE_DESC,
value: "service," + SB_HOTKEY_SERVICE_CONTRACTID
}
],
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.sbIHotkeyService])
};
function sbDefaultGlobalHotkeyActions() {
}
sbDefaultGlobalHotkeyActions.prototype =
{
/**
* You should change these to match your own actions, strings, and
* stringbundle (ie, you will need to ship your own translations with
* your extension since the description string you use will probably
* not be in the standard songbird string bundle)
*/
_packagename: "playback",
_actions: [ "volumeup",
"volumedown",
"nexttrack",
"previoustrack",
"playpause",
"pause",
"stop" ],
/**
* The string bundle to use to get the localized strings
* (ie, hotkeys.actions.playback, hotkeys.actions.playback.volumeup,
* hotkeys.actions.playback.volumedown, etc).
*/
_stringbundle: "chrome://songbird/locale/songbird.properties",
/**
* Internal data
*/
_localpackagename: null,
_sbs: null,
_songbirdStrings: null,
/**
* This enumerates the actions, their localized display strings,
* and their internal ids, so that the hotkey action manager may list them
* in the hotkeys preference pane.
*/
get actionCount() {
return this._actions.length;
},
enumActionLocaleDescription: function (aIndex) {
return this._getLocalizedPackageName() +
": " +
this._getLocalizedActionName(this._actions[aIndex]);
},
enumActionID: function(aIndex) {
return this._packagename + "." + this._actions[aIndex];
},
/**
* This is called when an action has been triggered
*/
onAction: function(aIndex) {
switch (aIndex) {
case 0: this._hotkey_volumeUp(); break;
case 1: this._hotkey_volumeDown(); break;
case 2: this._hotkey_nextTrack(); break;
case 3: this._hotkey_previousTrack(); break;
case 4: this._hotkey_playPause(); break;
case 5: this._hotkey_pause(); break;
case 6: this._hotkey_stop(); break;
}
},
get _mm() {
return Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
.getService(Ci.sbIMediacoreManager);
},
_hotkey_volumeUp: function() {
var volume = this._mm.volumeControl.volume + 0.03;
if (volume > 1) volume = 1;
this._mm.volumeControl.volume = volume;
},
_hotkey_volumeDown: function() {
var volume = this._mm.volumeControl.volume - 0.03;
if (volume < 0) volume = 0;
this._mm.volumeControl.volume = volume;
},
_hotkey_nextTrack: function() {
this._mm.sequencer.next();
},
_hotkey_previousTrack: function() {
this._mm.sequencer.previous();
},
_hotkey_playPause: function() {
try {
// If we are already playing something just pause/unpause playback
if (this._mm.status.state == Ci.sbIMediacoreStatus.STATUS_PLAYING ||
this._mm.status.state == Ci.sbIMediacoreStatus.STATUS_BUFFERING) {
this._mm.playbackControl.pause();
}
else if(this._mm.status.state == Ci.sbIMediacoreStatus.STATUS_PAUSED) {
this._mm.playbackControl.play();
}
// Otherwise just have the root application controller figure it out
else {
// If we have no context, initiate playback
// via the root application controller
var app = Cc["@songbirdnest.com/Songbird/ApplicationController;1"]
.getService(Ci.sbIApplicationController);
app.playDefault();
}
} catch (e) {
Cu.reportError(e);
}
},
_hotkey_pause: function() {
this._mm.playbackControl.pause();
},
_hotkey_stop: function() {
this._mm.playbackControl.stop();
},
_getLocalizedString: function(str, defaultstr) {
var r = defaultstr;
if (!this._sbs) {
this._sbs = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
this._songbirdStrings = this._sbs.createBundle(this._stringbundle);
}
try {
r = this._songbirdStrings.GetStringFromName(str);
} catch (e) { /* we have a default */ }
return r;
},
/**
* The local package name is taken from the specified string bundle,
* using the key "hotkeys.actions.package", where package is
* the internal name of the package, as specified in this._packagename.
*/
_getLocalizedPackageName: function() {
if (!this._localpackage)
this._localpackage = this._getLocalizedString("hotkeys.actions." +
this._packagename,
this._packagename);
return this._localpackage;
},
/**
* the local action name is taken from the specified string bundle, using
* the key "hotkeys.actions.package.action", where package
* is the internal name of the package, as specified in this._packagename,
* and action is the internal name of the action, as specified in the
* this._actions array.
*/
_getLocalizedActionName: function(action) {
return this._getLocalizedString("hotkeys.actions." +
this._packagename +
"." +
action,
action);
},
className: SB_DEFGLOBALHKACTIONS_CLASSNAME,
classDescription: SB_DEFGLOBALHKACTIONS_DESC,
classID: Components.ID(SB_DEFGLOBALHKACTIONS_CID),
contractID: SB_DEFGLOBALHKACTIONS_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.sbIHotkeyActionBundle,
Ci.nsISupportsWeakReference,
Ci.nsISupports])
};
function sbHotkeyConfiguration() {
}
sbHotkeyConfiguration.prototype =
{
key: null,
keyReadable: null,
action: null,
className: SB_HOTKEY_CONFIGURATION_CLASSNAME,
classDescription: SB_HOTKEY_CONFIGURATION_DESC,
classID: Components.ID(SB_HOTKEY_CONFIGURATION_CID),
contractID: SB_HOTKEY_CONFIGURATION_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.sbIHotkeyConfiguration])
};
//------------------------------------------------------------------------------
// XPCOM Registration
function NSGetModule(compMgr, fileSpec)
{
return XPCOMUtils.generateModule([sbHotkeyService,
sbDefaultGlobalHotkeyActions,
sbHotkeyConfiguration]);
}