NowPlaying needs further work before it's ready

[ ] Should use the NPconnection->acquire() call and wait for the signal before playing.
[ ] Should listen for Revoked signal and stop playback if received.
[ ] Do not hardcode any file paths, or default audio streams.
[ ] Should accept more metadata properties than the 3 given now.
[ ] Should take an icon for the media being played
[ ] Should use the Fancy OverlayStyle always (Plain is default and shows nothing valuable).

Some questions I have at the moment:
- Are we supposed to allow the user to specify actions wrt to a signal?
Story implies we hard-code, but https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html implies we don't.
- How do we specify signal handling normally then? Are Cordova slots/signals replacing internal npc handling?
- How about play, stop, pause - because we hard-coded behavior, no need signal/slot?
  Q: How do WE specify what acquire does in C++ (not qml)? Signals and slots? Then user who uses our plugin won't? Shoulnd't user specify some kind of signals slots thing?

Initial story sizing and prioritization:
1. ~7 Should use the NPconnection->acquire() call and wait for the signal before playing.
-> New function that just emits NPconnection->acquire() signal
-> New slot it to acquire()
-> mp->play()
npc->setMediaState(bb::multimedia::MediaState::Started);
npc->setMetaData(mp->metaData());
2. ~5 Should listen for Revoked signal and stop playback if received.
    -> New function that just emits NPconnection->revoke() signal
    -> New slot it to revoke()
    -> mp->stop()

3. ~1 Do not hardcode any file paths, or default audio streams.
    - How is the NowPlaying plugin intended to provide access to stored media? Where would the media be? (https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html - assets... right? Or media player songs added by user? If the app accesses files there, how can I specify them anymore thru plugin?)

4. ~1 Should accept more metadata properties than the 3 given now.
    - Create a test function to see json values set?
    - Are we checking whether individual json values are set?

5. ~1 Should take an icon for the media being played
    - Need to know how NPconnection works first? Get sample?

6. ~1 Should use the Fancy OverlayStyle always (Plain is default and shows nothing valuable).
    - https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html
    *- what is overlay, still? https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html
        -> play with controls, music controls. That pops out with metadata.

I've been working to understand the functional requirements of NowPlaying, but it isn't yet clear to me. This is my current understanding:
QML Example:

User can specify when npc.acquire(), npc.revoke(), mp.play(), mp.pause(), mp.stop() called (main.qml in https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html)
Users specify handlers - they do so by using some (predefined somewhere?) signals: onAcquired, onRevoked, onPause, onPlay, onStop

C++ Example:

User can specify when npc.acquire(), npc.revoke(), mp.play(), mp.pause(), mp.stop() called (main function)
Don't see how users specify handlers.
Q: How are users intended to interact with the plugin?

NowPlaying Cordova:

