mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-01-05 11:14:11 +01:00
Basic Songbird 1.9a support.
--HG-- rename : xulmus/AUTHORS => melodactyl/AUTHORS rename : xulmus/Makefile => melodactyl/Makefile rename : xulmus/NEWS => melodactyl/NEWS rename : xulmus/TODO => melodactyl/TODO rename : xulmus/chrome.manifest => melodactyl/chrome.manifest rename : xulmus/components/commandline-handler.js => melodactyl/components/commandline-handler.js rename : xulmus/components/protocols.js => melodactyl/components/protocols.js rename : xulmus/content/config.js => melodactyl/content/config.js rename : xulmus/content/dactyl.dtd => melodactyl/content/dactyl.dtd rename : xulmus/content/library.js => melodactyl/content/library.js rename : xulmus/content/logo.png => melodactyl/content/logo.png rename : xulmus/content/xulmus.xul => melodactyl/content/melodactyl.xul rename : xulmus/content/player.js => melodactyl/content/player.js rename : xulmus/content/xulmus.svg => melodactyl/content/xulmus.svg rename : xulmus/contrib/vim/Makefile => melodactyl/contrib/vim/Makefile rename : xulmus/contrib/vim/ftdetect/xulmus.vim => melodactyl/contrib/vim/ftdetect/melodactyl.vim rename : xulmus/contrib/vim/mkvimball.txt => melodactyl/contrib/vim/mkvimball.txt rename : xulmus/contrib/vim/syntax/xulmus.vim => melodactyl/contrib/vim/syntax/melodactyl.vim rename : xulmus/defaults/preferences/dactyl.js => melodactyl/defaults/preferences/dactyl.js rename : xulmus/install.rdf => melodactyl/install.rdf rename : xulmus/locale/en-US/all.xml => melodactyl/locale/en-US/all.xml rename : xulmus/locale/en-US/autocommands.xml => melodactyl/locale/en-US/autocommands.xml rename : xulmus/locale/en-US/browsing.xml => melodactyl/locale/en-US/browsing.xml rename : xulmus/locale/en-US/dactyl.dtd => melodactyl/locale/en-US/dactyl.dtd rename : xulmus/locale/en-US/gui.xml => melodactyl/locale/en-US/gui.xml rename : xulmus/locale/en-US/intro.xml => melodactyl/locale/en-US/intro.xml rename : xulmus/locale/en-US/player.xml => melodactyl/locale/en-US/player.xml rename : xulmus/locale/en-US/tabs.xml => melodactyl/locale/en-US/tabs.xml rename : xulmus/skin/icon.png => melodactyl/skin/icon.png
This commit is contained in:
6
melodactyl/AUTHORS
Normal file
6
melodactyl/AUTHORS
Normal file
@@ -0,0 +1,6 @@
|
||||
Main developer/Project founder:
|
||||
* Prathyush Thota <prathyushthota@gmail.com>
|
||||
|
||||
Developers:
|
||||
* Martin Stubenschrott (stubenschrott@vimperator.org)
|
||||
* Doug Kearns (dougkearns@gmail.com)
|
||||
11
melodactyl/Makefile
Normal file
11
melodactyl/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
#### configuration
|
||||
|
||||
NAME = melodactyl
|
||||
|
||||
FIREFOX ?= songbird
|
||||
HOSTAPP ?= $(SONGBIRD)
|
||||
PROFILEPATHS ?= "$$HOME/.songbird" \
|
||||
"$$HOME/Library/Songbird" \
|
||||
"$$APPDATA/Songbird"
|
||||
|
||||
include ../common/Makefile
|
||||
22
melodactyl/NEWS
Executable file
22
melodactyl/NEWS
Executable file
@@ -0,0 +1,22 @@
|
||||
2009-XX-XX:
|
||||
* version 0.2pre
|
||||
* asciidoc is no longer required to build Xulmus
|
||||
* The help system is newly modularized
|
||||
* add [c]:silent[c]
|
||||
* add [j]$MY_XULMUSRC[j]
|
||||
* add [m]'[m] and [m]"[m] local marks
|
||||
* add [m]w[m] and [m]W[m] Normal mode mappings for symmetry with [m]o[m]/[m]O[m] and [m]t[m]/[m]T[m]
|
||||
* add [c]:messclear[c]
|
||||
* add 'maxitems'
|
||||
* [c]:dialog {subscribe|newsmartplaylist}[c]
|
||||
* add [c]:displaypane[c] and [c]:dpclose[c]
|
||||
* rename [c]:filter[c] to [c]:queue[c] and [c]:Filter[c] to [c]:filter[c]
|
||||
* add 'repeat' and 'shuffle'
|
||||
* add 'jsdebugger' option - switch on/off javascript debugger service
|
||||
* add "addons", "downloads", "extoptions" and "help" to the 'activate' option.
|
||||
|
||||
2009-03-28:
|
||||
* version 0.1
|
||||
* first public release
|
||||
|
||||
// vim: set filetype=asciidoc:
|
||||
24
melodactyl/TODO
Normal file
24
melodactyl/TODO
Normal file
@@ -0,0 +1,24 @@
|
||||
Priority list:
|
||||
1-9 as in Vim (9 = required for next release, 5 = would be nice, 1 = probably not)
|
||||
|
||||
BUGS:
|
||||
- broken commands:
|
||||
- :tabduplicate
|
||||
- :open songbird-internal-search searchString (broken because SB intercepts queries to this engine)
|
||||
- <C-^> only works between browser tabs not the media tab
|
||||
- numbered tabs
|
||||
- command-line option handling is broken in Xulmus only - it used to work.
|
||||
|
||||
FEATURES:
|
||||
9 '?' - Reusing '/'.
|
||||
8 Merge with SongBird's sanitizer implementation.
|
||||
8 Playlist/SmartPlaylist operations & meta-data operations.
|
||||
8 Sort-View commands.
|
||||
7 Queue view.
|
||||
7 j/k - for browsing through the visible view.
|
||||
7 extended hint mode for opening links in FF.
|
||||
6 :tqueue, :lqueue etc.
|
||||
5 make Player mode commands work in the Mini-Player.
|
||||
5 Check for default extensions and add commands for them. Ex. Last.fm, Seeqpod e.t.c
|
||||
Wouldn't these be provided as Xulmus plugins like Pentadactyl does? --djk
|
||||
5 tagging tracks for manipulation by commands
|
||||
37
melodactyl/chrome.manifest
Normal file
37
melodactyl/chrome.manifest
Normal file
@@ -0,0 +1,37 @@
|
||||
# Songbird
|
||||
content melodactyl content/
|
||||
skin melodactyl classic/1.0 skin/
|
||||
locale melodactyl en-US locale/en-US/
|
||||
locale dactyl en-US ../common/locale/en-US/
|
||||
|
||||
content dactyl ../common/content/
|
||||
resource dactyl ../common/modules/
|
||||
skin dactyl classic/1.0 ../common/skin/
|
||||
|
||||
override chrome://dactyl/content/dactyl.dtd chrome://melodactyl/content/dactyl.dtd
|
||||
override chrome://dactyl/content/config.js chrome://melodactyl/content/config.js
|
||||
|
||||
overlay chrome://songbird/content/xul/layoutBaseOverlay.xul chrome://melodactyl/content/melodactyl.xul
|
||||
overlay chrome://songbird/content/xul/layoutBaseOverlay.xul chrome://dactyl/content/dactyl.xul
|
||||
|
||||
#component {16dc34f7-6d22-4aa4-a67f-2921fb5dcb69} components/commandline-handler.js
|
||||
#contract @mozilla.org/commandlinehandler/general-startup;1?type=melodactyl {16dc34f7-6d22-4aa4-a67f-2921fb5dcb69}
|
||||
#category command-line-handler m-melodactyl @mozilla.org/commandlinehandler/general-startup;1?type=melodactyl
|
||||
#
|
||||
#component {c1b67a07-18f7-4e13-b361-2edcc35a5a0d} components/protocols.js
|
||||
#contract @mozilla.org/network/protocol;1?name=chrome-data {c1b67a07-18f7-4e13-b361-2edcc35a5a0d}
|
||||
#component {9c8f2530-51c8-4d41-b356-319e0b155c44} components/protocols.js
|
||||
#contract @mozilla.org/network/protocol;1?name=dactyl {9c8f2530-51c8-4d41-b356-319e0b155c44}
|
||||
#component {f4506a17-5b4d-4cd9-92d4-2eb4630dc388} components/protocols.js
|
||||
#contract @dactyl.googlecode.com/base/xpc-interface-shim {f4506a17-5b4d-4cd9-92d4-2eb4630dc388}
|
||||
#component {81495d80-89ee-4c36-a88d-ea7c4e5ac63f} components/protocols.js
|
||||
#contract @mozilla.org/network/protocol/about;1?what=melodactyl {81495d80-89ee-4c36-a88d-ea7c4e5ac63f}
|
||||
|
||||
#overlay chrome://songbird/content/xul/layoutWithBrowserOverlay.xul chrome://xulmus/content/xulmus.xul
|
||||
#overlay chrome://songbird/content/xul/layoutWithBrowserOverlay.xul chrome://dactyl/content/dactyl.xul
|
||||
|
||||
#overlay chrome://songbird/content/xul/layoutWithoutBrowserOverlay.xul chrome://xulmus/content/xulmus.xul
|
||||
#overlay chrome://songbird/content/xul/layoutWithoutBrowserOverlay.xul chrome://dactyl/content/dactyl.xul
|
||||
|
||||
#overlay windowtype:Songbird:Main chrome://dactyl/content/dactyl.xul
|
||||
#overlay windowtype:Songbird:Main chrome://xulmus/content/xulmus.xul
|
||||
1
melodactyl/components/commandline-handler.js
Symbolic link
1
melodactyl/components/commandline-handler.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../common/components/commandline-handler.js
|
||||
1
melodactyl/components/protocols.js
Symbolic link
1
melodactyl/components/protocols.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../common/components/protocols.js
|
||||
308
melodactyl/content/config.js
Normal file
308
melodactyl/content/config.js
Normal file
@@ -0,0 +1,308 @@
|
||||
// Copyright (c) 2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
|
||||
// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
|
||||
// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
|
||||
//
|
||||
// This work is licensed for reuse under an MIT license. Details are
|
||||
// given in the LICENSE.txt file included with this file.
|
||||
|
||||
|
||||
Components.utils.import("resource://gre/modules/utils.js"); // XXX
|
||||
|
||||
const Config = Module("config", ConfigBase, {
|
||||
init: function init() {
|
||||
init.supercall(this);
|
||||
|
||||
// TODO: mention this to SB devs, they seem keen to provide these
|
||||
// functions to make porting from FF as simple as possible.
|
||||
window.toJavaScriptConsole = function () {
|
||||
toOpenWindowByType("global:console", "chrome://global/content/console.xul");
|
||||
};
|
||||
|
||||
window.BrowserStop = function () {
|
||||
SBGetBrowser().mCurrentBrowser.stop();
|
||||
};
|
||||
},
|
||||
/*** required options, no checks done if they really exist, so be careful ***/
|
||||
name: "Xulmus",
|
||||
host: "Songbird",
|
||||
|
||||
/*** optional options, there are checked for existence and a fallback provided ***/
|
||||
features: ["bookmarks", "hints", "marks", "history", "quickmarks", "session", "tabs", "player"],
|
||||
defaults: {
|
||||
guioptions: "mprb",
|
||||
showtabline: 2,
|
||||
titlestring: "Xulmus"
|
||||
},
|
||||
|
||||
guioptions: {
|
||||
m: ["Menubar", ["main-menubar"]],
|
||||
T: ["Toolbar", ["nav-bar"]],
|
||||
p: ["Player controls", ["player_wrapper"]]
|
||||
},
|
||||
|
||||
get isPlayerWindow() SBGetBrowser().mCurrentTab == SBGetBrowser().mediaTab,
|
||||
// focusContent() focuses this widget gSongbirdWindowController takes care of the focus.
|
||||
get visualbellWindow() document.getElementById(this.mainWindowId),
|
||||
|
||||
styleableChrome: ["chrome://purplerain/content/xul/mainplayer.xul"],
|
||||
|
||||
autocommands: {
|
||||
BookmarkAdd: "Triggered after a page is bookmarked",
|
||||
ColorScheme: "Triggered after a color scheme has been loaded",
|
||||
DOMLoad: "Triggered when a page's DOM content has fully loaded",
|
||||
DownloadPost: "Triggered when a download has completed",
|
||||
Fullscreen: "Triggered when the browser's fullscreen state changes",
|
||||
LocationChange: "Triggered when changing tabs or when navigation to a new location",
|
||||
PageLoadPre: "Triggered after a page load is initiated",
|
||||
PageLoad: "Triggered when a page gets (re)loaded/opened",
|
||||
ShellCmdPost: "Triggered after executing a shell command with :!cmd",
|
||||
TrackChangePre: "Triggered before a playing track is changed",
|
||||
TrackChange: "Triggered after a playing track has changed",
|
||||
ViewChangePre: "Triggered before a sequencer view is changed",
|
||||
ViewChange: "Triggered after a sequencer view is changed",
|
||||
StreamStart: "Triggered after a stream has started",
|
||||
StreamPause: "Triggered after a stream has paused",
|
||||
StreamEnd: "Triggered after a stream has ended",
|
||||
StreamStop: "Triggered after a stream has stopped",
|
||||
Enter: "Triggered after Songbird starts",
|
||||
LeavePre: "Triggered before exiting Songbird, just before destroying each module",
|
||||
Leave: "Triggered before exiting Songbird",
|
||||
},
|
||||
|
||||
// TODO: remove those which don't make sense, can't be provided.
|
||||
dialogs: {
|
||||
about: ["About Songbird",
|
||||
function () { window.openDialog("chrome://songbird/content/xul/about.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
||||
addons: ["Manage Add-ons",
|
||||
function () { SBOpenPreferences("paneAddons"); }],
|
||||
checkupdates: ["Check for updates",
|
||||
function () { window.checkForUpdates(); }],
|
||||
cleardata: ["Clear private data",
|
||||
function () { Sanitizer.showUI(); }],
|
||||
cookies: ["List your cookies",
|
||||
function () { window.toOpenWindowByType("Browser:Cookies", "chrome://browser/content/preferences/cookies.xul", "chrome,dialog=no,resizable"); }],
|
||||
console: ["JavaScript console",
|
||||
function () { window.toJavaScriptConsole(); }],
|
||||
dominspector: ["DOM Inspector",
|
||||
function () { try { window.inspectDOMDocument(content.document); } catch (e) { dactyl.echoerr("DOM Inspector extension not installed"); } }],
|
||||
downloads: ["Manage Downloads",
|
||||
function () { window.toOpenWindowByType("Download:Manager", "chrome://mozapps/content/downloads/downloads.xul", "chrome,dialog=no,resizable"); }],
|
||||
jumpto: ["Jump to a media item",
|
||||
function () { onJumpToFileKey(); }],
|
||||
newsmartplaylist: ["Open the file selector dialog",
|
||||
function () { SBNewSmartPlaylist(); }],
|
||||
openfile: ["Open the file selector dialog",
|
||||
function () { SBFileOpen(); }],
|
||||
pagesource: ["View page source",
|
||||
function () { window.BrowserViewSourceOfDocument(content.document); }],
|
||||
places: ["Places Organizer: Manage your bookmarks and history",
|
||||
function () { PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); }],
|
||||
preferences: ["Show Songbird preferences dialog",
|
||||
function () { window.openPreferences(); }],
|
||||
printsetup: ["Setup the page size and orientation before printing",
|
||||
function () { PrintUtils.showPageSetup(); }],
|
||||
print: ["Show print dialog",
|
||||
function () { PrintUtils.print(); }],
|
||||
saveframe: ["Save frame to disk",
|
||||
function () { window.saveFrameDocument(); }],
|
||||
savepage: ["Save page to disk",
|
||||
function () { window.saveDocument(window.content.document); }],
|
||||
searchengines: ["Manage installed search engines",
|
||||
function () { window.openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
|
||||
selectionsource: ["View selection source",
|
||||
function () { buffer.viewSelectionSource(); }],
|
||||
subscribe: ["Add a new subscription",
|
||||
function () { SBSubscribe(); }]
|
||||
},
|
||||
|
||||
focusChange: function () {
|
||||
// Switch to -- PLAYER -- mode for Songbird Media Player.
|
||||
if (config.isPlayerWindow)
|
||||
dactyl.mode = modes.PLAYER;
|
||||
else
|
||||
dactyl.mode = modes.NORMAL;
|
||||
},
|
||||
|
||||
hasTabbrowser: true,
|
||||
// FIXME: unless I'm seeing double in in the wee small hours gBrowser is
|
||||
// first set from getBrowser which they've deprecated in FF.
|
||||
get tabbrowser() window.getBrowser(),
|
||||
get browser() window.getBrowser(),
|
||||
|
||||
modes: [["PLAYER", { char: "p" }]],
|
||||
|
||||
removeTab: function (tab) {
|
||||
if (config.tabbrowser.mTabs.length > 1)
|
||||
config.tabbrowser.removeTab(tab);
|
||||
else {
|
||||
if (buffer.URL != "about:blank" || window.getWebNavigation().sessionHistory.count > 0) {
|
||||
dactyl.open("about:blank", dactyl.NEW_BACKGROUND_TAB);
|
||||
config.tabbrowser.removeTab(tab);
|
||||
}
|
||||
else
|
||||
dactyl.beep();
|
||||
}
|
||||
},
|
||||
|
||||
scripts: [
|
||||
"browser",
|
||||
"bookmarks",
|
||||
"history",
|
||||
"quickmarks",
|
||||
"tabs",
|
||||
"player",
|
||||
"library"
|
||||
],
|
||||
|
||||
// FIXME: tab arg and media tab exception?
|
||||
stop: function (tab) {
|
||||
SBGetBrowser().mCurrentBrowser.stop();
|
||||
}
|
||||
}, {
|
||||
|
||||
/**
|
||||
* Shows or hides the main service pane.
|
||||
*
|
||||
* @param {boolean} value Show the service pane if true, hide it if false.
|
||||
*/
|
||||
showServicePane: function (value) {
|
||||
const key = "splitter.servicepane_splitter.was_collapsed";
|
||||
gServicePane.open = value;
|
||||
SBDataSetBoolValue(key, gServicePane.open);
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the display panel with the specified <b>id<b>.
|
||||
*
|
||||
* @param {string} id The ID of the display pane.
|
||||
*/
|
||||
openDisplayPane: function (id) {
|
||||
if (id == "servicepane")
|
||||
this.showServicePane(true);
|
||||
else {
|
||||
let pane = document.getElementById(id);
|
||||
let manager = services.get("displayPaneManager");
|
||||
let paneinfo = manager.getPaneInfo(pane._lastURL.stringValue);
|
||||
|
||||
if (!paneinfo)
|
||||
paneinfo = manager.defaultPaneInfo;
|
||||
|
||||
pane.loadContent(paneinfo);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the display panel with the specified <b>id</b>
|
||||
*
|
||||
* @param {string} id The ID of the display pane.
|
||||
*/
|
||||
closeDisplayPane: function (id) {
|
||||
if (id == "servicepane")
|
||||
this.showServicePane(false);
|
||||
else
|
||||
document.getElementById(id).hide();
|
||||
},
|
||||
|
||||
// FIXME: best way to format these args? Hyphenated? One word like :dialog?
|
||||
/**
|
||||
* @property {object} A map of display pane command argument strings to
|
||||
* panel element IDs.
|
||||
*/
|
||||
displayPanes: {
|
||||
"service pane left": "servicepane",
|
||||
"content pane bottom": "displaypane_contentpane_bottom",
|
||||
"service pane bottom": "displaypane_servicepane_bottom",
|
||||
"right sidebar": "displaypane_right_sidebar"
|
||||
}
|
||||
}, {
|
||||
commands: function () {
|
||||
commands.add(["dpcl[ose]"],
|
||||
"Close a display pane",
|
||||
function (args) {
|
||||
let arg = args.literalArg;
|
||||
|
||||
if (arg in Config.displayPanes)
|
||||
Config.closeDisplayPane(Config.displayPanes[arg]);
|
||||
else
|
||||
dactyl.echoerr("E475: Invalid argument: " + arg);
|
||||
|
||||
},
|
||||
{
|
||||
argCount: "1",
|
||||
completer: function (context) completion.displayPane(context),
|
||||
literal: 0
|
||||
});
|
||||
|
||||
// TODO: this should accept a second arg to specify content
|
||||
commands.add(["displayp[ane]", "dp[ane]", "dpope[n]"],
|
||||
"Open a display pane",
|
||||
function (args) {
|
||||
let arg = args.literalArg;
|
||||
|
||||
if (arg in Config.displayPanes)
|
||||
Config.openDisplayPane(Config.displayPanes[arg]);
|
||||
// TODO: focus when we have better key handling of these extended modes
|
||||
else
|
||||
dactyl.echoerr("E475: Invalid argument: " + arg);
|
||||
},
|
||||
{
|
||||
argCount: "1",
|
||||
completer: function (context) completion.displayPane(context),
|
||||
literal: 0
|
||||
});
|
||||
|
||||
commands.add(["pref[erences]", "prefs"],
|
||||
"Show " + config.host + " preferences",
|
||||
function (args) {
|
||||
if (args.bang) { // open Songbird settings GUI dialog
|
||||
dactyl.open("about:config",
|
||||
(options["newtab"] && options.get("newtab").has("all", "prefs"))
|
||||
? dactyl.NEW_TAB : dactyl.CURRENT_TAB);
|
||||
}
|
||||
else
|
||||
window.openPreferences();
|
||||
},
|
||||
{
|
||||
argCount: "0",
|
||||
bang: true
|
||||
});
|
||||
},
|
||||
completion: function () {
|
||||
completion.displayPane = function (context) {
|
||||
context.title = ["Display Pane"];
|
||||
context.completions = Config.displayPanes; // FIXME: useful description etc
|
||||
};
|
||||
},
|
||||
modes: function () {
|
||||
this.ignoreKeys = {
|
||||
"<Return>": modes.NORMAL | modes.INSERT,
|
||||
"<Space>": modes.NORMAL | modes.INSERT,
|
||||
"<Up>": modes.NORMAL | modes.INSERT,
|
||||
"<Down>": modes.NORMAL | modes.INSERT
|
||||
};
|
||||
},
|
||||
options: function () {
|
||||
// TODO: SB doesn't explicitly support an offline mode. Should we? --djk
|
||||
options.add(["online"],
|
||||
"Set the 'work offline' option",
|
||||
"boolean", true,
|
||||
{
|
||||
setter: function (value) {
|
||||
const ioService = services.get("io");
|
||||
ioService.offline = !value;
|
||||
options.setPref("browser.offline", ioService.offline);
|
||||
return value;
|
||||
},
|
||||
getter: function () !services.get("io").offline
|
||||
});
|
||||
},
|
||||
services: function () {
|
||||
services.add("displayPaneManager", "@songbirdnest.com/Songbird/DisplayPane/Manager;1", Ci.sbIDisplayPaneManager);
|
||||
services.add("mediaPageManager", "@songbirdnest.com/Songbird/MediaPageManager;1", Ci.sbIMediaPageManager);
|
||||
services.add("propertyManager","@songbirdnest.com/Songbird/Properties/PropertyManager;1", Ci.sbIPropertyManager);
|
||||
services.addClass("mutablePropertyArray", "@songbirdnest.com/Songbird/Properties/MutablePropertyArray;1",
|
||||
Ci.sbIMutablePropertyArray);
|
||||
}
|
||||
});
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
18
melodactyl/content/dactyl.dtd
Normal file
18
melodactyl/content/dactyl.dtd
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
<!ENTITY % dactylBranding SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%dactylBranding;
|
||||
|
||||
<!ENTITY dactyl.mainWindow "mainplayer">
|
||||
<!ENTITY dactyl.commandContainer "&dactyl.mainWindow;">
|
||||
<!ENTITY dactyl.name "xulmus">
|
||||
<!ENTITY dactyl.appName "Xulmus">
|
||||
<!ENTITY dactyl.idName "XULMUS">
|
||||
<!ENTITY dactyl.host "&brandShortName;">
|
||||
<!ENTITY dactyl.hostbin "songbird">
|
||||
<!ENTITY dactyl.fileExt "xulmus">
|
||||
<!ENTITY dactyl.statusBefore "statusbar-display">
|
||||
<!ENTITY dactyl.statusAfter "">
|
||||
|
||||
<!ENTITY xmlns.dactyl "http://vimperator.org/namespaces/liberator">
|
||||
<!ENTITY xmlns.html "http://www.w3.org/1999/xhtml">
|
||||
<!ENTITY xmlns.xul "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
64
melodactyl/content/library.js
Normal file
64
melodactyl/content/library.js
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
|
||||
// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
|
||||
//
|
||||
// This work is licensed for reuse under an MIT license. Details are
|
||||
// given in the LICENSE.txt file included with this file.
|
||||
|
||||
|
||||
// TODO: flesh this out
|
||||
const Library = Module("library", {
|
||||
init: function () {
|
||||
this.MAIN_LIBRARY = LibraryUtils.mainLibrary;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an XPCOM enumerator to a JavaScript array.
|
||||
*
|
||||
* @param {nsISimpleEnumerator|nsIStringEnumerator|nsIArray} enum The enumerator to convert.
|
||||
* @returns {Array}
|
||||
*/
|
||||
_toJSArray: function _toJSArray(enum) ArrayConverter.JSArray(enum),
|
||||
|
||||
/**
|
||||
* Returns an array of all the artist names in the main library.
|
||||
*
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getArtists: function getArtists() this._toJSArray(this.MAIN_LIBRARY.getDistinctValuesForProperty(SBProperties.artistName)),
|
||||
|
||||
// FIXME: Prathyush do we really want to remove duplicates? If so, why not tracks too? --djk
|
||||
/**
|
||||
* Returns an array of all the album names for <b>artist</b> in the
|
||||
* main library.
|
||||
*
|
||||
* @param {string} artist The artist's name.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getAlbums: function getAlbums(artist) {
|
||||
let albums = this._toJSArray(this.MAIN_LIBRARY.getItemsByProperty(SBProperties.artistName, artist))
|
||||
.map(function (track) track.getProperty(SBProperties.albumName));
|
||||
return util.Array.uniq(albums);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of all the track names for <b>artist</b> and
|
||||
* <b>album</b> in the main library.
|
||||
*
|
||||
* @param {string} artist The artist's name.
|
||||
* @param {string} album The album's name.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getTracks: function getTracks(artist, album) {
|
||||
let properties = services.create("mutablePropertyArray");
|
||||
|
||||
properties.appendProperty(SBProperties.artistName, artist);
|
||||
properties.appendProperty(SBProperties.albumName, album);
|
||||
|
||||
return this._toJSArray(this.MAIN_LIBRARY.getItemsByProperties(properties))
|
||||
.map(function (track) track.getProperty(SBProperties.trackName));
|
||||
}
|
||||
}, {
|
||||
}, {
|
||||
});
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
BIN
melodactyl/content/logo.png
Normal file
BIN
melodactyl/content/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
52
melodactyl/content/melodactyl.xul
Normal file
52
melodactyl/content/melodactyl.xul
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://xulmus/skin/xulmus.css" type="text/css"?>
|
||||
|
||||
<overlay id="xulmus"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:nc="http://home.netscape.com/NC-rdf#"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<menupopup id="viewSidebarMenu">
|
||||
<menuitem observes="xulmus-viewAddonsSidebar" label="Add-ons" accesskey="A"/>
|
||||
<menuitem observes="xulmus-viewConsoleSidebar" label="Console" accesskey="C"/>
|
||||
<menuitem observes="xulmus-viewDownloadsSidebar" label="Downloads" accesskey="D"/>
|
||||
<menuitem observes="xulmus-viewPreferencesSidebar" label="Preferences" accesskey="P"/>
|
||||
</menupopup>
|
||||
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
<broadcaster id="xulmus-viewAddonsSidebar"
|
||||
autoCheck="false"
|
||||
type="checkbox"
|
||||
group="sidebar"
|
||||
sidebarurl="chrome://mozapps/content/extensions/extensions.xul"
|
||||
sidebartitle="Add-ons"
|
||||
oncommand="toggleSidebar('xulmus-viewAddonsSidebar');"/>
|
||||
<broadcaster id="xulmus-viewConsoleSidebar"
|
||||
autoCheck="false"
|
||||
type="checkbox"
|
||||
group="sidebar"
|
||||
sidebarurl="chrome://global/content/console.xul"
|
||||
sidebartitle="Console"
|
||||
oncommand="toggleSidebar('xulmus-viewConsoleSidebar');"/>
|
||||
<broadcaster id="xulmus-viewDownloadsSidebar"
|
||||
autoCheck="false"
|
||||
type="checkbox"
|
||||
group="sidebar"
|
||||
sidebarurl="chrome://mozapps/content/downloads/downloads.xul"
|
||||
sidebartitle="Downloads"
|
||||
oncommand="toggleSidebar('xulmus-viewDownloadsSidebar');"/>
|
||||
<broadcaster id="xulmus-viewPreferencesSidebar"
|
||||
autoCheck="false"
|
||||
type="checkbox"
|
||||
group="sidebar"
|
||||
sidebarurl="about:config"
|
||||
sidebartitle="Preferences"
|
||||
oncommand="toggleSidebar('xulmus-viewPreferencesSidebar');"/>
|
||||
</broadcasterset>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim: set fdm=marker sw=4 ts=4 et: -->
|
||||
799
melodactyl/content/player.js
Normal file
799
melodactyl/content/player.js
Normal file
@@ -0,0 +1,799 @@
|
||||
// Copyright (c) 2009 by Prathyush Thota <prathyushthota@gmail.com>
|
||||
// Copyright (c) 2009 by Doug Kearns <dougkearns@gmail.com>
|
||||
//
|
||||
// This work is licensed for reuse under an MIT license. Details are
|
||||
// given in the LICENSE.txt file included with this file.
|
||||
|
||||
|
||||
const Player = Module("player", {
|
||||
init: function init() {
|
||||
this._lastSearchString = "";
|
||||
this._lastSearchIndex = 0;
|
||||
this._lastSearchView = this._currentView; //XXX
|
||||
|
||||
// Get the focus to the visible playlist first
|
||||
//window._SBShowMainLibrary();
|
||||
|
||||
gMM.addListener(this._mediaCoreListener);
|
||||
},
|
||||
|
||||
destroy: function destroy() {
|
||||
gMM.removeListener(this._mediaCoreListener);
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves the track position <b>interval</b> milliseconds forwards or
|
||||
* backwards.
|
||||
*
|
||||
* @param {number} interval The time interval (ms) to move the track
|
||||
* position.
|
||||
* @param {boolean} direction The direction in which to move the track
|
||||
* position, forward if true otherwise backwards.
|
||||
* @private
|
||||
*/
|
||||
_seek: function _seek(interval, direction) {
|
||||
let position = gMM.playbackControl ? gMM.playbackControl.position : 0;
|
||||
player.seekTo(position + (direction ? interval : -interval));
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for media core events and in response dispatches the appropriate
|
||||
* autocommand events.
|
||||
* @private
|
||||
*/
|
||||
_mediaCoreListener: {
|
||||
onMediacoreEvent: function (event) {
|
||||
switch (event.type) {
|
||||
case Ci.sbIMediacoreEvent.BEFORE_TRACK_CHANGE:
|
||||
dactyl.log("Before track changed: " + event.data);
|
||||
autocommands.trigger("TrackChangePre", { track: event.data });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.TRACK_CHANGE:
|
||||
autocommands.trigger("TrackChange", { track: event.data });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.BEFORE_VIEW_CHANGE:
|
||||
dactyl.log("Before view changed: " + event.data);
|
||||
autocommands.trigger("ViewChangePre", { view: event.data });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.VIEW_CHANGE:
|
||||
dactyl.log("View changed: " + event.data);
|
||||
autocommands.trigger("ViewChange", { view: event.data });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.STREAM_START:
|
||||
dactyl.log("Track started: " + gMM.sequencer.currentItem);
|
||||
autocommands.trigger("StreamStart", { track: gMM.sequencer.currentItem });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.STREAM_PAUSE:
|
||||
dactyl.log("Track paused: " + gMM.sequencer.currentItem);
|
||||
autocommands.trigger("StreamPause", { track: gMM.sequencer.currentItem });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.STREAM_END:
|
||||
dactyl.log("Track ended: " + gMM.sequencer.currentItem);
|
||||
autocommands.trigger("StreamEnd", { track: gMM.sequencer.currentItem });
|
||||
break;
|
||||
case Ci.sbIMediacoreEvent.STREAM_STOP:
|
||||
dactyl.log("Track stopped: " + gMM.sequencer.currentItem);
|
||||
autocommands.trigger("StreamStop", { track: gMM.sequencer.currentItem });
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @property {sbIMediaListView} The current media list view. @private */
|
||||
get _currentView() SBGetBrowser().currentMediaListView,
|
||||
|
||||
/**
|
||||
* @property {number} The player volume in the range 0.0-1.0.
|
||||
*/
|
||||
get volume() gMM.volumeControl.volume,
|
||||
set volume(value) {
|
||||
gMM.volumeControl.volume = value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the specified media item in the current media list view.
|
||||
*
|
||||
* @param {sbIMediaItem} mediaItem The media item to focus.
|
||||
*/
|
||||
focusTrack: function focusTrack(mediaItem) {
|
||||
SBGetBrowser().mediaTab.mediaPage.highlightItem(this._currentView.getIndexForItem(mediaItem));
|
||||
},
|
||||
|
||||
/**
|
||||
* Plays the currently selected media item. If no item is selected the
|
||||
* first item in the current media view is played.
|
||||
*/
|
||||
play: function play() {
|
||||
// Check if there is any selection in place, else play first item of the visible view.
|
||||
// TODO: this approach, or similar, should be generalised for all commands, PT? --djk
|
||||
if (this._currentView.selection.count != 0)
|
||||
gMM.sequencer.playView(this._currentView,
|
||||
this._currentView.getIndexForItem(this._currentView.selection.currentMediaItem));
|
||||
else
|
||||
gMM.sequencer.playView(SBGetBrowser().currentMediaListView, 0);
|
||||
|
||||
this.focusTrack(gMM.sequencer.currentItem);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops playback of the currently playing media item.
|
||||
*/
|
||||
stop: function stop() {
|
||||
gMM.sequencer.stop();
|
||||
},
|
||||
|
||||
/**
|
||||
* Plays the next media item in the current media view.
|
||||
*/
|
||||
next: function next() {
|
||||
["cmd_control_next", "cmd_find_current_track"].forEach(gSongbirdWindowController.doCommand);
|
||||
},
|
||||
|
||||
/**
|
||||
* Plays the previous media item in the current media view.
|
||||
*/
|
||||
previous: function previous() {
|
||||
["cmd_control_previous", "cmd_find_current_track"].forEach(gSongbirdWindowController.doCommand);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the play/pause status of the current media item.
|
||||
*/
|
||||
togglePlayPause: function togglePlayPause() {
|
||||
["cmd_control_playpause", "cmd_find_current_track"].forEach(gSongbirdWindowController.doCommand);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the shuffle status of the sequencer.
|
||||
*/
|
||||
toggleShuffle: function toggleShuffle() {
|
||||
if (gMM.sequencer.mode != gMM.sequencer.MODE_SHUFFLE)
|
||||
gMM.sequencer.mode = gMM.sequencer.MODE_SHUFFLE;
|
||||
else
|
||||
gMM.sequencer.mode = gMM.sequencer.MODE_FORWARD;
|
||||
},
|
||||
|
||||
// FIXME: not really toggling (depending on your definition) - good enough for now.
|
||||
/**
|
||||
* Toggles between the sequencer's three repeat modes: Repeat-One,
|
||||
* Repeat-All and Repeat-None.
|
||||
*/
|
||||
toggleRepeat: function toggleRepeat() {
|
||||
switch (gMM.sequencer.repeatMode) {
|
||||
case gMM.sequencer.MODE_REPEAT_NONE:
|
||||
gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_ONE;
|
||||
break;
|
||||
case gMM.sequencer.MODE_REPEAT_ONE:
|
||||
gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_ALL;
|
||||
break;
|
||||
case gMM.sequencer.MODE_REPEAT_ALL:
|
||||
gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_NONE;
|
||||
break;
|
||||
default:
|
||||
gMM.sequencer.repeatMode = gMM.sequencer.MODE_REPEAT_NONE;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Seeks forward <b>interval</b> milliseconds in the currently playing
|
||||
* track.
|
||||
*
|
||||
* @param {number} interval The time interval (ms) to advance the
|
||||
* current track.
|
||||
*/
|
||||
seekForward: function seekForward(interval) {
|
||||
this._seek(interval, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Seeks backwards <b>interval</b> milliseconds in the currently
|
||||
* playing track.
|
||||
*
|
||||
* @param {number} interval The time interval (ms) to rewind the
|
||||
* current track.
|
||||
*/
|
||||
seekBackward: function seekBackward(interval) {
|
||||
this._seek(interval, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Seeks to a specific position in the currently playing track.
|
||||
*
|
||||
* @param {number} The new position (ms) in the track.
|
||||
*/
|
||||
seekTo: function seekTo(position) {
|
||||
// FIXME: if not playing
|
||||
if (!gMM.playbackControl)
|
||||
this.play();
|
||||
|
||||
let min = 0;
|
||||
let max = gMM.playbackControl.duration - 5000; // TODO: 5s buffer like cmus desirable?
|
||||
|
||||
gMM.playbackControl.position = util.Math.constrain(position, min, max);
|
||||
},
|
||||
|
||||
/**
|
||||
* Increases the volume by 5% of the maximum volume.
|
||||
*/
|
||||
increaseVolume: function increaseVolume() {
|
||||
this.volume = util.Math.constrain(this.volume + 0.05, 0, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Decreases the volume by 5% of the maximum volume.
|
||||
*/
|
||||
decreaseVolume: function decreaseVolume() {
|
||||
this.volume = util.Math.constrain(this.volume - 0.05, 0, 1);
|
||||
},
|
||||
|
||||
// TODO: Document what this buys us over and above cmd_find_current_track
|
||||
/**
|
||||
* Focuses the currently playing track.
|
||||
*/
|
||||
focusPlayingTrack: function focusPlayingTrack() {
|
||||
this.focusTrack(gMM.sequencer.currentItem);
|
||||
},
|
||||
|
||||
/**
|
||||
* Searches the current media view for <b>str</b>
|
||||
*
|
||||
* @param {string} str The search string.
|
||||
*/
|
||||
searchView: function searchView(str) {
|
||||
let search = _getSearchString(this._currentView);
|
||||
let searchString = "";
|
||||
|
||||
if (search != "") // XXX
|
||||
searchString = str + " " + search;
|
||||
else
|
||||
searchString = str;
|
||||
|
||||
this._lastSearchString = searchString;
|
||||
|
||||
let searchView = LibraryUtils.createStandardMediaListView(this._currentView.mediaList, searchString);
|
||||
|
||||
if (searchView.length) {
|
||||
this._lastSearchView = searchView;
|
||||
this._lastSearchIndex = 0;
|
||||
this.focusTrack(searchView.getItemByIndex(this._lastSearchIndex));
|
||||
}
|
||||
else
|
||||
dactyl.echoerr("E486 Pattern not found: " + searchString, commandline.FORCE_SINGLELINE);
|
||||
},
|
||||
|
||||
/**
|
||||
* Repeats the previous view search.
|
||||
*
|
||||
* @param {boolean} reverse Search in the reverse direction to the previous
|
||||
* search.
|
||||
*/
|
||||
searchViewAgain: function searchViewAgain(reverse) {
|
||||
function echo(str) {
|
||||
this.timeout(function () {
|
||||
commandline.echo(str, commandline.HL_WARNINGMSG, commandline.APPEND_TO_MESSAGES | commandline.FORCE_SINGLELINE);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
if (this._lastSearchIndex == 0) {
|
||||
this._lastSearchIndex = this._lastSearchView.length - 1;
|
||||
echo("Search hit TOP, continuing at BOTTOM");
|
||||
}
|
||||
else
|
||||
this._lastSearchIndex = this._lastSearchIndex - 1;
|
||||
}
|
||||
else {
|
||||
if (this._lastSearchIndex == (this._lastSearchView.length - 1)) {
|
||||
this._lastSearchIndex = 0;
|
||||
echo("Search hit BOTTOM, continuing at TOP");
|
||||
}
|
||||
else
|
||||
this._lastSearchIndex = this._lastSearchIndex + 1;
|
||||
}
|
||||
|
||||
// TODO: Implement for "?" --ken
|
||||
commandline.echo("/" + this._lastSearchString, null, commandline.FORCE_SINGLELINE);
|
||||
this.focusTrack(this._lastSearchView.getItemByIndex(this._lastSearchIndex));
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* The search dialog keypress callback.
|
||||
*
|
||||
* @param {string} str The contents of the search dialog.
|
||||
*/
|
||||
onSearchKeyPress: function onSearchKeyPress(str) {
|
||||
if (options["incsearch"])
|
||||
this.searchView(str);
|
||||
},
|
||||
|
||||
/**
|
||||
* The search dialog submit callback.
|
||||
*
|
||||
* @param {string} str The contents of the search dialog.
|
||||
*/
|
||||
onSearchSubmit: function onSearchSubmit(str) {
|
||||
this.searchView(str);
|
||||
},
|
||||
|
||||
/**
|
||||
* The search dialog cancel callback.
|
||||
*/
|
||||
onSearchCancel: function onSearchCancel() {
|
||||
// TODO: restore the view state if altered by an 'incsearch' search
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of all available playlists.
|
||||
*
|
||||
* @returns {sbIMediaList[]}
|
||||
*/
|
||||
getPlaylists: function getPlaylists() {
|
||||
let mainLibrary = LibraryUtils.mainLibrary;
|
||||
let playlists = [mainLibrary];
|
||||
let listener = {
|
||||
onEnumerationBegin: function () { },
|
||||
onEnumerationEnd: function () { },
|
||||
onEnumeratedItem: function (list, item) {
|
||||
// FIXME: why are there null items and duplicates?
|
||||
if (!playlists.some(function (list) list.name == item.name) && item.name != null)
|
||||
playlists.push(item);
|
||||
return Ci.sbIMediaListEnumerationListener.CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
mainLibrary.enumerateItemsByProperty("http://songbirdnest.com/data/1.0#isList", "1", listener);
|
||||
|
||||
return playlists;
|
||||
},
|
||||
|
||||
/**
|
||||
* Plays the media item at <b>index</b> in <b>playlist</b>.
|
||||
*
|
||||
* @param {sbIMediaList} playlist
|
||||
* @param {number} index
|
||||
*/
|
||||
playPlaylist: function playPlaylist(playlist, index) {
|
||||
gMM.sequencer.playView(playlist.createView(), index);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of all available media pages.
|
||||
*
|
||||
* @returns {sbIMediaPageInfo[]}
|
||||
*/
|
||||
getMediaPages: function getMediaPages() {
|
||||
let list = SBGetBrowser().currentMediaPage.mediaListView.mediaList;
|
||||
let pages = services.get("mediaPageManager").getAvailablePages(list);
|
||||
return ArrayConverter.JSArray(pages).map(function (page) page.QueryInterface(Ci.sbIMediaPageInfo));
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the the specified media page into <b>view</b> with the given
|
||||
* <b>list</b> of media items.
|
||||
*
|
||||
* @param {sbIMediaPage} page
|
||||
* @param {sbIMediaList} list
|
||||
* @param {sbIMediaView} view
|
||||
*/
|
||||
loadMediaPage: function loadMediaPage(page, list, view) {
|
||||
services.get("mediaPageManager").setPage(list, page);
|
||||
SBGetBrowser().loadMediaList(list, null, null, view, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Applys the specified <b>rating<b> to <b>mediaItem<b>.
|
||||
*
|
||||
* @param {sbIMediaItem} mediaItem The media item to rate.
|
||||
* @param {number} rating The star rating (1-5).
|
||||
*/
|
||||
rateMediaItem: function rateMediaItem(mediaItem, rating) {
|
||||
mediaItem.setProperty(SBProperties.rating, rating);
|
||||
},
|
||||
|
||||
// TODO: add more fields, and generate the list dynamically. PT should the
|
||||
// available fields reflect only the visible view fields or offer others? --djk
|
||||
/**
|
||||
* Sorts the current media view by <b>field</b> in the order specified by
|
||||
* <b>ascending</b>.
|
||||
*
|
||||
* @param {string} field The sort field.
|
||||
* @param {boolean} ascending If true sort in ascending order, otherwise in
|
||||
* descending order.
|
||||
*/
|
||||
sortBy: function sortBy(field, ascending) {
|
||||
let order = ascending ? "a" : "d";
|
||||
let properties = services.create("mutablePropertyArray");
|
||||
properties.strict = false;
|
||||
|
||||
switch (field) {
|
||||
case "title":
|
||||
properties.appendProperty(SBProperties.trackName, order);
|
||||
break;
|
||||
case "time":
|
||||
properties.appendProperty(SBProperties.duration, order);
|
||||
break;
|
||||
case "artist":
|
||||
properties.appendProperty(SBProperties.artistName, order);
|
||||
break;
|
||||
case "album":
|
||||
properties.appendProperty(SBProperties.albumName, order);
|
||||
break;
|
||||
case "genre":
|
||||
properties.appendProperty(SBProperties.genre, order);
|
||||
break;
|
||||
case "rating":
|
||||
properties.appendProperty(SBProperties.rating, order);
|
||||
break;
|
||||
default:
|
||||
properties.appendProperty(SBProperties.trackName, order);
|
||||
break;
|
||||
}
|
||||
|
||||
this._currentView.setSort(properties);
|
||||
}
|
||||
}, {
|
||||
}, {
|
||||
commandline: function () {
|
||||
commandline.registerCallback("change", modes.SEARCH_VIEW_FORWARD, this.closure.onSearchKeyPress);
|
||||
commandline.registerCallback("submit", modes.SEARCH_VIEW_FORWARD, this.closure.onSearchSubmit);
|
||||
commandline.registerCallback("cancel", modes.SEARCH_VIEW_FORWARD, this.closure.onSearchCancel);
|
||||
},
|
||||
commands: function () {
|
||||
commands.add(["f[ilter]"],
|
||||
"Filter tracks based on keywords {genre/artist/album/track}",
|
||||
function (args) {
|
||||
let library = LibraryUtils.mainLibrary;
|
||||
let view = LibraryUtils.createStandardMediaListView(LibraryUtils.mainLibrary, args.literalArg);
|
||||
|
||||
if (view.length == 0)
|
||||
dactyl.echoerr("No Tracks matching the keywords");
|
||||
else {
|
||||
SBGetBrowser().loadMediaList(LibraryUtils.mainLibrary, null, null, view,
|
||||
"chrome://songbird/content/mediapages/filtersPage.xul");
|
||||
// TODO: make this this.focusTrack work ?
|
||||
this.focusTrack(view.getItemByIndex(0));
|
||||
}
|
||||
},
|
||||
{
|
||||
argCount: "1",
|
||||
literal: 0
|
||||
//completer: function (context, args) completion.tracks(context, args);
|
||||
});
|
||||
|
||||
commands.add(["load"],
|
||||
"Load a playlist",
|
||||
function (args) {
|
||||
let arg = args.literalArg;
|
||||
|
||||
if (arg) {
|
||||
// load the selected playlist/smart playlist
|
||||
let playlists = player.getPlaylists();
|
||||
|
||||
for ([i, list] in Iterator(playlists)) {
|
||||
if (util.compareIgnoreCase(arg, list.name) == 0) {
|
||||
SBGetBrowser().loadMediaList(playlists[i]);
|
||||
this.focusTrack(this._currentView.getItemByIndex(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dactyl.echoerr("E475: Invalid argument: " + arg);
|
||||
}
|
||||
else {
|
||||
// load main library if there are no args
|
||||
_SBShowMainLibrary();
|
||||
}
|
||||
},
|
||||
{
|
||||
argCount: "?",
|
||||
completer: function (context, args) completion.playlist(context, args),
|
||||
literal: 0
|
||||
});
|
||||
|
||||
// TODO: better off as a single command (:player play) or cmus compatible (:player-play)? --djk
|
||||
commands.add(["playerp[lay]"],
|
||||
"Play track",
|
||||
function () { player.play(); });
|
||||
|
||||
commands.add(["playerpa[use]"],
|
||||
"Pause/unpause track",
|
||||
function () { player.togglePlayPause(); });
|
||||
|
||||
commands.add(["playern[ext]"],
|
||||
"Play next track",
|
||||
function () { player.next(); });
|
||||
|
||||
commands.add(["playerpr[ev]"],
|
||||
"Play previous track",
|
||||
function () { player.previous(); });
|
||||
|
||||
commands.add(["players[top]"],
|
||||
"Stop track",
|
||||
function () { player.stop(); });
|
||||
|
||||
commands.add(["see[k]"],
|
||||
"Seek to a track position",
|
||||
function (args) {
|
||||
let arg = args[0];
|
||||
|
||||
// intentionally supports 999:99:99
|
||||
if (!/^[+-]?(\d+[smh]?|(\d+:\d\d:|\d+:)?\d{2})$/.test(arg))
|
||||
return void dactyl.echoerr("E475: Invalid argument: " + arg);
|
||||
|
||||
function ms(t, m) Math.abs(parseInt(t, 10) * { s: 1000, m: 60000, h: 3600000 }[m])
|
||||
|
||||
if (/:/.test(arg)) {
|
||||
let [seconds, minutes, hours] = arg.split(":").reverse();
|
||||
hours = hours || 0;
|
||||
var value = ms(seconds, "s") + ms(minutes, "m") + ms(hours, "h");
|
||||
}
|
||||
else {
|
||||
if (!/[smh]/.test(arg.substr(-1)))
|
||||
arg += "s"; // default to seconds
|
||||
|
||||
value = ms(arg.substring(arg, arg.length - 1), arg.substr(-1));
|
||||
}
|
||||
|
||||
if (/^[-+]/.test(arg))
|
||||
arg[0] == "-" ? player.seekBackward(value) : player.seekForward(value);
|
||||
else
|
||||
player.seekTo(value);
|
||||
|
||||
},
|
||||
{ argCount: "1" });
|
||||
|
||||
commands.add(["mediav[iew]"],
|
||||
"Change the current media view",
|
||||
function (args) {
|
||||
// FIXME: is this a SB restriction? --djk
|
||||
if (!SBGetBrowser().currentMediaPage)
|
||||
return void dactyl.echoerr("Exxx: Can only set the media view from the media tab"); // XXX
|
||||
|
||||
let arg = args[0];
|
||||
|
||||
if (arg) {
|
||||
let pages = player.getMediaPages();
|
||||
|
||||
for ([, page] in Iterator(pages)) {
|
||||
if (util.compareIgnoreCase(arg, page.contentTitle) == 0) {
|
||||
player.loadMediaPage(page, SBGetBrowser().currentMediaListView.mediaList,
|
||||
SBGetBrowser().currentMediaListView);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dactyl.echoerr("E475: Invalid argument: " + arg);
|
||||
}
|
||||
},
|
||||
{
|
||||
argCount: "1",
|
||||
completer: function (context) completion.mediaView(context),
|
||||
literal: 0
|
||||
});
|
||||
|
||||
commands.add(["sort[view]"],
|
||||
"Sort the current media view",
|
||||
function (args) {
|
||||
let order = args["-order"] || "up";
|
||||
player.sortBy(args[0], order == "up");
|
||||
},
|
||||
{
|
||||
argCount: "1",
|
||||
completer: function (context) completion.mediaListSort(context),
|
||||
options: [[["-order", "-o"], commands.OPTION_STRING,
|
||||
function (arg) /^(up|down)$/.test(arg),
|
||||
function () [["up", "Sort in ascending order"], ["down", "Sort in descending order"]]]]
|
||||
});
|
||||
|
||||
// FIXME: use :add -q like cmus? (not very vim-like are it's multi-option commands) --djk
|
||||
commands.add(["qu[eue]"],
|
||||
"Queue tracks by artist/album/track",
|
||||
function (args) {
|
||||
let properties = services.create("mutablePropertyArray");
|
||||
|
||||
// args
|
||||
switch (args.length) {
|
||||
case 3:
|
||||
properties.appendProperty(SBProperties.trackName, args[2]);
|
||||
case 2:
|
||||
properties.appendProperty(SBProperties.albumName, args[1]);
|
||||
case 1:
|
||||
properties.appendProperty(SBProperties.artistName, args[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
let library = LibraryUtils.mainLibrary;
|
||||
let mainView = library.createView();
|
||||
gMM.sequencer.playView(mainView,
|
||||
mainView.getIndexForItem(library.getItemsByProperties(properties).queryElementAt(0, Ci.sbIMediaItem)));
|
||||
player.focusPlayingTrack();
|
||||
},
|
||||
{
|
||||
argCount: "+",
|
||||
completer: function (context, args) completion.song(context, args)
|
||||
});
|
||||
|
||||
// TODO: maybe :vol! could toggle mute on/off? --djk
|
||||
commands.add(["vol[ume]"],
|
||||
"Set the volume",
|
||||
function (args) {
|
||||
let arg = args[0];
|
||||
|
||||
if (!/^[+-]?\d+$/.test(arg))
|
||||
return void dactyl.echoerr("E488: Trailing characters");
|
||||
|
||||
let level = parseInt(arg, 10) / 100;
|
||||
|
||||
if (/^[+-]/.test(arg))
|
||||
level = player.volume + level;
|
||||
|
||||
player.volume = util.Math.constrain(level, 0, 1);
|
||||
},
|
||||
{ argCount: "1" });
|
||||
},
|
||||
completion: function () {
|
||||
completion.song = function song(context, args) {
|
||||
// TODO: useful descriptions?
|
||||
function map(list) list.map(function (i) [i, ""]);
|
||||
let [artist, album] = [args[0], args[1]];
|
||||
|
||||
if (args.completeArg == 0) {
|
||||
context.title = ["Artists"];
|
||||
context.completions = map(library.getArtists());
|
||||
}
|
||||
else if (args.completeArg == 1) {
|
||||
context.title = ["Albums by " + artist];
|
||||
context.completions = map(library.getAlbums(artist));
|
||||
}
|
||||
else if (args.completeArg == 2) {
|
||||
context.title = ["Tracks from " + album + " by " + artist];
|
||||
context.completions = map(library.getTracks(artist, album));
|
||||
}
|
||||
};
|
||||
|
||||
completion.playlist = function playlist(context, args) {
|
||||
context.title = ["Playlist", "Type"];
|
||||
context.keys = { text: "name", description: "type" };
|
||||
context.completions = player.getPlaylists();
|
||||
};
|
||||
|
||||
completion.mediaView = function mediaView(context) {
|
||||
context.title = ["Media View", "URL"];
|
||||
context.anchored = false;
|
||||
context.keys = { text: "contentTitle", description: "contentUrl" };
|
||||
context.completions = player.getMediaPages();
|
||||
};
|
||||
|
||||
completion.mediaListSort = function mediaListSort(context) {
|
||||
context.title = ["Media List Sort Field", "Description"];
|
||||
context.anchored = false;
|
||||
context.completions = [["title", "Track name"], ["time", "Duration"], ["artist", "Artist name"],
|
||||
["album", "Album name"], ["genre", "Genre"], ["rating", "Rating"]]; // FIXME: generate this list dynamically - see #sortBy
|
||||
};
|
||||
},
|
||||
mappings: function () {
|
||||
mappings.add([modes.PLAYER],
|
||||
["x"], "Play track",
|
||||
function () { player.play(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["z"], "Previous track",
|
||||
function () { player.previous(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["c"], "Pause/unpause track",
|
||||
function () { player.togglePlayPause(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["b"], "Next track",
|
||||
function () { player.next(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["v"], "Stop track",
|
||||
function () { player.stop(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["Q"], "Queue tracks by artist/album/track",
|
||||
function () { commandline.open(":", "queue ", modes.EX); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["f"], "Loads current view filtered by the keywords",
|
||||
function () { commandline.open(":", "filter ", modes.EX); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["i"], "Select current track",
|
||||
function () { gSongbirdWindowController.doCommand("cmd_find_current_track"); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["s"], "Toggle shuffle",
|
||||
function () { player.toggleShuffle(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["r"], "Toggle repeat",
|
||||
function () { player.toggleRepeat(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["h", "<Left>"], "Seek -10s",
|
||||
function (count) { player.seekBackward(Math.max(1, count) * 10000); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["l", "<Right>"], "Seek +10s",
|
||||
function (count) { player.seekForward(Math.max(1, count) * 10000); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["H", "<S-Left>"], "Seek -1m",
|
||||
function (count) { player.seekBackward(Math.max(1, count) * 60000); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["L", "<S-Right>"], "Seek +1m",
|
||||
function (count) { player.seekForward(Math.max(1, count) * 60000); },
|
||||
{ count: true });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["=", "+"], "Increase volume by 5% of the maximum",
|
||||
function () { player.increaseVolume(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["-"], "Decrease volume by 5% of the maximum",
|
||||
function () { player.decreaseVolume(); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["/"], "Search forward for a track",
|
||||
function (args) { commandline.open("/", "", modes.SEARCH_VIEW_FORWARD); });
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["n"], "Find the next track",
|
||||
function () { player.searchViewAgain(false);});
|
||||
|
||||
mappings.add([modes.PLAYER],
|
||||
["N"], "Find the previous track",
|
||||
function () { player.searchViewAgain(true);});
|
||||
|
||||
for (let i in util.range(0, 6)) {
|
||||
let (rating = i) {
|
||||
mappings.add([modes.PLAYER],
|
||||
["<C-" + rating + ">"], "Rate the current media item " + rating,
|
||||
function () {
|
||||
let item = gMM.sequencer.currentItem || this._currentView.selection.currentMediaItem; // XXX: a bit too magic
|
||||
if (item)
|
||||
player.rateMediaItem(item, rating);
|
||||
else
|
||||
dactyl.beep();
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
},
|
||||
options: function () {
|
||||
options.add(["repeat"],
|
||||
"Set the playback repeat mode",
|
||||
"number", 0,
|
||||
{
|
||||
setter: function (value) gMM.sequencer.repeatMode = value,
|
||||
getter: function () gMM.sequencer.repeatMode,
|
||||
completer: function (context) [
|
||||
["0", "Repeat none"],
|
||||
["1", "Repeat one"],
|
||||
["2", "Repeat all"]
|
||||
],
|
||||
validator: Option.validateCompleter
|
||||
});
|
||||
|
||||
options.add(["shuffle"],
|
||||
"Play tracks in shuffled order",
|
||||
"boolean", false,
|
||||
{
|
||||
setter: function (value) gMM.sequencer.mode = value ? gMM.sequencer.MODE_SHUFFLE : gMM.sequencer.MODE_FORWARD,
|
||||
getter: function () gMM.sequencer.mode == gMM.sequencer.MODE_SHUFFLE
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
88
melodactyl/content/xulmus.svg
Normal file
88
melodactyl/content/xulmus.svg
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="162"
|
||||
height="40"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
version="1.0"
|
||||
sodipodi:docbase="/home/maxauthority/code/pentadactyl"
|
||||
sodipodi:docname="xulmus.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="/home/maxauthority/code/pentadactyl/xulmus.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 29 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="185 : 29 : 1"
|
||||
inkscape:persp3d-origin="92.5 : 19.333333 : 1"
|
||||
id="perspective2392" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.04"
|
||||
inkscape:cx="84.114858"
|
||||
inkscape:cy="55.052209"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="185px"
|
||||
height="58px"
|
||||
showgrid="false" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-5.4392018,-9.6624603)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans Mono"
|
||||
x="6.2673268"
|
||||
y="29.896835"
|
||||
id="text2229"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2231"
|
||||
x="6.2673268"
|
||||
y="29.896835">xulmus_</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-weight:normal;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans Mono"
|
||||
x="6.4079518"
|
||||
y="53.183945"
|
||||
id="text2233"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2235"
|
||||
x="6.4079518"
|
||||
y="53.183945">~</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
9
melodactyl/contrib/vim/Makefile
Normal file
9
melodactyl/contrib/vim/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
VIMBALL = xulmus.vba
|
||||
|
||||
vimball: mkvimball.txt syntax/xulmus.vim ftdetect/xulmus.vim
|
||||
-echo '%MkVimball! ${VIMBALL} .' | vim -u NORC -N -e -s mkvimball.txt
|
||||
|
||||
all: vimball
|
||||
|
||||
clean:
|
||||
rm -f ${VIMBALL}
|
||||
2
melodactyl/contrib/vim/ftdetect/melodactyl.vim
Normal file
2
melodactyl/contrib/vim/ftdetect/melodactyl.vim
Normal file
@@ -0,0 +1,2 @@
|
||||
" TODO: what's the Xulmus filename extension?
|
||||
au BufNewFile,BufRead *xulmusrc*,*.xulmus set filetype=xulmus
|
||||
2
melodactyl/contrib/vim/mkvimball.txt
Normal file
2
melodactyl/contrib/vim/mkvimball.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
syntax/xulmus.vim
|
||||
ftdetect/xulmus.vim
|
||||
111
melodactyl/contrib/vim/syntax/melodactyl.vim
Normal file
111
melodactyl/contrib/vim/syntax/melodactyl.vim
Normal file
@@ -0,0 +1,111 @@
|
||||
" Vim syntax file
|
||||
" Language: Xulmus configuration file
|
||||
" Maintainer: Doug Kearns <dougkearns@gmail.com>
|
||||
" Last Change: 2009 Nov 14
|
||||
|
||||
" TODO: make this xulmus specific - shared dactyl config?
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
syn include @javascriptTop syntax/javascript.vim
|
||||
unlet b:current_syntax
|
||||
|
||||
syn include @cssTop syntax/css.vim
|
||||
unlet b:current_syntax
|
||||
|
||||
syn match xulmusCommandStart "\%(^\s*:\=\)\@<=" nextgroup=xulmusCommand,xulmusAutoCmd
|
||||
|
||||
syn keyword xulmusCommand ab[breviate] ab[clear] addo[ns] bN[ext] b[uffer] ba[ck] bd[elete] beep bf[irst] bl[ast] bma[rk] bmarks
|
||||
\ bn[ext] bp[revious] br[ewind] bufd[o] buffers bun[load] bw[ipeout] ca[bbrev] cabc[lear] cd chd[ir] cm[ap] cmapc[lear]
|
||||
\ cno[remap] colo[rscheme] com[mand] comc[lear] cu[nmap] cuna[bbrev] delbm[arks] delc[ommand] delm[arks] delmac[ros]
|
||||
\ delqm[arks] dels[tyle] dia[log] displayp[ane] dl do[autocmd] doautoa[ll] downl[oads] dp[ane] dpcl[ose] dpope[n] ec[ho]
|
||||
\ echoe[rr] echom[sg] em[enu] exe[cute] exta[dd] extd[isable] extde[lete] exte[nable] extens[ions] exto[ptions]
|
||||
\ extp[references] exu[sage] f[ilter] files fini[sh] fo[rward] frameo[nly] fw h[elp] helpa[ll] ha[rdcopy] hi[ghlight]
|
||||
\ hist[ory] hs ia[bbrev] iabc[lear] im[ap] imapc[lear] ino[remap] iu[nmap] iuna[bbrev] javas[cript] js ju[mps] let load
|
||||
\ loadplugins lpl ls ma[rk] macros map mapc[lear] marks mediav[iew] mes[sages] messc[lear] mkv[imperatorrc] mkx[ulmusrc]
|
||||
\ nm[ap] nmap[clear] nno[remap] no[remap] noh[lsearch] norm[al] nu[nmap] o[pen] optionu[sage] pa[geinfo] pagest[yle] pas
|
||||
\ playern[ext] playerp[lay] playerpa[use] playerpr[ev] players[top] pm[ap] pmap[clear] pno[remap] pref[erences] prefs
|
||||
\ pu[nmap] pw[d] q[uit] qa[ll] qma[rk] qmarks queue quita[ll] re[draw] re[load] reloada[ll] res[tart] run runt[ime] sav[eas]
|
||||
\ sb[ar] sb[open] sbcl[ose] scrip[tnames] se[t] see[k] setg[lobal] setl[ocal] sideb[ar] sil[ent] sort[view] so[urce] st[op]
|
||||
\ stopa[ll] sty[le] tN[ext] t[open] tab tabN[ext] tabc[lose] tabd[o] tabde[tach] tabdu[plicate] tabfir[st] tabl[ast] tabm[ove]
|
||||
\ tabn[ext] tabnew tabo[nly] tabopen tabp[revious] tabr[ewind] tabs tbh[ide] tbs[how] tbt[oggle] time tn[ext] toolbarh[ide]
|
||||
\ toolbars[how] toolbart[oggle] tp[revious] u[ndo] una[bbreviate] undoa[ll] unl[et] unm[ap] verb[ose] ve[rsion] vie[wsource]
|
||||
\ viu[sage] vm[ap] vmap[clear] vno[remap] vol[ume] vu[nmap] w[rite] wc[lose] winc[lose] wq wqa[ll] xa[ll] zo[om]
|
||||
\ contained
|
||||
|
||||
syn match xulmusCommand "!" contained
|
||||
|
||||
syn keyword xulmusAutoCmd au[tocmd] contained nextgroup=xulmusAutoEventList skipwhite
|
||||
|
||||
syn keyword xulmusAutoEvent BookmarkAdd ColorScheme DOMLoad DownloadPost Fullscreen LocationChange PageLoad PageLoadPre
|
||||
\ ShellCmdPost StreamEnd StreamPause StreamStart StreamStop TrackChange TrackChangePre ViewChange ViewChangePre XulmusEnter
|
||||
\ XulmusLeave XulmusLeavePre
|
||||
\ contained
|
||||
|
||||
syn match xulmusAutoEventList "\(\a\+,\)*\a\+" contained contains=xulmusAutoEvent
|
||||
|
||||
syn region xulmusSet matchgroup=xulmusCommand start="\%(^\s*:\=\)\@<=\<\%(setl\%[ocal]\|setg\%[lobal]\|set\=\)\=\>"
|
||||
\ end="$" keepend oneline contains=xulmusOption,xulmusString
|
||||
|
||||
syn keyword xulmusOption activate act cdpath cd complete cpt defsearch ds editor encoding enc eventignore ei extendedhinttags eht
|
||||
\ fileencoding fenc followhints fh guioptions go helpfile hf hintinputs hin hintmatching hm hinttags ht hinttimeout hto
|
||||
\ history hi laststatus ls maxitems messages msgs newtab nextpattern pageinfo pa popups pps previouspattern repeat runtimepath
|
||||
\ rtp scroll scr shell sh shellcmdflag shcf showstatuslinks ssli showtabline stal suggestengines titlestring urlseparator
|
||||
\ verbose vbs wildcase wic wildignore wig wildmode wim wildoptions wop wordseparators wsp
|
||||
\ contained nextgroup=xulmusSetMod
|
||||
|
||||
" toggle options
|
||||
syn match xulmusOption "\<\%(no\|inv\)\=\%(errorbells\|eb\|exrc\|ex\|focuscontent\|fc\|fullscreen\|fs\|ignorecase\|ic\)\>!\="
|
||||
\ contained nextgroup=xulmusSetMod
|
||||
syn match xulmusOption "\<\%(no\|inv\)\=\%(incsearch\|is\|insertmode\|im\|hlsearch\|hls\|linksearch\|lks\)\>!\="
|
||||
\ contained nextgroup=xulmusSetMod
|
||||
syn match xulmusOption "\<\%(no\|inv\)\=\%(loadplugins\|lpl\|more\|online\|shuffle\|showmode\|smd\|smartcase\|scs\)\>!\="
|
||||
\ contained nextgroup=xulmusSetMod
|
||||
syn match xulmusOption "\<\%(no\|inv\)\=\%(online\|visualbell\|vb\|usermode\|um\)\>!\="
|
||||
\ contained nextgroup=xulmusSetMod
|
||||
|
||||
syn match xulmusSetMod "\%(\<[a-z_]\+\)\@<=&" contained
|
||||
|
||||
syn region xulmusJavaScript start="\%(^\s*\%(javascript\|js\)\s\+\)\@<=" end="$" contains=@javascriptTop keepend oneline
|
||||
syn region xulmusJavaScript matchgroup=xulmusJavaScriptDelimiter
|
||||
\ start="\%(^\s*\%(javascript\|js\)\s\+\)\@<=<<\s*\z(\h\w*\)"hs=s+2 end="^\z1$" contains=@javascriptTop fold
|
||||
|
||||
let s:cssRegionStart = '\%(^\s*sty\%[le]!\=\s\+\%(-\%(n\|name\)\%(\s\+\|=\)\S\+\s\+\)\=[^-]\S\+\s\+\)\@<='
|
||||
execute 'syn region xulmusCss start="' . s:cssRegionStart . '" end="$" contains=@cssTop keepend oneline'
|
||||
execute 'syn region xulmusCss matchgroup=xulmusCssDelimiter'
|
||||
\ 'start="' . s:cssRegionStart . '<<\s*\z(\h\w*\)"hs=s+2 end="^\z1$" contains=@cssTop fold'
|
||||
|
||||
syn match xulmusNotation "<[0-9A-Za-z-]\+>"
|
||||
|
||||
syn match xulmusComment +".*$+ contains=xulmusTodo,@Spell
|
||||
syn keyword xulmusTodo FIXME NOTE TODO XXX contained
|
||||
|
||||
syn region xulmusString start="\z(["']\)" end="\z1" skip="\\\\\|\\\z1" oneline
|
||||
|
||||
syn match xulmusLineComment +^\s*".*$+ contains=xulmusTodo,@Spell
|
||||
|
||||
" NOTE: match vim.vim highlighting group names
|
||||
hi def link xulmusAutoCmd xulmusCommand
|
||||
hi def link xulmusAutoEvent Type
|
||||
hi def link xulmusCommand Statement
|
||||
hi def link xulmusComment Comment
|
||||
hi def link xulmusJavaScriptDelimiter Delimiter
|
||||
hi def link xulmusCssDelimiter Delimiter
|
||||
hi def link xulmusNotation Special
|
||||
hi def link xulmusLineComment Comment
|
||||
hi def link xulmusOption PreProc
|
||||
hi def link xulmusSetMod xulmusOption
|
||||
hi def link xulmusString String
|
||||
hi def link xulmusTodo Todo
|
||||
|
||||
let b:current_syntax = "xulmus"
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: tw=130 et ts=4 sw=4:
|
||||
4
melodactyl/defaults/preferences/dactyl.js
Normal file
4
melodactyl/defaults/preferences/dactyl.js
Normal file
@@ -0,0 +1,4 @@
|
||||
pref("extensions.dactyl.name", "melodactyl");
|
||||
pref("extensions.dactyl.appName", "Melodactyl");
|
||||
pref("extensions.dactyl.idName", "MELODACTYL");
|
||||
pref("extensions.dactyl.host", "Songbird");
|
||||
25
melodactyl/install.rdf
Normal file
25
melodactyl/install.rdf
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#"
|
||||
xmlns:songbird="http://www.songbirdnest.com/2007/addon-metadata-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>melodactyl@dactyl.googlecode.com</em:id>
|
||||
<em:type>2</em:type>
|
||||
<em:name>Melodactyl</em:name>
|
||||
<em:version>0.1a1pre</em:version>
|
||||
<em:description>Songbird for Vim and CMus junkies.</em:description>
|
||||
<em:creator>Prathyush Thota</em:creator>
|
||||
<em:homepageURL>http://dactyl.sourceforge.net/</em:homepageURL>
|
||||
<em:iconURL>chrome://melodactyl/skin/icon.png</em:iconURL>
|
||||
<em:optionsURL>chrome://dactyl/content/preferences.xul</em:optionsURL>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>songbird@songbirdnest.com</em:id>
|
||||
<em:minVersion>1.8.0</em:minVersion>
|
||||
<em:maxVersion>1.9.0</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
||||
|
||||
<!-- vim: set fdm=marker sw=4 ts=4 et: -->
|
||||
14
melodactyl/locale/en-US/all.xml
Normal file
14
melodactyl/locale/en-US/all.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<include href="player" tag="player.html" insertafter="intro.html"/>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
51
melodactyl/locale/en-US/autocommands.xml
Normal file
51
melodactyl/locale/en-US/autocommands.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<dl tag="autocommand-list" replace="autocommand-list">
|
||||
<dt>BookmarkAdd</dt> <dd>Triggered after a page is bookmarked</dd>
|
||||
<dt>ColorScheme</dt> <dd>Triggered after a color scheme has been loaded</dd>
|
||||
<dt>DOMLoad</dt> <dd>Triggered when a page's DOM content has fully loaded</dd>
|
||||
<dt>DownloadPost</dt> <dd>Triggered when a download has completed</dd>
|
||||
<dt>Fullscreen</dt> <dd>Triggered when the player's fullscreen state changes</dd>
|
||||
<dt>LocationChange</dt><dd>Triggered when changing tabs or when navigating to a new location</dd>
|
||||
<dt>PageLoadPre</dt> <dd>Triggered after a page load is initiated</dd>
|
||||
<dt>PageLoad</dt> <dd>Triggered when a page gets (re)loaded/opened</dd>
|
||||
<dt>ShellCmdPost</dt> <dd>Triggered after executing a shell command with <ex>:!</ex>#{cmd}</dd>
|
||||
<dt>TrackChangePre</dt><dd>Triggered before a playing track is changed</dd>
|
||||
<dt>TrackChange</dt> <dd>Triggered after a playing track has changed</dd>
|
||||
<dt>ViewChangePre</dt> <dd>Triggered before a sequencer view is changed</dd>
|
||||
<dt>ViewChange</dt> <dd>Triggered after a sequencer view is changed</dd>
|
||||
<dt>StreamStart</dt> <dd>Triggered after a stream has started</dd>
|
||||
<dt>StreamPause</dt> <dd>Triggered after a stream has paused</dd>
|
||||
<dt>StreamEnd</dt> <dd>Triggered after a stream has ended</dd>
|
||||
<dt>StreamStop</dt> <dd>Triggered after a stream has stopped</dd>
|
||||
<dt>XulmusEnter</dt> <dd>Triggered after Songbird starts</dd>
|
||||
<dt>XulmusLeavePre</dt><dd>Triggered before exiting Songbird, just before destroying each module</dd>
|
||||
<dt>XulmusLeave</dt> <dd>Triggered before exiting Songbird</dd>
|
||||
</dl>
|
||||
|
||||
<dl tag="autocommand-args" replace="autocommand-args">
|
||||
<dt><url></dt> <dd>The URL against which the event was selected.</dd>
|
||||
<dt><title></dt> <dd>The page, bookmark or download title.</dd>
|
||||
<dt><doc></dt> <dd>The document for which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
|
||||
<dt><tab></dt> <dd>The tab in which the event occurred. Only for <em>DOMLoad</em>, <em>PageLoad</em> and <em>PageLoadPre</em>.</dd>
|
||||
<dt><tags></dt> <dd>The tags applied to <url>. Only for <em>BookmarkAdd</em>.</dd>
|
||||
<dt><keyword></dt><dd>The keywords applied to the bookmark. Only for <em>BookmarkAdd</em>.</dd>
|
||||
<dt><icon></dt> <dd>The icon associated with <url>. Only for <em>BookmarkAdd</em>.</dd>
|
||||
<dt><size></dt> <dd>The size of a downloaded file. Only for <em>DownloadPost</em>.</dd>
|
||||
<dt><file></dt> <dd>The target destination of a download. Only for <em>DownloadPost</em>.</dd>
|
||||
<dt><state></dt> <dd>The new fullscreen state. Only for <em>Fullscreen</em>.</dd>
|
||||
<dt><name></dt> <dd>The color scheme name. Only for <em>ColorScheme</em>.</dd>
|
||||
<dt><view></dt> <dd>The new sequencer view. Only for <em>ViewChangePre</em> and <em>ViewChange</em>.</dd>
|
||||
<dt><track></dt> <dd>The new media track. Only for <em>TrackChangePre</em>, <em>TrackChange</em> and <em>Stream</em>.</dd>
|
||||
</dl>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
17
melodactyl/locale/en-US/browsing.xml
Normal file
17
melodactyl/locale/en-US/browsing.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<span replace="w"/>
|
||||
<span replace="W"/>
|
||||
<span replace=":wc"/>
|
||||
<span replace=":winon"/>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
4
melodactyl/locale/en-US/dactyl.dtd
Normal file
4
melodactyl/locale/en-US/dactyl.dtd
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
<!ENTITY appName "Xulmus">
|
||||
<!ENTITY hostapp "Songbird">
|
||||
|
||||
56
melodactyl/locale/en-US/gui.xml
Normal file
56
melodactyl/locale/en-US/gui.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<dl tag="dialog-list" replace="dialog-list">
|
||||
<dt>about</dt> <dd>About &dactyl.host;</dd>
|
||||
<dt>addons</dt> <dd>Manage Add-ons</dd>
|
||||
<dt>checkupdates</dt> <dd>Check for updates</dd>
|
||||
<dt>cleardata</dt> <dd>Clear private data</dd>
|
||||
<dt>cookies</dt> <dd>List your cookies</dd>
|
||||
<dt>console</dt> <dd>JavaScript console</dd>
|
||||
<dt>dominspector</dt> <dd>DOM Inspector</dd>
|
||||
<dt>downloads</dt> <dd>Manage Downloads</dd>
|
||||
<dt>jumpto</dt> <dd>Jump to a media item</dd>
|
||||
<dt>newsmartplaylist</dt><dd>Create a new smart playlist</dd>
|
||||
<dt>openfile</dt> <dd>Open the file selector dialog</dd>
|
||||
<dt>pagesource</dt> <dd>View page source</dd>
|
||||
<dt>places</dt> <dd>Places Organizer: Manage your bookmarks and history</dd>
|
||||
<dt>preferences</dt> <dd>Show &dactyl.host; preferences dialog</dd>
|
||||
<dt>printsetup</dt> <dd>Setup the page size and orientation before printing</dd>
|
||||
<dt>print</dt> <dd>Show print dialog</dd>
|
||||
<dt>saveframe</dt> <dd>Save frame to disk</dd>
|
||||
<dt>savepage</dt> <dd>Save page to disk</dd>
|
||||
<dt>searchengines</dt> <dd>Manage installed search engines</dd>
|
||||
<dt>selectionsource</dt> <dd>View selection source</dd>
|
||||
<dt>subscribe</dt> <dd>Add a new subscription</dd>
|
||||
</dl>
|
||||
|
||||
<item replace="sbcl">
|
||||
<tags>:dpcl :dpclose</tags>
|
||||
<spec>:dpcl<oa>ose</oa> <a>pane</a></spec>
|
||||
<description>
|
||||
<p>Close the specified display pane.</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item replace=":sbope">
|
||||
<tags>:dpope :dpopen :dp :dpane :dislplayp :dislplaypane</tags>
|
||||
<spec>:displaypane <a>pane</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Open the specified display pane. <a>pane</a> is any of "service
|
||||
pane left", "service pane bottom", "content pane bottom" or "right
|
||||
sidebar".
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
129
melodactyl/locale/en-US/intro.xml
Normal file
129
melodactyl/locale/en-US/intro.xml
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE document SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<document
|
||||
name="intro"
|
||||
title="&dactyl.appName; Intro"
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<logo/>
|
||||
|
||||
<h2 tag="intro">Introduction</h2>
|
||||
|
||||
<link topic="http://vimperator.org/%dactyl.name;">&dactyl.appName;</link>
|
||||
is a free media player add-on for &dactyl.host;, which
|
||||
combines the best features of the
|
||||
<link topic="http://cmus.sourceforge.net">CMus</link>
|
||||
music player and the
|
||||
<link topic="http://www.vim.org">Vim</link>
|
||||
text editor.
|
||||
|
||||
<warning tag="warning">
|
||||
To provide the most authentic CMus/Vim experience, the &dactyl.host; toolbar
|
||||
is hidden.
|
||||
If you really need it, type: <ex>:set guioptions+=T</ex> to get it back.
|
||||
If you don't like &dactyl.appName; at all, you can uninstall it by typing
|
||||
<ex>:extdelete &dactyl.appName;</ex> or <ex>:extdisable &dactyl.appName;</ex> to disable it.
|
||||
If you like it but can't remember the shortcuts, then press <k>F1</k> or
|
||||
<ex>:help</ex> to get this help window back.
|
||||
</warning>
|
||||
|
||||
<tags>author donation</tags>
|
||||
<p>
|
||||
&dactyl.appName; was written by
|
||||
<link topic="prathyushthota@gmail.com">Prathyush Thota</link>. If you
|
||||
appreciate my work on &dactyl.appName; and want to encourage
|
||||
me working on it more, you can either send me greetings, patches
|
||||
or make a donation:
|
||||
</p>
|
||||
|
||||
<pan><handle/></pan>
|
||||
|
||||
<p>
|
||||
Of course as a believer in free open source software, only make
|
||||
a donation if you really like &dactyl.appName; and the money
|
||||
doesn't hurt -- otherwise just use it, recommend it and like it
|
||||
:)
|
||||
</p>
|
||||
|
||||
<h2 tag="overview">Help topics</h2>
|
||||
|
||||
<ul>
|
||||
<li><link topic="starting">Starting &dactyl.appName;</link>: How &dactyl.appName; starts up, where it reads the config file... </li>
|
||||
<li><link topic="player">Player mode</link>: Interacting with the media player.</li>
|
||||
<li><link topic="browsing">Browsing</link>: Basic mappings and commands needed for a browsing session (how to open a web page or go back in history).</li>
|
||||
<li><link topic="buffer">Buffer</link>: Operations on the current document like scrolling or copying text.</li>
|
||||
<li><link topic="cmdline">Command-line mode</link>: Command-line editing.</li>
|
||||
<li><link topic="insert">Insert mode</link>: Insert-mode editing.</li>
|
||||
<li><link topic="options">Options</link>: A description of all options.</li>
|
||||
<li><link topic="pattern">Text search commands</link>: Searching for text in the current buffer.</li>
|
||||
<li><link topic="tabs">Tabs</link>: Managing your tabbed browsing session.</li>
|
||||
<li><link topic="hints">Hints</link>: Selecting hyperlinks and other page elements.</li>
|
||||
<li><link topic="map">Key mappings, abbreviations, and user-defined commands</link>: Defining new key mappings, abbreviations and user commands.</li>
|
||||
<li><link topic="eval">Expression evaluation</link>: Executing JavaScript.</li>
|
||||
<li><link topic="marks">Marks</link>: Using bookmarks, QuickMarks, history and local marks.</li>
|
||||
<li><link topic="repeat">Repeating commands</link>: Using macros to repeat recurring workflows.</li>
|
||||
<li><link topic="autocommands">Automatic commands</link>: Automatically executing code on certain events.</li>
|
||||
<li><link topic="print">Printing</link>: Printing pages.</li>
|
||||
<li><link topic="gui">&dactyl.appName;'s GUI</link>: Accessing &dactyl.host; menus, dialogs and the display panels.</li>
|
||||
<li><link topic="styling">Styling the GUI and web pages</link>: Changing the styling of content pages and &dactyl.appName; itself.</li>
|
||||
<li><link topic="message">Error and informational messages</link>: A description of messages and error messages.</li>
|
||||
<li><link topic="developer">Developer information</link>: How to write docs or plugins.</li>
|
||||
<li><link topic="various">Various commands</link>: Other help which didn't fit into any other category.</li>
|
||||
<li><link topic="index">Index</link>: An index of all commands and options.</li>
|
||||
</ul>
|
||||
<p>
|
||||
You can also jump directly to the help of a specific command
|
||||
with <ex>:help o</ex> or <ex>:help :set</ex>.
|
||||
</p>
|
||||
|
||||
<h2 tag="features">Features</h2>
|
||||
|
||||
<!-- TODO: make Xulmus specific -->
|
||||
<ul>
|
||||
<li>Vim-like keybindings (<k>h</k>, <k>j</k>, <k>k</k>, <k>l</k>, <k>gg</k>, <k>G</k>, <k>0</k>, <k>$</k>, <k>ZZ</k>, <k name="C-f"/>, etc.)</li>
|
||||
<li>Ex commands (<ex>:quit</ex>, <ex>:open www.foo.com</ex>, ...)</li>
|
||||
<li>Tab completion available for all commands with support for "longest" matching when set in 'wildmode'</li>
|
||||
<li>Hit-a-hint like navigation of links (start with <k>f</k> to follow a link)</li>
|
||||
<li>Advanced completion of bookmark and history URLs (searching also in title, not only URL)</li>
|
||||
<li>Vim-like statusline with a Wget-like progress bar</li>
|
||||
<li>Minimal GUI (easily hide useless menubar and toolbar with <ex>:set guioptions=</ex>)</li>
|
||||
<li>Ability to <ex>:source</ex> JavaScript files, and to use a [a]~/.xulmusrc[a] file with syntax highlighting if you install http://code.google.com/p/pentadactyl-labs/issues/detail?id=50[xulmus.vim]</li>
|
||||
<li>Easy quick searches (<ex>:open foo</ex> will search for "foo" in google, <ex>:open ebay terminator</ex> will search for "terminator" on ebay) with support for &dactyl.host; keyword bookmarks and search engines</li>
|
||||
<li>Count supported for many commands (<em>3</em><k name="C-o"/> will go back 3 pages)</li>
|
||||
<li>Beep on errors</li>
|
||||
<li>Marks support (<k>m</k><em>a</em> to set mark a on a web page, <k>'</k><em>a</em> to go there)</li>
|
||||
<li>QuickMarks support (quickly go to previously marked web pages with <k>go</k><a>a-zA-Z0-9</a>)</li>
|
||||
<li><ex>:map</ex> and <ex>:command</ex> support (and feedkeys() for script writers)</li>
|
||||
<li><ex>:time</ex> support for profiling</li>
|
||||
<li>Move the text cursor and select text with Vim keys and a Visual mode</li>
|
||||
<li>External editor support</li>
|
||||
<li>Macros to replay key strokes</li>
|
||||
<li>AutoCommands to execute actions on certain events</li>
|
||||
<li>A comprehensive help system, explaining all commands, mappings and options</li>
|
||||
</ul>
|
||||
|
||||
<h2 tag="contact">Contact</h2>
|
||||
<p>
|
||||
Please send comments/bug reports/patches to the mailing list,
|
||||
where we will properly answer any questions. You can also join
|
||||
the
|
||||
<link topic="irc://irc.oftc.net/pentadactyl">#pentadactyl</link>
|
||||
IRC channel on
|
||||
<link topic="http://www.oftc.net/">OFTC</link> or check the
|
||||
<link topic="http://code.google.com/p/dactyl/w/list?q=label%3Aproject-&dactyl.name;">Wiki</link>
|
||||
for
|
||||
<link topic="http://code.google.com/p/dactyl/wiki/FAQ">
|
||||
frequently asked questions (FAQ)</link>.
|
||||
Make sure, you have read the
|
||||
<link topic="http://dactyl.googlecode.com/hg/xulmus/TODO">TODO</link>
|
||||
file first, as we are aware of many things which can be improved
|
||||
when we find time for it or receive patches.
|
||||
</p>
|
||||
|
||||
</document>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
327
melodactyl/locale/en-US/player.xml
Normal file
327
melodactyl/locale/en-US/player.xml
Normal file
@@ -0,0 +1,327 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE document SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<document
|
||||
name="browsing"
|
||||
title="&dactyl.appName; Browsing"
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<h1 tag="player-mode player">Player mode</h1>
|
||||
<toc start="2"/>
|
||||
|
||||
<p>
|
||||
The following features apply to Player mode which is activated when the
|
||||
media tab has focus.
|
||||
</p>
|
||||
|
||||
<h2 tag="playing-tracks">Playing tracks</h2>
|
||||
|
||||
<item>
|
||||
<tags>p_x :playerp :playerplay</tags>
|
||||
<spec>:playerp<oa>lay</oa></spec>
|
||||
<spec>x</spec>
|
||||
<description>
|
||||
<p>
|
||||
Play the current track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_z :playerpr :playerprev</tags>
|
||||
<spec>:playerpr<oa>ev</oa></spec>
|
||||
<spec>z</spec>
|
||||
<description>
|
||||
<p>
|
||||
Play the previous track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_b :playern :playernext</tags>
|
||||
<spec>:playern<oa>ext</oa></spec>
|
||||
<spec>b</spec>
|
||||
<description>
|
||||
<p>
|
||||
Play the next track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_c :playerpa :playerpause</tags>
|
||||
<spec>:playerpa<oa>use</oa></spec>
|
||||
<spec>c</spec>
|
||||
<description>
|
||||
<p>
|
||||
Pause/unpause the current track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_v :playerps :playerstop</tags>
|
||||
<spec>:playerps<oa>top</oa></spec>
|
||||
<spec>v</spec>
|
||||
<description>
|
||||
<p>
|
||||
Stop playing the current track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_x</tags>
|
||||
<spec>x</spec>
|
||||
<description>
|
||||
<p>
|
||||
Toggle shuffle mode.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_r</tags>
|
||||
<spec>r</spec>
|
||||
<description>
|
||||
<p>
|
||||
Toggle repeat mode.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_i</tags>
|
||||
<spec>i</spec>
|
||||
<description>
|
||||
<p>
|
||||
Select the currently playing track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="queue queueing">Queueing tracks</h2>
|
||||
|
||||
<item>
|
||||
<tags>p_Q :qu :queue</tags>
|
||||
<spec>:qu<oa>eue</oa> <a>artist</a> <oa>album</oa> <oa>track</oa></spec>
|
||||
<spec>Q</spec>
|
||||
<description>
|
||||
<p>
|
||||
Queue tracks by artist/album/track. If only <a>artist</a> is
|
||||
specified then all tracks for that artist are played in album
|
||||
order. If <oa>album</oa> is also specified then all tracks for that
|
||||
album are played. A specific track can be specified with
|
||||
<oa>track</oa>.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="filter filtering">Filtering the library</h2>
|
||||
|
||||
<item>
|
||||
<tags>p_f :f :filter</tags>
|
||||
<spec>:f<oa>ilter</oa> <a>keywords</a></spec>
|
||||
<spec>f</spec>
|
||||
<description>
|
||||
<p>
|
||||
Filter and show the tracks as a view. The tracks are filtered by
|
||||
the <a>keywords</a> provided as arguments. This text search applies
|
||||
over the default filter properties, namely: Genre, Artist, Album
|
||||
and Track.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="seeking">Seeking to a track position</h2>
|
||||
|
||||
<item>
|
||||
<tags><![CDATA[p_<Left> p_h]]></tags>
|
||||
<spec><oa>count</oa>h</spec>
|
||||
<description>
|
||||
<p>
|
||||
Seek +10s.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags><![CDATA[p_<Right> p_l]]></tags>
|
||||
<spec><oa>count</oa>l</spec>
|
||||
<description>
|
||||
<p>
|
||||
Seek -10s.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags><![CDATA[p_<S-Left> p_H]]></tags>
|
||||
<spec><oa>count</oa>H</spec>
|
||||
<description>
|
||||
<p>
|
||||
Seek +1m.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags><![CDATA[p_<S-Right> p_L]]></tags>
|
||||
<spec><oa>count</oa>L</spec>
|
||||
<description>
|
||||
<p>
|
||||
Seek -1m.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>:see :seek</tags>
|
||||
<spec>:see<oa>k</oa> <a>[HH:]MM:SS]</a></spec>
|
||||
<spec>:see<oa>k</oa> +<a>time[hms]</a> | -<a>time[hms]</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Seek to an absolute or relative position in a track. The position
|
||||
can be given in seconds (s), minutes (m), or hours (h). If the unit
|
||||
is not specified then seconds is assumed. The position is absolute
|
||||
unless the value is prefixed with "-" or "+".
|
||||
</p>
|
||||
<p>
|
||||
Positions may also be specified in <a>[HH:]MM:SS</a> format.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="volume">Adjusting the volume</h2>
|
||||
|
||||
<item>
|
||||
<tags>p_+ p_=</tags>
|
||||
<spec>+</spec>
|
||||
<spec>=</spec>
|
||||
<description>
|
||||
<p>
|
||||
Increase volume by 5% of the maximum.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_-</tags>
|
||||
<spec>-</spec>
|
||||
<description>
|
||||
<p>
|
||||
Decrease volume by 5% of the maximum.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>:vol :volume</tags>
|
||||
<spec>vol<oa>[ume]</oa> <a>value</a></spec>
|
||||
<spec>vol<oa>[ume]</oa> +<a>value</a> | -<a>value</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Set the player volume. <a>value</a> can be an absolute value
|
||||
between 0 and 100% or a relative value if prefixed with "-" or "+".
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="playlists">Managing playlists</h2>
|
||||
|
||||
<item>
|
||||
<tags>:load</tags>
|
||||
<spec>:load <oa>playlist</oa></spec>
|
||||
<description>
|
||||
<p>
|
||||
Load <a>playlist</a>. If no playlist is specified then the main
|
||||
library view is loaded.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="media-view view">Changing media views</h2>
|
||||
|
||||
<item>
|
||||
<tags>:mediav :mediaview</tags>
|
||||
<spec>:mediav<oa>ew</oa> <a>view</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Change the media view to <a>view</a>. This can only be run when the
|
||||
media tab is the current tab.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="search">Search commands</h2>
|
||||
|
||||
<item>
|
||||
<tags>p_/</tags>
|
||||
<spec>/<a>pattern</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Search forward for a track matching <a>pattern</a> in the visible
|
||||
media view.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<!--
|
||||
<item>
|
||||
<tags>p_?</tags>
|
||||
<spec>?<a>pattern</a></spec>
|
||||
<description>
|
||||
<p>
|
||||
Search backwards for a track matching <a>pattern</a> in the visible
|
||||
media view.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
-->
|
||||
|
||||
<item>
|
||||
<tags>p_n</tags>
|
||||
<spec>n</spec>
|
||||
<description>
|
||||
<p>
|
||||
Find the next track. Repeats the last search. If the search hits
|
||||
BOTTOM of the view, it continues from TOP.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<tags>p_N</tags>
|
||||
<spec>N</spec>
|
||||
<description>
|
||||
<p>
|
||||
Find the previous track. Repeats the last search in the opposite
|
||||
direction. If the search hits TOP of the view, it continues from
|
||||
BOTTTOM.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
<h2 tag="rating">Rating tracks</h2>
|
||||
|
||||
<item>
|
||||
<tags><![CDATA[p_<C-5> p_<C-4> p_<C-3> p_<C-2> p_<C-1> p_<C-0>]]></tags>
|
||||
<spec><![CDATA[<C-0>]]></spec>
|
||||
<spec><![CDATA[<C-1>]]></spec>
|
||||
<spec><![CDATA[<C-2>]]></spec>
|
||||
<spec><![CDATA[<C-3>]]></spec>
|
||||
<spec><![CDATA[<C-4>]]></spec>
|
||||
<spec><![CDATA[<C-5>]]></spec>
|
||||
<description>
|
||||
<p>
|
||||
Rate the current track with N stars.
|
||||
</p>
|
||||
</description>
|
||||
</item>
|
||||
|
||||
</document>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
16
melodactyl/locale/en-US/tabs.xml
Normal file
16
melodactyl/locale/en-US/tabs.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="chrome://dactyl/content/help.xsl"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://dactyl/content/dactyl.dtd">
|
||||
|
||||
<overlay
|
||||
xmlns="http://vimperator.org/namespaces/liberator"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<span replace=":window"/>
|
||||
<span replace=":u"/>
|
||||
<span replace=":undoa"/>
|
||||
|
||||
</overlay>
|
||||
|
||||
<!-- vim:se sts=4 sw=4 et: -->
|
||||
BIN
melodactyl/skin/icon.png
Normal file
BIN
melodactyl/skin/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 465 B |
Reference in New Issue
Block a user