Hi there,
Firstly, in order to get a grasp of how hotkeys and actions work, I'd recommend going through SampleScripts/hotkeyAction and possibly SampleScripts/refreshSkinShortcut, as well as just generally examining actions.js. Secondly, if you don't yet know how to create and package an addon, the
Getting Started guide can be helpful.
Hotkeys and context menus are always associated with an
action. The text of a context menu item / name of the hotkey is given the action's
title, and when the menu item is clicked / hotkey is pressed, its
execute function is called. So all of the business logic for your special hotkey will go into your action's
execute parameter.
For rating the currently playing song, you can look in actions.js for
actions.ratePlaying1 through
actions.ratePlaying5. (If you do a Ctrl+F search, just search for "ratePlaying". They're made with
object literals, but you don't have to worry about that detail. Note that the
window.uitools.ratePlaying() function is passed a number from 0 to 100, not 0 to 5 (Also note that "unknown" ratings are given -1).
For skipping to the next song, that is simple. Just use
app.player.nextAsync(). For more details on the player, see here:
https://www.mediamonkey.com/docs/api/cl ... layer.html
To skip forward in the song, you can then use the
app.player.seekMSAsync method. Please note the
Async keyword in those two methods. I can take you down a long rabbit hole explaining what asynchronous methods are and how they work, how to use Promises and async/await — but the jist is that you need to do a little bit of extra work if you want to make sure the player changes seek position
after it's finished changing tracks. (If you do want to go down the rabbit hole, start here:
https://developer.mozilla.org/en-US/doc ... ynchronous)
If you do the following, there is
no guarantee that the player will do what you asked in the correct order.
Code: Select all
app.player.nextAsync();
app.player.seekMSAsync(5000);
Imagine you have an intern who's making you coffee. You tell him, "Go fill the kettle, turn it on, then pour the water" then let him go do it. He fills the kettle then turns it on, but before waiting for the water to boil, he starts pouring the cold water into the mug.
If you're writing code and you want your water to be boiled
before your intern pours the water, you have to tell him to wait before pouring the water. There are many ways to do this in code, but the simplest is by turning your function into an
async function, and using the
await keyword. (
More info here)
Now, after testing this myself, it seems like
awaiting app.player.nextAsync() isn't enough to make it work, so I'd recommend putting your seekMSAsync() in a timer. 100 ms seems to do the trick.
All together, here's a working sample for an action's
execute function:
Code: Select all
async function() {
uitools.ratePlaying(80);
await app.player.nextAsync();
requestTimeout(async function () {
if (app.player.trackLengthMS > 10000) {
await app.player.seekMSAsync(5000);
}
}, 100);
}
I put that
if block in there just in case you have a song that's super short, in which case you probably wouldn't want it to skip.
If you want to add multiple hotkeys, one for each star, I'd recommend putting that nextAsync() and seekMSAsync() business into a single function (i.e. something like "skipAndSeek()"), and call it from each of your separate actions. That way, you don't have to deal with lots of copy-and-paste.
Good luck!
(P.S. I'd recommend using a debug build, so you can easily open the JS console and run tests/debug stuff from there. Also the pack-mmip addon can be useful:
https://github.com/JL102/pack-mmip)