MM5 API with WebSockets in NodeJS

To discuss development of addons / skins / customization of MediaMonkey.

Moderators: jiri, drakinite, Addon Administrators

MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

MM5 API with WebSockets in NodeJS

Post by MyVikes »

So i'm learning lots here websockets, MM5 API, etc. My issue is I'm using NodeJS to run the following script and it "works" but i'm not getting what i need and that is the list of albums. Instead i get the following message back:

event.data:
{"id":2,"result":{"result":{"type":"object","subtype":"promise","className":"Promise","description":"Promise","objectId":"{\"injectedScriptId\":1,\"id\":1}"}}}

In the code you see where i show a message in MM5 and it does show the count of albums and the names of the albums appear in the message. Yeah!

How can i get the promised list of albums for processing in NodeJS?

Code: Select all

const WebSocket = require('ws');

var ws = new WebSocket("ws://localhost:9222/devtools/page/0A34A500F331A35BD411032547B65F05")

var exp = 
"                                                                       \
var sql = 'SELECT * FROM ALBUMS WHERE Artist = \"B.B. King\"';          \
var intCount = 0;                                                       \
var strMsg;                                                             \
                                                                        \
function showMessage(msgToShow) {                                       \
    window.whenReady(() => {uitools.toastMessage.show(msgToShow, {disableUndo: true});});                           \
}                                                                       \
                                                                        \
async function getAlbums() {                                            \
    await app.db.getQueryResultAsync(sql)                               \
    .then(function (res) {while (!res.eof) {intCount++; strMsg = strMsg + res.fieldByName('Album'); res.next();}})  \
    .then(function () {showMessage(\"strMsg:\" + intCount + ', '  + strMsg)})                                       \
}                                                                       \
                                                                        \
getAlbums();                                                            \
";

console.log("exp:", "\n", exp);

var request = { 
    id: 2, 
    method: 'Runtime.evaluate', 
    params: {
        expression:exp
    } 
}

ws.addEventListener('open', function (event) {
    console.log("request expression:", "\n", request.params.expression, "\n\n");

    ws.send(JSON.stringify(request));
});

ws.addEventListener('message', function (event) {
    console.log("message=>", "\n", event.data, "\n\n");

    console.log("event.data:", "\n", event.data, "\n\n");

    var msg = JSON.parse(event.data);
    console.log("msg (parsed json):", "\n", msg, "\n\n");

    var result = msg.result.result;
    console.log("result:", "\n", result, "\n\n");

    var type = result.type;
    console.log("type:", "\n", type, "\n\n");

    if (type == "string") {
        var value = result.value;

        console.log("value:", "\n", value, "\n\n");
    } else if (type == "object") {
        var objectId = result.objectId;

        console.log("objectId:", "\n", JSON.parse(objectId), "\n\n");
    }
});

ws.addEventListener('error', function (event) {
    console.log("error=>", "\n", event.data, "\n\n");

    console.log("event.data:", "\n", event.data, "\n\n");
});
I've spent a good 8+ hours working on this so any tips will help me go a long ways I'm sure. :D
TIV73
Posts: 137
Joined: Sat Nov 12, 2011 1:31 pm

Re: MM5 API with WebSockets in NodeJS

Post by TIV73 »

You are getting back the reference to a promise containing your value instead of the actual object. You could either try manually resolving it with runtime.awaitPromise or playing around with the returnByValue and awaitPromise parameters in your runtime.evaluate request - but I'm not exactly sure if and how websockets in node handle this, you might end up having to write promise-aware functions.

Also, check out MediaMonkeyNet, specifically SendCommandAsync in MediaMonkeySession.cs. It's basically the same thing you are trying to do, just in .net.
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

You've given me something to look into....i'll get back after i try these...Thx
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

Update...I've gotten the MediaMonkeyNet app built and it's running. I used Wireshark to capture the request and pasted it into my NodeJS app and i got the expected response. So good from that standpoint...now i think i'm dealing with the specifics of the "app.db.getQueryResultAsync(sql)" request.

Thank you TIV73 for your suggestion!
drakinite
Posts: 474
Joined: Tue May 12, 2020 10:06 am
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by drakinite »

MyVikes wrote: Tue May 11, 2021 10:18 am Update...I've gotten the MediaMonkeyNet app built and it's running. I used Wireshark to capture the request and pasted it into my NodeJS app and i got the expected response. So good from that standpoint...now i think i'm dealing with the specifics of the "app.db.getQueryResultAsync(sql)" request.
Hi there, sorry for the late response; I was working on final projects for school. Great to hear TIV73's MediaMonkeyNet is working for you - Are you still having trouble with the async promises?
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

i have the original problem figured out and working and much more. Having fun working with websockets and JS.

I'm now struggling with getting the album art to return. Using this code:

Code: Select all

                        var thumbnail = res.getThumbAsync(200, 200, function (imageLink) {
                            _this._gettingImagePending = false;
                            if (imageLink && (imageLink !== '-')) {
                                console.log("got here 1:" + _this + ", " + imageLink);
                            } else {
                                console.log("got here 2:" + ", " + imageLink);
                            }
                        });
I can get a link such as "file:///temp/Thumbs/8A/BHJY132JIQ5Y81A1-200px.jpg" but it doesn't actually show up in the debug console under "temp/Thumbs". I see other jpg's appear as I scroll through the MM5 UI. Any thoughts on this one and of course once it does appear how to download it? :D