User can specify when npc.acquire(), npc.revoke(), mp.play(), mp.pause(), mp.stop() called (called in application's index.js)
Don't see how users specify handlers.
Q: What exactly do we want? How are users intended to interact with the plugin?
-> The stories sound like we hard-code the signal handlers.
-> You mentioned the person before created the wrong thing. What is it that we really want? From my understanding, we don't need play, stop, pause, etc. (these belong to music player - do we have another cordova module for this), just native NowPlaying's acquire, revoke.
-> Why are we defining our own signals and slots in cordova NowPlaying? Shouldn't we use native NowPlaying's internal signals and slots? Or is defining our own signals and slots really how C++ is meant to interact with the native NowPlaying (By ignoring the internal signals and slots and instead using our own method of communication)?

It may be important to note that this Plugin's primary goal is not to play audio - there is already a standard HTML5 way to play audio. The goal here is to allow audio to be played while being a good citizen on the system, and to interact with the overlay feature.
So, we want to provide an API where the user (app developer) can "request" playback of their media, and when the service is acquired, playback starts with the source URL, metadata, and icon, that the user requested. Options to enable or disable Next/Previous buttons should be included.
The user should be able to receive callbacks on the various events that can happen: Acquire, Revoke, Play, Pause, Stop, Next, Previous. The first five will be primarily notification in case the application wishes to update some UI to reflect that state. The Next and Previous events would be something the application would respond to by setting new media details.
Accordingly, there should be trackChange API, which doesn't do the Acquire again, but sets the new icon, metadata, url, and calls the trackChange slot to notify the Now Playing Connection.
Since the app will almost certainly have it's own UI for playback, we'll also need APIs for Play, Pause, Stop, which will pass through to the enclosed MediaPlayer object.
It may be useful for debugging to have methods to return the current media playback state, and if the connections is "acquired' or "preempted".

The previous developer thought it was useful to define their own signals and slots in the plugin. It worked for them, but it's not the only way to do this. I've tried to define above what the API should provide to a user of the plugin - the implementation details don't need to be apparent at that level. An app developer is unlikely to know or care about Signals and Slots or that the media player and now playing connection are separate objects for example.

Edited the API to use "resume" instead of "play" as it's really the opposite of "pause".
One other thing I was thinking is that we should only allow nextEnabled or prevEnabled to be set true if there is a callback defined for them.

Native functionality (as I imagine it to be):
Underlying logic:
    - Each media has a source and a logical (not physical) media notification area associated with it. Events associated with a media are sent and handled in its media notification area.
    - There is underlying logic for designating a "main" active media source between several. This is abstracted away from all media notification areas.
    - There is a volume overlay widget that is associated with the media notification area of the "main" active media source. The logic (JS), structure and presentation (HTML, CSS)... everything for the widget wrt the media notification area, the media source, etc. is handled by the OS.
    - There is underlying logic for playing/stopping/pausing media when an app is closed, sent to the background, or sent to the foreground. This is abstracted away from all media notification areas. It is done through connection priorities (https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html see that section.)
    - There is underlying logic for how playing/stopping/pausing media causes the hardware to do so. This is abstracted away from all media notification areas.
    - Has concept of signal and slots: http://developer.blackberry.com/native/documentation/dev/signals_slots/ Signals are handled by slots.

APIs:
    MediaPlayer: An instance of this class can:
        - control a single media source (up to 8 instances can play simultanesouly.) by sending a play/stop/pause command to the hardware.
    NowPlayingConnection: An instance of this class can:
        - call acquire()/revoke() to gain exclusive system-wide access to the media notification area for the currently "main" active media source.
        - when access is acquired to the media notification area, it can display/hide and modify the data in its volume overlay from specified data.
        - enable/disable the next/previous buttons on the volume overlay of the media notification area.
        - handle native signals for play/pause/stop/acquired/revoked which can be attached to a slot
        - return the current media playback state (stopped, playing, paused), whether the media notification area is acquired, and whether the connection to the media notification area is preempted by a higher priority connection (https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html under connection priority).
    NowPlayingController: An instance of this class can:
        - control the media source that is acquired by an instance of NowPlayingConnection by sending a play/stop/pause command to the hardware.

Desired functionality:
Plugin providing a API between JS and the native APIs, which will allow a
developer to:
1. Play audio "while being a good citizen on the system"
2. Interact with the overlay feature

User Stories:
-------------
(Note: play is intitial "play", as opposed to resume)

- "As a developer, I want API to acquire(play)/revoke(stop) system-wide access to the media notification area for the currently "main" active media source."
    - NowPlayingConnection.acquire()/revoke().
    - Update the current media player state with NowPlaying for stop with setMediaState(Stopped)

- "As a developer, I want API to change the track being played."
    - NowPlayingConnection.trackChange().
    - Ensure you don't call NowPlayingConnection.acquire(), in case you intentded to reuse that API. Can create helper function instead.

- "As a developer, I want API to resume/pause the currently "main" active media (that was started with acquire)."
    - MediaPlayer.play()/pause().
    - Update the current media player state with NowPlaying.setMediaState(Stated/Paused)

- "As a developer, I want to be able to specify the music I want to play when I acquire the media notification area or change the track."
    - Basically, call MediaPlayer.play()/pause()/stop().
    - The user specifies music through a URL (MediaPlayer.setSourceUrl()) or through the device filesystem (need to find out how)

- "As a developer, I want to be able to specify metadata for the music I want to play when I acquire the media notification area or change the track."
    - Basically, call NowPlayingConnection.setMetaData().
    - Do more than just the three current ones (title, artist, album) http://developer.blackberry.com/native/reference/cascades/bb__multimedia__metadata.html

- "As a developer, I want to be able to specify the icon for the music I want to play when I acquire the media notification area or change the track."
    - NowPlayingConnection->setIconUrl()

- "As a developer, when I acquire the media notification area or change the track, I want it to play the music specified."

- "As a developer, when I acquire the media notification area or change the track, I want the volume overlay to be displayed with the metadata and icon specified."
    - NowPlayingConnection->setOverlayStyle(OverlayStyle::Fancy)

- "As a developer, I want API to enable/disable the next/previous buttons of the volume overlay"
    - NowPlayingConnection->setNext/PreviousEnabled(bool)
    - Assert callback is specified when bool is true.

- "As a developer, I want API to receive callbacks from Acquire(play), Revoke(stop), Resume, Pause, Stop, Error, Next, Previous so that I can do actions like updating UI (first six) or set new media details (last two: Next, Previous) to reflect the state of the app after the function is done executing."
    - See https://github.com/blackberry/WebWorks-Community-APIs/tree/master/BB10/Memory for how SendPluginEvent works: "If you want the native code to be able to trigger an event on the JavaScript side then you'll need to call the SendPluginEvent function."
    - Example code path: setMetaButtonClick()

- "As a developer, I want API to return the current media playback state and if the connection is acquired or preempted"
    - NowPlayingConnection.mediaState(),NowPlayingConnection.isAcquired(), NowPlayingConnection.isPreempted()

- "As a developer, I want API that will allow me to define callback handlers for when my app gets preempted or is no longer preempted."
    - "With no audioManagerHandle specified, the now playing service will automatically call [emit] play() when no longer preempted. If an audioManagerHandle is specified, the now playing service will only call [emit] play() if the audio routing has not changed to a more public device while preempted." (http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#function-play). I think this play signal is the one for NowPlayingConnection (http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#function-play), and can be tied to a slot. We just have to provide an API function which requires a callback function (that we should assert must be specified?) for this slot, which will execute when the play signal occurs, i.e. when the media is no longer preempted.
        - I am not sure this is feasibly implementable though becauase idk if we can catch/handle/slot the emitted play() signal. One way to find out is to create an app and see how preempting behaves, and see if we can catch the signal and slot it.
    - I'm assuming pause() signal is emitted when we are preempted (I didn't find this specified in the native references though) and that we can do the same as for the play() signal.

To ask:
    - What do you mean by "Error" event? ("The user should be able to receive callbacks on the various events that can happen: Acquire, Revoke, Play, Pause, Stop, _Error_, Next, Previous.")

    - "[The trackChange API] should also include the options for enabling and disabling the Next/Previous buttons, as that would likely happen at this time."? Do you mean because e.g. we might hit the last track or something, we should ensure next/previous button enabling/disabling can be specified as a callback?

    - Clarify syntax for API for requestPlayback: Are you proposing to use a JSON parameter to specify how the JSON argument must be formatted (is that valid? I am unfamiliar with this syntax)? Are you are proposing to specify acquired as a named function callback paramter that must be specified in the function JSON argument (is that valid syntax, with the {...}?)? Is this intended to be a variable argument list of callbacks?

    - Clarify syntax for API for stop, resume, pause, currentState: These will take callbacks as parameters too, right?

Storyboard of example app using the NowPlaying plugin.

Play -> Pause -> Resume -> Pause -> Resume -> Stop
Play -> trackChange -> Stop
Preempted -> ?

Here's some information on the file structure with respect to the architecture of this plugin.
The plugin is in "plugin".
"sample" is a sample app that uses the plugin.
nowplaying_build.sh automatically creates another app called "debug1" and adds the plugin to it. It then uses the "sample" app as boilerplate code to copy into the newly created "debug1" app. The script then adds blackberry10 as a platform, and does a cordova run. You can use this script to run and test changes, because the first thing it always does is remove the "debug1" app.
Below, you'll see the layers wrt the drawing Tim made on the whiteboard during the code sprint. The first file listed in each layer is what you need to change (I like to open the non-.cpp files in order side by side on my editor, then the .cpp files in order side-by-side on momentics). If I remember correctly, the second file (second "->") is where the file is copied to when you add the plugin or when it gets copied from the "sample" app to the newly created "debug1" app; the third file is where the file is copied to when you add blackberry10 as a platform or is what the file is compiled to (a library).
App "main" html: sample/www/index.html
-> debug1/www/index.html
-> debug1/platforms/blackberry10/www/index.html
App "main" js: sample/www/js/index.js
-> debug1/www/js/index.js
-> debug1/platforms/blackberry10/www/js/index.js
App: plugin/www/client.js
-> debug1/plugins/com.blackberry.community.nowplaying/www/client.js
-> debug1/platforms/blackberry10/www/plugins/com.blackberry.community.nowplaying/www/client.js
Cordova: debug1/platforms/blackberry10/platform_www/cordova.js
Controller: plugin/src/blackberry10/index.js
-> debug1/plugins/com.blackberry.community.nowplaying/src/blackberry10/index.js
-> debug1/platforms/blackberry10/native/device/chrome/plugin/com.blackberry.community.nowplaying/index.js
TemplateJS: plugin/src/blackberry10/native/src/NowPlaying_js.cpp
-> debug1/plugins/com.blackberry.community.nowplaying/src/blackberry10/native/src/NowPlaying_js.cpp
-> debug1/platforms/blackberry10/native/device/plugins/jnext/libNowPlaying.so
TemplateNDK: plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp
-> debug1/plugins/com.blackberry.community.nowplaying/src/blackberry10/native/src/NowPlaying_ndk.cpp
-> debug1/platforms/blackberry10/native/device/plugins/jnext/libNowPlaying.so

We can divided the user stories into these 6 main items (tried to make them as mutually exclusive as possible):

Implement function to return state: media playback state and connection acquired or preempted.
Implement acquire, revoke, resume, pause, stop, error, next previous using native MediaPlayer API.
Implement callbacks into JS layer for acquire, revoke, resume, pause, stop, error, next previous.
Implement handlers for when the app gets premempted or is no longer preempted (needs further investigation).
Implement functions for specifying metadata, icon, and music to play.
Implement functions to acquire/revoke media notification area. Prepare volume overlay over media notification area.
a. Populate it with metadata, icon, and music.
b. Provide functionality to enable/disable the next/previous buttons of volume overlay.

Answers to your questions from earlier:

What do you mean by "Error" event? ("The user should be able to receive callbacks on the various events that can happen: Acquire, Revoke, Play, Pause, Stop, Error, Next, Previous.")

In the course of operation, an error might be encountered - like media not being found, low level issues from the native API/hardware, attempts to play without setting media, etc. There should be a way to get those messages.
- "[The trackChange API] should also include the options for enabling and disabling the Next/Previous buttons, as that would likely happen at this time."? Do you mean because e.g. we might hit the last track or something, we should ensure next/previous button enabling/disabling can be specified as a callback?

I think that should be a property set on the input when calling trackChange. When you set the track, that would be when you know if you are able to handle a Next or Previous request. It could be that you've reached the end of the list you were playing from, or you are starting a new list, or perhaps you are playing a single track with no other tracks to switch to. It seems less likely that the value would change after starting to play a track.
- Clarification on syntax for API for requestPlayback: Are you proposing to use a JSON parameter to specify how the JSON argument must be formatted (is that valid? I am unfamiliar with this syntax)? Are you are proposing to specify acquired as a named function callback paramter that must be specified in the function JSON argument (is that valid syntax, with the {...}?)? Is this intended to be a variable argument list of callbacks?

With JavaScript you typically document the properties you are expecting, and you can check for them and return an error if something is missing or incorrectly formatted. What I'm suggesting is the format of that object and the property names that you would use. The { ... } parts are what a developer would supply. With JavaScript you can specify the name of a function or define it inline.
- Clarification on syntax for API for stop, resume, pause, currentState: These will take callbacks as parameters too, right?

I think stop, resume, and pause would likely be simple methods that take no parameters and return nothing. The output of anything that happens with them would likely fall into one of the callbacks defined earlier.
currentState could return a JSON object directly, or through a callback.

"I think that should be a property set on the input when calling trackChange. When you set the track, that would be when you know if you are able to handle a Next or Previous request. It could be that you've reached the end of the list you were playing from, or you are starting a new list, or perhaps you are playing a single track with no other tracks to switch to. It seems less likely that the value would change after starting to play a track."

I just want to clarify what you mean by trackChange API. Stuff that have to do with changing tracks (next/previous actions) are just part of the overall NowPlaying API, right? "trackChange" is just a name associated with those set of actions?
So the proposal is for next/previous API to have optional parameters to enable/disable next/previous buttons on the overlay? Just to clarify, couldn't the user could just call these right after calling the next/previous API? So this is just for convenience?

"I think stop, resume, and pause would likely be simple methods that take no parameters and return nothing. The output of anything that happens with them would likely fall into one of the callbacks defined earlier."

I thought that they needed callbacks to update the UI?

trackChange is one of the methods on the native NowPlayingConnection API. It's intended to notify the system that the current playing track has changed.
From the perspective of a developer using the plugin, I think that changing the track and starting to play music the first time share a large amount of overlap. That's why I defined it as I did above. The first time you use the plugin, you'll need to define some callback methods, in addition to the track details.
I think that next and previous would not be APIs on this plugin, but that you can set a callback function for when these events happen. For example, you start playing music with the API and have enabled next and previous in that call, and set a callback function for next and previous events. Then the user taps on the "next" button on the Overlay. Your callback function for the next event is called, and you do whatever application logic you would like, and at some point call the trackChange method, providing the new media you would like to play.
So, I don't think there should be next or previous methods on the API and I don't think there should be specific APIs for enabling and disabling the next and previous buttons on the overlay. That ability should be included in the requestPlayback and trackChange methods only.
For a stop/resume/pause method call, it will start from the application code. For example, an application is playing music with this plugin, and the user taps on an application button to pause the music. The application then calls the "pause" method on the plugin. Back when they first started playback, they defined callback methods for the Pause event. That callback gets fired when the event is received and then they can update their UI, knowing that the music has actually paused, not just that the user tapped the button.
So they are using callbacks, but we are not forcing them to define one every time they call a method, just once at the start of using the plugin, because those events can happen at many different times and through different paths.

So earlier I was talking about finally understanding signals and slots. This made
me realize that how Tim's proposed API is supposed to work, now.
Here is the API. I think it should be in NowPlaying/plugin/www/client.js:
    requestPlayback: function(
        {
            songURL = "/songURL",
            iconURL = "/iconURL",
            metadata: { Title = "/Title", Artist = "/Artist", Album = "/Album" },
            nextEnabled = true,
            prevEnabled = true,
            callbacks: {
                play = function() {},
                stop = function() {},
                pause = function() {},
                resume = function() {},
                error = function() {},
                next = function() {},
                previous = function() {}
        }
    ) { ... },
     trackChange: function (
         {
            songURL = "/songURL",
            iconURL = "/iconURL",
            metadata: { Title = "/Title", Artist = "/Artist", Album = "/Album" },
            nextEnabled = true,
            prevEnabled = true,
         }
     ) { ... },
     stop: function() { ... },
     resume: function() { ... },
     pause: function() { ... },
     getState: function() { ... }

So we need to refactor to this API.
In the native code, we connect signals to slots in this manner: (This isn't how it looks like in the code atm, but I am showing this here for the purposes of discussion.)
    NowPlayingCordova/src/NowPlaying_ndk.hpp:
    class NowPlayingNDK : public QObject {
            Q_OBJECT
            ...
            public:
                ...
                QObject::connect(
                    this,
                    SIGNAL(bb::multimedia::NowPlayingConnection::pause()),
                    this,
                    SLOT(pause())
                    );
                ...
                public slots:
                    void pause();
            ...
    }

mp->pause() should trigger the signal bb::multimedia::NowPlayingConnection::pause() (according to http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#function-acquired). The slot pause() is the function we provide to handle what happens when we hit the signal. We connect the two. So the slot pause() should, at some point, be provided with a callback to the javascript native code.
Tim's point in our discussions was that this callback should be provided as the very first thing a developer using this plugin would do. This happens when the developer calls requestPlayback in the API. He/she provides the callback functions for all of resume, stop, pause, etc. Then in the native code, requestPlayback will set these callbacks as the callbacks that correspond to each slot. This way, when the pause signal is emitted and the pause() slot is executed, it will use that callback.
Essentially, e.g. for pause(), there will be three functions:
NowPlayingNDK::NowPlayingPause(): which will just emit bb::multimedia::NowPlayingConnection::pause() by doing "emit pauseSignal();"

void pause(): the slot which will do a callback into the javascript layer using NowPlayingNDK::sendEvent on a callbackId.

void setUpPauseCallback(callbackId):
    1. Connect the pause signal to its slot
        QObject::connect(
            this,
            SIGNAL(bb::multimedia::NowPlayingConnection::pause()),
            this,
            SLOT(pause())
        );
    (I think it's better to do it here, rather than in NowPlayingCordova/src/NowPlaying_ndk.hpp)
    2. Sets up the callbackId by which the slot pause() can make a callback into the javascript layer (class NowPlayingNDK should probably keep a list of callbackIDs, one per slot).

So the developer writing in javascript first sets up the various callbacks, which will set up the callback infrastructure, and then he/she can resume, stop, pause by just calling the native NowPlayingNDK::NowPlayingResume/Stop/Pause() to emit their corresponding signals.
Now providing these callbacks through requestPlayback can be tricky, because of how Cordova keeps track of them. I was invesigating this. Here's my understanding so far. I tested my understanding by walking through the debugger.

[sample app]
https://github.com/parker-mar/WebWorks-Community-APIs/blob/b3fb7f5ae166ece359e04a272a0a6c88886bdfef/BB10-Cordova/NowPlaying/sample/www/js/index.js
[javascipt client-side part of the plugin]
https://github.com/parker-mar/WebWorks-Community-APIs/blob/b3fb7f5ae166ece359e04a272a0a6c88886bdfef/BB10-Cordova/NowPlaying/plugin/www/client.js
[javascript server-side part of the plugin]
https://github.com/parker-mar/WebWorks-Community-APIs/blob/b3fb7f5ae166ece359e04a272a0a6c88886bdfef/BB10-Cordova/NowPlaying/plugin/src/blackberry10/index.js
[native front-end part of the plugin]
https://github.com/parker-mar/WebWorks-Community-APIs/blob/b3fb7f5ae166ece359e04a272a0a6c88886bdfef/BB10-Cordova/NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_js.cpp
[native back-end part of the plugin]
https://github.com/parker-mar/WebWorks-Community-APIs/blob/b3fb7f5ae166ece359e04a272a0a6c88886bdfef/BB10-Cordova/NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp

I am looking at the code path for setting the metadata and how it sets up the dummy aSyncCallback:

In the sample app, we:
1.a. Bind the metadata button:
setMetaButtonClick: function(){

    var jsonData = {"Title":"MyTitle",
            "Artist":"MyArtist",
            "Album":"MyAlbum"};
    com.blackberry.community.nowplaying.NowPlayingSetMetadata(jsonData, app.aSyncCallback);

},

1.b. aSyncCallback is defined:
aSyncCallback: function(data) {
    if (data) {
        console.log(data);
        app.writeOut(data.result);
    }
},

In the javascript client-side part of the plugin:
2.a. setMetaButtonClick (in 1.a.) calls this:
_self.NowPlayingSetMetadata = function (input, callback) {
        var success = function (data, response) {
            var json = JSON.parse(data);
            callback(json);
        },
        fail = function (data, response) {
            console.log("Error: " + data);
        };
    exec(success, fail, _ID, "NowPlayingSetMetadata", { input: input });
};

In the javascript server-side part of the plugin:
3.a. exec(success, fail, _ID, "NowPlayingSetMetadata", { input: input }) (in 2.a.) calls this:
NowPlayingSetMetadata:  function (success, fail, args, env) {
    var result = new PluginResult(args, env);
    resultObjs[result.callbackId] = result;
    args = JSON.parse(decodeURIComponent(args["input"]));
    nowPlaying.getInstance().NowPlayingSetMetadata(result.callbackId, args);
    result.noResult(true);
}

3.b. nowPlaying.getInstance().NowPlayingSetMetadata(result.callbackId, args); (in 3.a.) calls this:
self.NowPlayingSetMetadata = function (callbackId, input) {
    return JNEXT.invoke(self.m_id, "NowPlayingSetMetadata " + callbackId + " " + JSON.stringify(input));
};

In the native front-end part of the plugin:
4.a. JNEXT.invoke(self.m_id, "NowPlayingSetMetadata " + callbackId + " " + JSON.stringify(input)); (in 3.b.) calls this:
string NowPlayingJS::InvokeMethod(const string& command) {
    ...
    }else if(strCommand=="NowPlayingSetMetadata"){
    m_NowPlayingMgr->NowPlayingSetMetadata(callbackId,arg);
    return "";
    ...
}

In the native back-end part of the plugin:
5.a. m_NowPlayingMgr->NowPlayingSetMetadata(callbackId,arg); (in 4.a.) calls this:
void NowPlayingNDK::NowPlayingSetMetadata(const std::string& callbackId, const std::string& data){
    ...
    Json::Value root;
    ...
    root["result"] = "SetMetadata Succeed.";
    sendEvent(callbackId + " " + writer.write(root));
    ...
}

5.b. sendEvent(callbackId + " " + writer.write(root)); (in 5.a.) calls this:
void NowPlayingNDK::sendEvent(const string& msg){
    m_pParent->NotifyEvent(msg);
}

4'. In the native front-end part of the plugin:
4'.a. m_pParent->NotifyEvent(msg); (in 5.b.) calls this:
```
// Notifies JavaScript of an event
void NowPlayingJS::NotifyEvent(const std::string& event) {
    std::string eventString = m_id + " ";
    eventString.append(event);
    SendPluginEvent(eventString.c_str(), m_pContext);
}
```

3'. In the javascript server-side part of the plugin:
3'.a. SendPluginEvent(eventString.c_str(), m_pContext); (in 4'.a.) calls this:
```
// Fired by the Event framework (used by asynchronous callbacks)
self.onEvent = function (strData) {
    var arData = strData.split(" "),
        callbackId = arData[0],
        result = resultObjs[callbackId],
        data = arData.slice(1, arData.length).join(" ");

    if (result) {
        if (callbackId != threadCallback) {
            result.callbackOk(data, false);
            delete resultObjs[callbackId];
        } else {
            result.callbackOk(data, true);
        }
    }
};
```

2'. In the javascript client-side part of the plugin:
2'.a. result.callbackOk(data, true); (in 3'.a.) calls the function success in this:
```
_self.NowPlayingSetMetadata = function (input, callback) {
        var success = function (data, response) {
            var json = JSON.parse(data);
            callback(json);
        },
        fail = function (data, response) {
            console.log("Error: " + data);
        };
    exec(success, fail, _ID, "NowPlayingSetMetadata", { input: input });
};
```

1'. In the sample app, we:
1'.a. callback(json); (in 2'.a.) calls this:
```
aSyncCallback: function(data) {
    if (data) {
        console.log(data);
        app.writeOut(data.result);
    }
},
```

Now look at 2.a. above:
    _self.NowPlayingSetMetadata = function (input, callback) {
            var success = function (data, response) {
                var json = JSON.parse(data);
                callback(json);
            },
            fail = function (data, response) {
                console.log("Error: " + data);
            };
        exec(success, fail, _ID, "NowPlayingSetMetadata", { input: input });
    };

And 3.a. above:
    NowPlayingSetMetadata: function (success, fail, args, env) {
        var result = new PluginResult(args, env);
        resultObjs[result.callbackId] = result;
        args = JSON.parse(decodeURIComponent(args["input"]));
        nowPlaying.getInstance().NowPlayingSetMetadata(result.callbackId, args);
        result.noResult(true);
    }

And take a look at debug1/platforms/blackberry10/platform_www/cordova.js.
Look at the exec function at line 897. exec() indexes the given success and fail callbacks with a new callbackId at line 906. It then calls into 3.a. at line 932, which calls into native code tod do work. It then applies the success or fail callbacks at line 293 and deletes the callbackId index to them, depending on the result of 3.a (result.noResult(true)). This is how synchronous success and fail callbacks are made.
PluginResult is defined in debug1/platforms/blackberry10/native/device/chrome/lib/PluginResult.js.
To see how async callbacks are made, look at 3.a. again. Note that the true boolean in result.noResult(true) actually keeps the callbacks around, rather than deleting the callbackId index to them. This callbackId index is used as a key for resultObjects in 3.a., which is a list of results kept around for asynchronous calls. When a signal/event is fired in the native layer, the corresponding slot makes async calls through sendEvent() (5.b.) on such a callbackId. This goes up to 3'a., where the corresponding result is obtained from the resultObject, which is used to execute the success/fail functions associated with the callbackId. This is how async success and fail callbacks are made.
What's important to see here is that because exec indexes success and fail callbacks with one new callbackId, then in order to set up callbacks using
    requestPlayback: function(
            {
                songURL = "/songURL",
                iconURL = "/iconURL",
                metadata: { Title = "/Title", Artist = "/Artist", Album = "/Album" },
                nextEnabled = true,
                prevEnabled = true,
                callbacks: {
                    play = function() {},
                    stop = function() {},
                    pause = function() {},
                    resume = function() {},
                    error = function() {},
                    next = function() {},
                    previous = function() {}
            }
        ) { ... }

in plugin/www/client.js, we need this function in this file to distribute each callback into its own function that will call exec into the javascript server side of the plugin in plugin/src/blackberry10/index.js and whose success function is the given callback function to requestPlayback. Again, this is because there is only ONE new callbackId associated per exec(), each of which has only ONE success/fail callback associated with it. Otherwise, the success function for requestPlayback will have to determine which callback to execute, which is messy and overloads what it has to do.
In the sample app, we'll probably want a playlist to fiddle with, then:
var playlist = [
    {
        songURL: "http://www.pch.gc.ca/DAMAssetPub/DAM-hymChs-antSgn/STAGING/audio-audio/o-canada_1359474460106_eng.MP3",
        iconURL: "http://flaglane.com/download/canadian-flag/canadian-flag-small.jpg",
        metadata: {
            Title: "O Canada",
            Artist: "Canada",
            Album: "Canada's Favorites"
        }
    },
    {
        songURL: "sounds/highhat.mp3",
        iconURL: "img/Hi-hat.jpg",
        metadata: {
            Title: "High Hat",
            Artist: "Drum Kit",
            Album: "Instruments"
        }
    }
];

One thing that made this challenging to understand is insufficient documentation. The best I found is https://cordova.apache.org/docs/en/5.1.1/guide/platforms/blackberry10/plugin.html, but we will probably have to reference the actual code for details on how some of the modules work:
debug1/platforms/blackberry10/platform_www/cordova.js
debug1/platforms/blackberry10/platform_www/cordova-js-src/exec.js
debug1/platforms/blackberry10/native/device/chrome/lib/PluginResult.js
debug1/platforms/blackberry10/native/device/chrome/lib/jnext.js

Some questions about acquire/revoke/play/stop and trackChange (thru email):
Q1: Regarding the acquire/revoke/play/stop implementation I was considering:
The NowPlaying API's requestPlayback method can acquire to set up stuff like overlay style and music, then it can revoke before the method ends.
The NowPlaying API's play method can implicitly reacquire. The NowPlaying API's stop method can implicitly revoke. (Why would we need callbacks for Acquire, Revoke, then?)
Q2: Regarding trackChange API:
It can be called in two ways:

Developer can directly call trackChange() which in the native layer will do a stop(), set track according to details, then play(), and also do enabling/disabling of next/previous buttons from the volume overlay as specified.
requestPlayback is first given next()/previous() callbacks. These are called when internal logic (e.g. triggered by user tapping next/previous on the volume overlay) emits native next()/previous() signals, which connect to slots that execute the callbacks. The callbacks defined earlier should update the UI and call trackChange() according to "next"/"previous" songs and metadata that the developer keeps track of with a playlist in the JS client layer.
So my question is why requestPlayback needs parameters for enabling and disabling the next/previous buttons, if it's really the callback that calls trackChange that determines whether to disable/enable the buttons?
And why not provide next/previous helper NowPlayingConnection methods which emit the native next()/previous() signals (which do the callback and call trackChange eventually)?

Tim's response to Q1: I don’t understand why you’d revoke in the method that is trying to acquire.
There’s no “play” method defined in the API that I gave – it was changed to “resume” to better reflect its purpose, as the opposite of “pause”.
What you’re describing is a different API – where you have a sort of setup method, followed by standard playback controls. Either approach can work, but it seems to me that you’re forcing multiple method calls where you want one action. Every time the developer wants to play something, the developer will need to call the setup function to provide the metadata and settings for next/previous. Then they call play(). To change tracks, you would call the setup function again? And then call play() again? I wouldn’t be surprised if you find some better ways to do the API as you get more familiar with the low level capabilities, but I don’t see how this makes it better.
I think you still need callbacks for acquire and revoke, because those events can be fired as a result of external actions, and the application may need to handle them. For example, if you are using this API to play music, and a phone call comes in, the revoke signal would happen, and the app would lose its control over the audio. Maybe that could be abstracted into the pause event, but I don’t know. If it’s possible to handle all the acquire/revoke situations without needing to inform the application, then that would be a good improvement.
Tim's response to Q2: This is related to Q1 – in my design requestPlayback handles setup and begins playing the file. Whenever you start playing a file, you need to turn on or off the next/previous buttons, because they go into the overlay, which will be available as soon as audio starts playing. The requestPlayback method also works as the first time setup function, so it allows the developer to set up all their callback functions at one time, rather than every time they play a track.
You are right that most of the time it will be in a callback function on a next/previous event which determines what to do. At this point the app will figure out what track it wants to play, gather the metadata, and determine if it should have next or previous turned on, then it will call trackChange with that information. However, some applications may only use this to play a single track, turning off the next/previous buttons.
I don’t see how adding helper methods for next previous provide anything? The application developer is going to define methods for doing next and previous. These methods will do whatever logic makes sense to the app, and then call trackChange. Why would we need another method of for them to call, when they’ve already defined it, and can call it directly?

I think one ambiguity I'm having is how to be a good citizen on the system and with MP, NPConnection, and NPController.
https://developer.blackberry.com/native/documentation/graphics_multimedia/audio_video/accessing_media_notification_areas.html

The notification area emits signals that can be used by your app to keep track of when the Play, Pause, Prev or Next media player control buttons have been pressed.

I understand this sends a NPC Play(), Pause(), Prev(), Next() signal. But which music player instance does this interact with? Or is this a plain NPC signal which we must connect to a slot which calls methods of a music player instance we keep track of?

http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#property-audiomanagerhandle

The controllerActive property provides notification to indicate that one or more controllers are attached to the service that is currently acquired. The controllers require regular status updates to function accurately. This means that even if an application is in standby mode, regular status messages should continue to be sent to it.

I never considered "controllers" before. Are they http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingcontroller.html ?
In a high-level overview, how do MP, NPConnection, and NPController interact?

With no audioManagerHandle specified, the now playing service will automatically call play() when no longer preempted. If an audioManagerHandle is specified, the now playing service will only call play() if the audio routing has not changed to a more public device while preempted.

What this means to me is that the play() signal will be emitted, which means that we must connect it to a slot which calls methods of a music player instance we keep track of.
I didn't look at audioManager before. Is it a good idea to use it? Is it necessary?

About Q1
Assume we are using pre-defined signals.
From my understanding, Tim's proposed requestPlayback should:

Setup the callbacks by connecting acquire, revoke, play, stop,.. pre-defined signals to slots that will call the given callbacks.
Acquire the NowPlayingConnection (NPC).
Setup music to be played, with metadata and icon.
Play the MusicPlayer instance. This should call the play() slot.
(Does not revoke the NPC before exiting)

The proposed trackChange should:

Stop the MusicPlayer instance. This should call the stop() slot.
Setup the music to be played, with metadata and icon.
Play the MusicPlayer instance. This should call the play() slot.

Some thoughts:

We need to connect native signals like play() to our given callbacks at some point. Maybe we don't need to define our own signals.

When should we acquire? revoke? I think it should be done only as necessary (as if it were a lock), since it is under the control of the system (through NowPlayingConnection preemption, for example).

requestPlayback feels overloaded. I would rather the dev do 2.-4. seperately, hence the initialPlay()/acquire() and stop()/revoke() function I suppose I was suggesting.

About Q2
I understand and agree with the first two paragraphs of Tim's response.
In the third paragraph:

I don’t see how adding helper methods for next previous provide anything? The application developer is going to define methods for doing next and previous. These methods will do whatever logic makes sense to the app, and then call trackChange. Why would we need another method of for them to call, when they’ve already defined it, and can call it directly?
I imagine three use cases which will eventually call trackChange in the native C++ layer:

Volume Overlay next/previous buttons are touched.
The developer creates a next/previous button on their app.
The developer creates a method to jump to a particular song from their app.

For case 1, the developer must first specify next/previous callbacks through requestPlayback.
For case 2, the developer may create a next/previous functions.
For case 3, the developer would use trackChange.
By providing next/previous API, the developer could just specify an anonymous function for case 1 without having to create seperate and possibly inconsistent next/previous functions.
When I suggested the API I thought a reason it would help is that we could output an error in case the next/previous callbacks were not yet defined through requestPlayback, but because the same error could be caught through trackChange (which the developer-defined next/previous functions would call), this is a mooch point/question.
However, I do feel like it's natural for a music playing API like NowPlaying to have next/previous options, especially since the developer provides callbacks for them through requestPlayback.

I'm conjecturing that MediaPlayer and NowPlayingConnection should not "depend" on one another. After some inspection, I found that this assumption led me to believe that MediaPlayer's public slot bb::multimedia::MediaError::Type play () emits NowPlayingConnection's signal void play () because the documentation for the latter says:
"This signal is emitted on notification that a play track command has been received."
and I presumed this "play track command" to be a signal as emitted by former.
However, I noticed that

Since these are separate APIs, we should expect them to behave independently.
The documentation for MediaPlayer's play never actually says it emits a "play track command"-like signal:
"Successful playback will emit a mediaStateChanged() signal with a MediaState::Started value. If the player is in the MediaState.Unprepared state internally prepare() will be called. In this case a mediaStateChanged() signal is emitted twice, once with a value of MediaState.Prepared and next MediaState.Started."

So, in working with QT connecting the NowPlayingConnection signal to a slot, I realize was failing to fire the NowPlayingConnection signal because I thought it would be fired by MusicPlayer's play() slot, but that actually fires a mediaStateChanged() signal.
The question, then, how do I fire the NowPlayingConnection play() signal? I don't see any functions in the API to emit it. This differs from acquire(), for which I can be fired using the slot acquire() and caught using the the signal void acquired(). I believe these must be fired by internal signals, so I'll try that.
http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#function-play
has this sentence, but what does it mean? Maybe it will be useful in teaching us how to fire the signals.
"Acquired signals can be used in calls to next(), previous(), play(), pause(), and stop(). Upon receiving a signal, the user must call the function that is most appropriate for their media."

I'm curious about this "playlist" - can we use it? How does it work? I assume we won't for now.
http://developer.blackberry.com/native/reference/cascades/bb__multimedia__mediaplayer.html#function-previoustrack

bb::multimedia::MediaError::Type nextTrack ()
Moves playback to the next track in the playlist.
If the media source is a playlist, this function will move to the next track. On success it will result in a trackChanged() signal.
If the media source is not a playlist then calling this function does nothing.
This method call is blocking.

About Q1

What you’re describing is a different API – where you have a sort of setup method, followed by standard playback controls. Either approach can work, but it seems to me that you’re forcing multiple method calls where you want one action. Every time the developer wants to play something, the developer will need to call the setup function to provide the metadata and settings for next/previous. Then they call play(). To change tracks, you would call the setup function again? And then call play() again?

I'm not too sure what you mean by "either approach".
I am guessing your approach to be this:
requestPlayback should:
    1. Setup the callbacks by connecting acquire, revoke, play, stop,.. pre-defined signals to slots that will call the given callbacks.
    2. Acquire the NowPlayingConnection.
    3. Setup music to be played, with metadata and icon.
    4. Play the MusicPlayer instance. This should call the play() slot.
    (Does not revoke the NowPlayingConnection before exiting)

trackChange should:
    1. Stop the MusicPlayer instance. This should call the stop() slot.
    2. Setup the music to be played, with metadata and icon.
    3. Play the MusicPlayer instance. This should call the play() slot.

But I guess I am proposing a more decoupled approach for requestPlayback, wherein the developer would use the API like this:
    /**********************
     * APP LOGIC VARIABLES
     **********************/
    var currentSong = -1;

    var myPlaylist = [
        {
            songURL: "http://www.pch.gc.ca/DAMAssetPub/DAM-hymChs-antSgn/STAGING/audio-audio/o-canada_1359474460106_eng.MP3",
            iconURL: "http://flaglane.com/download/canadian-flag/canadian-flag-small.jpg",
            metadata: {
                Title: "O Canada",
                Artist: "Canada",
                Album: "Canada's Favorites"
            }
        },
        {
            songURL: "sounds/highhat.mp3",
            iconURL: "img/Hi-hat.jpg",
            metadata: {
                Title: "High Hat",
                Artist: "Drum Kit",
                Album: "Instruments"
            }
        }
    ];

    /************
     * CALLBACKS
     ************/
    function myAcquireCallback() {
        // I can't think of any UI or app logic updates that warrants us needing this callback.
        // It seems myPlayCallback() should do all the work, which is always triggered alongside.
    }

    function myRevokeCallback() {
        // I can't think of any UI or app logic updates that warrants us needing this callback.
        // It seems myStopCallback() should do all the work, which is always triggered alongside.
    }

    function myPlayResumeCallback() { // Essentially the same for play and resume
        // 1. Update the app logic, including currentSong.
        // 2. Update the UI.
    }

    function myPauseCallback() {
        // 1. Update the app logic.
        // 2. Update the UI.
    }

    function myStopCallback() {
        // 1. Update the app logic, including currentSong.
        // 2. Update the UI.
    }

    function myNextCallback() {
        // 1. Update the UI
        // 2. cordova.plugins.nowplaying.trackChange(
        //    {
        //        myPlaylist[currentSong + 1].songURL,
        //        myPlaylist[currentSong + 1].iconURL,
        //        myPlaylist[currentSong + 1].metadata,
        //        currentSong + 1 < myPlaylist.size() - 1 // nextEnabled. Here: false
        //        currentSong + 1 > 0 // prevEnabled. Here: true
        //    }).
        // 3. Update the app logic, including currentSong.
    }

    function myPreviousCallback() {
        // 1. Update the UI
        // 2. cordova.plugins.nowplaying.trackChange(
        //    {
        //        myPlaylist[currentSong - 1].songURL,
        //        myPlaylist[currentSong - 1].iconURL,
        //        myPlaylist[currentSong - 1].metadata,
        //        currentSong - 1 < myPlaylist.size() - 1 // nextEnabled. Here: true
        //        currentSong - 1 > 0 // prevEanbled. Here: false
        //    }).
        // 3. Update the app logic, including currentSong.
    }

    function myErrorCallback() {
        // 1. Update the app logic.
        // 2. Update the UI.
    }

    /******************************************************
     * Main execution using cordova.plugins.nowplaying API
     ******************************************************/
    cordova.plugins.nowplaying.requestPlayback(
        {
            myAcquireCallback, myRevokeCallback,
            myPlayResumeCallback, myPauseCallback, myStopCallback,
            myNextCallback, myPreviousCallback,
            myErrorCallback
        });
        // 1. Set up the NowPlayingConnection volume overlay.
        //
        // 2. Set up user-triggerable callbacks:
        //   - Connect the NowPlayingConnection->acquired() signal, as emitted by NowPlayingConnection->acquire(), to the acquireSlot() that triggers myAcquireCallback.
        //   - Connect the NowPlayingConnection->revoked() signal, as emitted by NowPlayingConnection->revoke(), to the revokeSlot() that triggers myRevokeCallback.
        //   - Connect the mediaStateChanged(MediaState::Started) signal, as emitted by MediaPlayer->play(), to the playSlot() that triggers myPlayResumeCallback.
        //   - Connect the mediaStateChanged(MediaState::Paused) signal, as emitted by MediaPlayer->pause(), to the pauseSlot() that triggers myPauseCallback.
        //   - Connect the mediaStateChanged(MediaState::Stopped) signal, as emitted by MediaPlayer->stop() to the stopSlot() that triggers myStopCallback.
        //
        //   These two are optional and not specified by Tim's API:
        //   - Connect a newly defined nextSignal() to the nextSlot() that triggers myNextCallback.
        //   - Connect a newly defined previousSignal() to the previousSlot() that triggers myPreviousCallback.
        //
        // 3. Set up system-triggerable callbacks:
        //   - Connect the NowPlayingConnection->acquired() signal,
        //   as emitted internally thru preemption, to the acquireSlot() that triggers myAcquireCallback.
        //   - Connect the NowPlayingConnection->revoked() signal,
        //   as emitted internally thru preemption, to the revokeSlot() that triggers myRevokeCallback.
        //   - Connect the NowPlayingConnection->play() signal,
        //   as emitted internally thru preemption or volumeOverlay, to the playSlot() that triggers myPlayResumeCallback.
        //   - Connect the NowPlayingConnection->pause() signal,
        //   as emitted internally thru preemption or volumeOverlay, to the pauseSlot() that triggers myPauseCallback.
        //   - Connect the NowPlayingConnection->stop() signal,
        //   as emitted internally thru preemption or volumeOverlay, to the stopSlot() that triggers myStopCallback.
        //   - Connect the NowPlayingConnections->next() signal,
        //   as emitted internally thru volumeOverlay, to the nextSlot() that triggers myNextCallback.
        //   - Connect the NowPlayingConnections->previous() signal,
        //   as emitted internally thru volumeOverlay, to the previousSlot() that triggers myPreviousCallback.
        //
        // 4. Set up other callbacks:
        //   - Connect a newly-defined errorSignal() to the errorSlot() that triggers the callback.

    cordova.plugins.nowplaying.play(
        {
            myPlaylist[0].songURL,
            myPlaylist[0].iconURL,
            myPlaylist[0].metadata,
            currentSong < myPlaylist.size() - 1, // nextEnabled. Here: true
            currentSong > 0 // prevEnabled. Here: false
        });
        // 1. Setup songURL, iconURL, metadata.
        // 2. Enable/disable next/previous buttons on the volume overlay.
        // 3. NowPlayingConnection->acquire().
        // 4. MediaPlayer->play().

    cordova.plugins.nowplaying.pause();
        // 1. MediaPlayer->pause().

    cordova.plugins.nowplaying.resume();
        // 1. MediaPlayer->play().

    cordova.plugins.nowplaying.trackChange(
        {
            myPlaylist[1].songURL,
            myPlaylist[1].iconURL,
            myPlaylist[1].metadata,
            currentSong < myPlaylist.size() - 1, // nextEnabled. Here: false
            currentSong > 0 // prevEnabled. Here: true
        });
        // 1. MediaPlayer->stop().
        // 2. Setup songURL, iconURL, metadata.
        // 3. Enable/disable next/previous buttons on the volume overlay.
        // 4. MediaPlayer->play().

    // This API method is optional and is not specified by Tim's API
    cordova.plugins.nowplaying.previous();
        // 1. emit the newly defined previousSignal().

    // This API method is optional and is not specified by Tim's API
    cordova.plugins.nowplaying.next();
        // 1. emit the newly defined nextSignal().

    cordova.plugins.nowplaying.stop();
        // 1. MediaPlayer->stop().
        // 2. NowPlayingConnection->revoke().

I can't seem to get the volumeOverlay buttons to fire signals, e.g. next() or pause() buttons.
I am trying this, for example (connecting to a dummy pauseSlot):
newConnectResult = QObject::connect(
npc,
SIGNAL(next()),
this,
SLOT(pauseSlot())
);

I don't think we need to use NowPlayingController at all - I think it might be trimmed version of the NowPlayingConnection without the Overlay interface. I'm confirming that if I can with some colleagues.
Let's also leave out audioManagerHandle - it's a way to control how the audio is played, like which speakers [handset, speakerphone, line out, bluetooth] and it's not something we really need to tackle in this version.
The MediaPlayer instance that our NowPlayingConnection interacts with, is the one that we create. I thought that was already in the original plugin.

Ok. Yes, MediaPlayer was already here.

Firing the Next() and Play() signals on the NowPlayingConnection probably require you to tap on the buttons on the Overlay.

You can give the mediaplayer a playlist file, like a .m3u file, instead of an audio track and that will give you the ability to do next and previous within the mediaplayer object. I wasn't planning on using that approach though, as I preferred to leave that control up to the developer, in case they weren't able to use a standard playlist file.

I'm fine with you changing the API to what you've got there - the only thing is that I think you can go with a single play() method, and not have a trackChange at all, right? It seems like the small differences could be handled by some status checks inside the method.

I'm fine with you changing the API to what you've got there - the only thing is that I think you can go with a single play() method, and not have a trackChange at all, right?
Right, yeah I think this can be done.

Firing the Next() and Play() signals on the NowPlayingConnection probably require you to tap on the buttons on the Overlay.
Yes, I've tried this. The overlay does respond to taps in the sense that the buttons change visuals ("tapped" state vs "untapped" state, "pause" toggles with "play"), but they aren't firing anything. At the same time, the volume overlay isn't showing the icon and metadata. And this is odd because I do setVolumeOverlay to fancy, and the NowPlayingConnection is acquired.

I don't think we need to use NowPlayingController at all - I think it might be trimmed version of the NowPlayingConnection without the Overlay interface. I'm confirming that if I can with some colleagues.

In this thread, a Paul Bernhardt suggests using NowPlayingController.
https://supportforums.blackberry.com/t5/Native-Development/How-do-I-invoke-the-Pause-button-functionality-to-pause-media/td-p/2685185

TODO: (no particular order)

Volume Overlay
(NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp)

Get music, icon, and metadata to show here
Get buttons here to fire signals
Investigate setting appropriate size for media notification area even though Tim mentioned

I don’t think there’s any control to change the size of the media notification area – it’s set by the OS and the hardware.

App preemption
(NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp)

Get app preemption to fire signals

Metadata
(NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp)

Investigate putting more than just the Title, Artist, Album properties, even though http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#comment-1134791487 says

Comment 2 years ago from Oct 30, 2015.Wes Barichak: "Currently, the only metadata properties that are available are MetaData::Album, MetaData::Artist, and MetaData::Title, while the rest of the MetaData properties are ignored. This will likely change in the future though."

Icon
(NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp)

Investigate setting icons based on URLs even though http://developer.blackberry.com/native/reference/cascades/bb__multimedia__nowplayingconnection.html#function-play says

Comment 2 years ago from Oct 30, 2015.
Theodore Mavrakis: "How can we pass an http url to use for the icon of a NowPlayingConnection?"
Wes Barichak: "Currently, this is not possible. But, we will be looking at adding this functionality in a future release."

Validate parameters to NowPlayingRequestPlayback and NowPlayingPlay.
(NowPlaying/plugin/www/client.js)

Give NowPlayingNDK::NowPlayingError signal/slot parameters to specify error information. Can create an enum of general errors that can occur. Use this throughout the class.
(NowPlaying/plugin/src/blackberry10/native/src/NowPlaying_ndk.cpp)

Ensure callbacks are not duplicated when pressing "Stop" and "requestPlayback" multiple times in the sample app, i.e. idempotentcy.

Give the sample app more interesting callbacks, e.g. the sample app https://github.com/blackberry/Cascades-Samples/tree/master/nowplaying uses images.

Test more songURL and iconURL local paths

Regarding your signals not firing - I think we're missing some critical code here and I don't know where it was lost. These sorts of plugins that use signals and slots leverage the ApplicationThread class to make this all work. The plugin code is run on that ApplicationThread, and that's what makes the signals and slots work - because the ApplicationThread is a QThread with the necessary signal and slot capabilities.
Looking at both MediaKeys and SystemDialog as examples, I see calls to the "join" method on initialization, passing in the Window Group so that the Application Thread runs in the same group as the app itself, but I don't see that in this plugin: https://github.com/parker-mar/WebWorks-Community-APIs/blob/master/BB10-Cordova/MediaKeys/plugin/src/blackberry10/index.js#L92-L104
Secondly, the method calls need to go from the Plugin's thread, to the ApplicationThread where the NowPlayingNDK code was moved. MediaKeys and SystemDialog do that like the following, but I see direct method calls in this plugin:
https://github.com/parker-mar/WebWorks-Community-APIs/blob/master/BB10-Cordova/MediaKeys/plugin/src/blackberry10/native/src/mediaKeys_js.cpp#L102-L103
I think we need to check out these differences in order to make the communication work properly. There could be other things that I missed too.

Yes! This worked perfectly for the volume overlay.
I am trying to figure out how this will work for preemption, as it doesn't seem to work as of yet. I am testing this by using the mic button or playing another video, then returning to the NowPlaying app and expecting play/pause callbacks to be shown (but they are not). I looked at almost all the other plugins, but nothing found yet. Do you have any advice here Tim?

I don't see you handling the revoke signal at all - that's what you should be getting when another audio signal takes over. When you get that signal, you can pause the mediaplayer.

Right, okay I modified this and preemption works now.

Notes and corresponding slides
for presentation I made with mentors at own university:
Uploading CSC494 Presentation.docx…
pics.pdf


Can I share FABRIC_API_KEY and FABRIC_API_SECRET publicly?

Hi,
When installing the plugin, it adds FABRIC_API_KEY and FABRIC_API_SECRET in the config.xml.
Can I checkout this file publicly on Github without worrying about those secrets ?
Thanks

Reading from Fabric's forums, I think I can.
Letting this open until someone confirm 😸

API keys are secret only for you, so it's not recommended

Ok thanks


Issue205

OK, so this should in theory leave us with a fully-functional duplication system, that should have no impact on the results of non-duplication simulations. That's difficult to ascertain though... Or is there a way to recover a former version of develop to launch a few simulations from it and check that the results are identical, @swom ?

(don 't need a full review unless you want to have a look, I just wasn't sure whether you'd be notified otherwise)


Added token for mutation aliases

This is the promised hook.
The variable-input, atom-input, and property-mutation have been replaced with simple aliases added by the new hook. The aliases are added exactly as described in the image here.
The code might look quite complex but most of it is just 4 relatively simple functions.

Amazing, thank you so much!


Checklist for using Passenger and Apache2

Hello,
can someone give me a step by step description for using Passenger with Apache2 to serve a pageflow website. Or tell me where I can find such an instruction.
Thank you

Hi,
Pageflow itself is not a Rails application, but a so called Rails engine that can be used inside a Rails application. There are many options regarding Rails application deployment. Still, most of these considerations are not Pageflow specific, so most Passenger tutorials should be be applicable to your case. Nevertheless the topic is somewhat out of scope for Pageflow's documentation. Therefore I am going to close this issue.


Do not rely on conditional module definition

The downside of conditional module definition is that
it may not work as expected in umbrellas. Given the
Sentry Logger configuration in an umbrella project is
shared across all apps, if we do:
config :logger, :backends, [Sentry.LoggerBackend]

then :sentry needs to be defined on all dependencies.
However, if a dependency is not a web application,
Sentry may be compiled before Plug! And if it is compiled
before Plug, it wouldn't define Sentry.PlugCapture and
friends, which means the web app in the umbrella wouldn't
have those modules available.

Thank you!!


switch sample to use new plugin

@briandealwis @loosebazooka This is template for generated code from the new project wizard.

ping

LGTM though we should have an outstanding blocking issue that we need to update to a released version of app-maven-plugin.


max_temp and min_temp warnings

Describe the bug
I have a heat pump, so my system supports emergency heating. When I turn on aux_heat, I get two log warning messages:
 Logger: custom_components.lennoxs30.climate
Source: custom_components/lennoxs30/climate.py:280
Integration: Lennox S30/E30 (documentation, issues)
First occurred: 1:46:46 PM (1 occurrences)
Last logged: 1:46:46 PM
max_temp - unexpected system mode [emergency heat] returning default - please raise an issue

 Logger: custom_components.lennoxs30.climate
Source: custom_components/lennoxs30/climate.py:253
Integration: Lennox S30/E30 (documentation, issues)
First occurred: 1:46:46 PM (1 occurrences)
Last logged: 1:46:46 PM
min_temp - unexpected system mode [emergency heat] returning default - please raise an issue

The S40 successfully changes to emergency heat mode.  So everything runs fine.  However, the log message says to raise an issue, so I have created this issue.  This is a low priority for me.
To Reproduce
The following Yaml action was run:
    - service: climate.set_aux_heat
      target:
        entity_id: climate.lennox_zone_1
      data:
        aux_heat: true

Expected behavior
No log messages.
Screenshots/Logs
NA
Version

Home Assistant: 2023.12.3
This Integration: 2023.10.1

**Integration Configuration **

Cloud or Local Connection: Local
Inverter or Sensor Diagnostics Enabled: no

Additional context
NA

Thanks for the report.  The impact will be the climate entity will not use the min / max temperature ranges defined in the Lennox System and will instead use the HA defaults when in Emergency Heat Mode.  So I'd expect to see some weirdness with the min / max limits changing in the thermostat card when switching in/out of emergency heat mode.
I'll get it fixed.

https://github.com/PeteRager/lennoxs30/releases/tag/2024.1.0


Migrate to Bookmark-Config and Bookmark-Database

Bookmark-Config and Bookmark-Database are now in a somewhat working state. We should work towards migrating Gatekeeper towards using those packages.

This is done.


Bump DMD_VER to 2.078.2

2.078.2 was released with more reliable retries and fallback mirror usage (https://github.com/dlang/dub/pull/1339) - hopefully this helps to reduce the spurious DUB failures.

I just saw this today again:
ZipException: no end record
posix.mak:799: recipe for target 'dpl-docs' failed
make: *** [dpl-docs] Error 2

(at https://github.com/dlang/tools/pull/312)
As this PR bumps the version to DUB with this being fixed, we should probably merge this rather sooner than later.


Why is @Bean SamplerFunction trySample never executed?

In project with spring-cloud-stream, rabbitmq and spring-cloud-sleuth my SamplerFunction.trySample is never executed. Where can be a problem?
Bean is in a correct @Configuration class (other beans are created and work).
`spring.sleuth.sampler.probability: 0.001
@Bean
SamplerFunction<MessagingRequest> zipkinSampler() {
    return new Zipkin.ZipkinSampler();
}

public static class ZipkinSampler implements SamplerFunction<MessagingRequest> {

    private SamplerFunction<MessagingRequest> sampler = MessagingRuleSampler.newBuilder()
            .putRule(channelNameEquals("alertsNever"), Sampler.NEVER_SAMPLE)
            .putRule(channelNameEquals("rabbitChannel"), RateLimitingSampler.create(1))
            .putRule(Matchers.alwaysMatch(), RateLimitingSampler.create(100))
            .build();;

    @Override
    public Boolean trySample(final MessagingRequest request) {
        log.info("trySample {}, channelKind: {}, channelName: {}, operation: {}", request, request.channelKind(), request.channelName(), request.operation());

        return sampler.trySample(request);
    }
}`

Can you create a sample that replicates this problem?

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

I have the same issue.
Dependencies:  spring-cloud-stream, spring-cloud-starter-stream-rabbit, spring-cloud-starter-zipkin
Expected behaviour:
Exposed bean @ConsumerSampler  @ProducerSampler SamplerFunction<MessagingRequest> should be used to determine sampling rate for created and published RabbitMQ message.
Actual behaviour:
The provided SamplerFunction is ignored. Instead the default RateLimitingSampler bean provided via autoconfiguration is created and used to make a sampling decision for created and published messages.
Workaround
Creating custom Sampler bean enables to extend and adjust the sampling behaviour.

Can you create a sample that replicates this issue please?

Here is a sample repository to reproduce the issue https://github.com/gindex/sleuth-rabbit-issue

hey @gindex I'm trying to make the sample work with the latest Boot 2.4.x but I can't work around Kotlin issues. Would it be possible to rewrite it to Java and update to the latest version?

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.


Add #![feature(param_attrs)] to enable exception example

On rust V1.39 nightly, at least, the exceptions example gives an error. Adding a line to the example allows it to run.
I'm very green at rust embedded, so there may be better ways, but this makes the example work.

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @andre-richter (or someone else) soon.
If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.
Please see the contribution instructions for more information.

Hi @bobgates, I believe that is a fluke in the nightly build you're using because param_attrs where stabilized around that time, cf. https://github.com/rust-lang/rust/pull/64010.

Okay, with a current Rust nightly 1.44, this problem goes away.


[Bug] Node always needs to be launched

🐛 Bug Report
The node should always be launched, but it is only launched during online mode.
Steps to Reproduce
Launch node in offline mode and you cannot make any rpc calls.
Code/Action snippet to reproduce
(https://github.com/monadicus/mentat/blob/main/mentat/src/server/mod.rs#L143)
Expected Behavior
RPC calls should work as long as they don't make any outbound connections.
(Write what you expected to happen here)
Your Environment

Mentat Version: Main

I thought this was intended so you could have configs that didn't need to start child processes?

@Meshiest iirc according to what @MACS-J1149 and I found the node always needs to be started according to Rosetta spec. It's just that in OFFLINE mode outbound connections are not allowed.


[6843] - extract PersonalDetailsForm validation

Context
After this spike we have decided that validation logic for each Form service used in the trainee creation journey should be pulled, making each available to: API, UI, BulkUpdate. with the latter two being the focus of this ticket.
Changes proposed in this pull request

Pulls personal detail validations into a separate module
New module  is used in TraineeAttributes and PersonalDetailsForm

Guidance to review

sanity check approach
are we happy with moving all these validations into app/validators/xxxx_xxxx_validations.rb

 Extract PersonalDetails validation


Added sutrajobs.com

SutraHR is an Indian startup recruiting agency that spams indiscriminately, ignoring requests to stop. Their email comes from @sutrajobs.com.

Invalid as of efead6b265b13e2abf5fd0da25b0bebc2f801272


Initial Tofu support

Feature description 💡
Add support to run the remote CLI driven workflow and VCS driven using opentofu using version v1.6.X
Anything else?
tofu releases can be download using the information in the following link:
https://api.github.com/repos/opentofu/opentofu/releases

Initial support was added in version 2.19.0-beta.5


ypspur: 0.0.1-4 in 'indigo/distribution.yaml' [bloom]

Increasing version of package(s) in repository ypspur to 0.0.1-4:

upstream repository: https://github.com/DaikiMaekawa/ypspur
release repository: https://github.com/DaikiMaekawa/ypspur-release.git
distro file: indigo/distribution.yaml
bloom version: 0.5.20
previous version for package: 0.0.1-3

Note it's best practice to make versioned releases in the upstream not abuse the debian increment number for new releases.


Janicart needs attachable floor buffer as lategame tech

Either with advanced mop or as another tech. Essentially it'd change X reagents under it per second to water (like space cleaner) so janitor can drive over puddles instead.

Vehicles removed awaiting better implementation.


CTRL+R executes reverse-i-search

[Y] I have read through the manual page (man fzf)
[Y] I have the latest version of fzf
[Y] I have searched through the existing issues

Info

OS

[Y] Linux (Arch)
[ ] Mac OS X
[ ] Windows
[ ] Etc.

Shell

[Y] bash
[ ] zsh
[ ] fish

Problem / Steps to reproduce
CTRL+R does not bring up fzf
Tested in terminator and termite

How did you install fzf? You may need to take extra steps to enable shell key bindings depending on your package manager.

https://github.com/junegunn/fzf#using-linux-package-managers

Thank you very much junegunn, you were right!  I just added
source /usr/share/fzf/key-bindings.bash
source  /usr/share/fzf/completion.bash
to my .bashrc file and it is working
Thanks again!


Polish Hive query execution in SQL Lab

Added hive to the staging, connection string looks like:
hive://hive-server2-silver.synapse:3623/default?auth=NOSASL
Couple existing issues:

[ ] progress tracker doesn't work

[ ] fetching metadata fails for some tables

[ ] no partition predicate error for table preview: http://stackoverflow.com/questions/39049620/no-partition-predicate-found-for-alias-even-when-the-partition-predicate-in-pres

[ ]

hey @bkyryliuk, any updates on this? This will allow us to revoke SSH access from engineers that simply SSH to run Hive queries on DI servers.

@bkyryliuk left on a long trip to southeast Asia and is joining a company named Open Door, I'll be taking over this.

I also meet this problem. When executing a hive query, the progress can't be get, but preview a hive table is ok.

@liweiwei71 this is a stale issue, closing. Also unclear which problem you are referring to. Please open a new issue.