Thanks for the follow-up!
drakinite
Posts: 474
Joined: Tue May 12, 2020 10:06 am
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by drakinite »

Yep - The MediaMonkey application takes those file:///temp/(etc) requests and serves them from your system temp folder. For other applications to load the files, you'll probably have to replace file:///temp with "file:///"+os.tmpdir() https://nodejs.org/api/os.html#os_os_tmpdir
(I'm not at my computer atm, so I can't confirm the exact code.) To browse the files themselves, you can type %temp% into windows explorer and browse from there.

That's great that you're using Node and it's working well so far - NodeJS is my native tongue. 😉
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

I found the file on my PC so Thx Drakinite.

That being said here is my ultimate goal: I currently have an Android app that speaks to a set of web services i wrote in VB.Net which speaks to the MM4 comm objects and it works wonderfully. The app allows me to auto pick album randomly from a number of suggestions, just pick a random album (both without picking an album that has been played in the last n days), a list filtered albums by a genre, artist name, as well as browse my library and a host of other functions. Getting images was tricky and i found i had to actually open the MP3 and extract the album art, B64 it and return with the albums or songs json representation. This all works amazingly fast, so much so, i'd argue it's faster than the MM4 app itself. So I thought that with MM5 supporting web sockets i could eliminate the middle layer. :-) I started with Node.JS as i found starter code on the forum. I used MediaMonkey.Net app (also found and then downloaded and ran) and Wireshark to get some tips/tricks for how to send the json params. Java is actually my native language (and hence the Android app) so i took what i learned in Node.JS and already have a working prototype there which i can easily translate to the Android app. Needless to say if the MediaMonkey is interested in features for their mobile app i have a few i could suggest.

BUT, now my concerns are about being able to achieving my goal due to the album art. With your tip i can now find the file but how do i "serve it up" to my android app? :-( I either need a javascript B64 library to encode it and then to return in a json object or i need MM5 to serve it up via a URL. I don't see either options as being native to MM5's API (or i haven't found them yet). I think that because MM5 is fact running on the PC and hence has access to the file system to show the file in the MM5 app, is that correct? if that is the case then i'm going to have to find a javascript library that will B64 the image or allow MM5 to serve up a URL. I'll go down these paths next unless someone can suggest otherwise. I could also do a simple Node.JS or Java app to process a request from the Android app to a return a URL to the file.

Here is a stackoverflow article about B64 and javascript: https://stackoverflow.com/questions/362 ... javascript

I know there is a lot to unpack up above but thanks again for all you insights and help.
drakinite
Posts: 474
Joined: Tue May 12, 2020 10:06 am
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by drakinite »

What protocol does your Android app use to connect to your web services? (is it HTTP/REST? Websocket? Something else?) Does it connect directly to your Node.JS server or does it connect directly to your VB.Net program?

If your Node app uses Express, and it's just an HTTP server, you might be able to just use the res.sendFile() method: http://expressjs.com/en/4x/api.html#res.sendFile
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

The current version of the Android app speak to my webservice via HTTP/REST.
Currently: Android -> VB.Net app via HTTP -> MM4 via COM.

The updated version of the Android app will speak directly to MM5 via websockets.
Future: Android-> MM5 via websockets

I've created an addon for MM5 with the javascript functions I will need for the future Android app. Before i translate to the Android app i'm testing and everything works when called from my Node.JS or Java app except for the album art which i'm working on now. So the addon in effect replaces the functionality of the existing VB.Net intermediary.
drakinite
Posts: 474
Joined: Tue May 12, 2020 10:06 am
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by drakinite »

Ah, I see!
So, if you use JS within the MM interface to read the image, you can probably send it as a blob, since websockets support that format: https://developer.mozilla.org/en-US/doc ... ocket/send

There are different ways of getting a blob from an image, but I found a good method on StackOverflow here: https://stackoverflow.com/questions/424 ... javascript
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

Nailed it!

Thank you so much drakinite!
MyVikes
Posts: 31
Joined: Sun Jul 02, 2017 1:20 am

Re: MM5 API with WebSockets in NodeJS

Post by MyVikes »

Next question: Thus far iIve been accessing the web sockets via Localhost but now I'm trying to access then via the IP address and have been unsuccessful. To test i've temporarily disabled the firewall but still no luck. So instead of "http://localhost:9222/json" I'm trying to use "http://192.168.0.163:9222/json".

Should this work and if so what suggestions do you have for me to try next?
drakinite
Posts: 474
Joined: Tue May 12, 2020 10:06 am
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by drakinite »

Have you checked your router settings? Does the regular MM5 media sharing work from the same computer?
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
Peke
Posts: 14284
Joined: Tue Jun 10, 2003 7:21 pm
Location: Serbia
Contact:

Re: MM5 API with WebSockets in NodeJS

Post by Peke »

drakinite wrote: Mon May 31, 2021 2:55 pm Have you checked your router settings? Does the regular MM5 media sharing work from the same computer?
I agree with @drakinite, have you tried to access MM5 UI using "http://localhost:<SHARING PORT>/" and "http://192.168.0.163:<SHARING PORT>/" ?
Best regards,
Peke
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
How to add SCREENSHOTS to forum
Post Reply