Roon extension - http APIs

Hi Francois,

I’m not in front of the computer right now, but I remember having this issue as well.

Please make sure that there are no leading and trailing spaces from the copy/pasted zone or output ids from list_zones (especially at the very end of the url)

What I did was write the url into notes and remove all the spaces before pasting it to the browser.

Let me know if you are still having this issue.

Bastian

working now thanks! did have a space in there.

one more thing I’d like to do is add a call for playing a specific play list in a zone - is there an API for this as well, if so how would I call it?

Thanks again - happy w the transfer working

Francois

Hi Francois,

Yes, you can use the roon’s browse apis.
If you’d like to see some examples, you can try the browse/player pages on either my GitHub’s http or ws repositories.

For the http repository, you can go straight to browse.html (as it will let you select the zone)
or for the ws repository, open player.html and click on the search icon.

There are several limitations on using the browse APIs, the biggest one is that we can’t use multiple clients at the same time.

Let me know if you have any further questions.

Bastian

Hi @ben

You helped me out on the APIs in the past. I don’t know whether you are still in charge of the APIs. if you are not, could you please forward this question.

I was looking at the roon’s browse api documentation at https://roonlabs.github.io/node-roon-api/RoonApiBrowse.html

And I saw the “multi_session_key” property. and from the description, it says

If your application browses several instances of the same hierarchy at the same time, you can populate this to distinguish between them. Most applications will omit this field.

I tried adding this to the call, but the returning item_key stays the same and i subsequent calls using the item_key and multi_session_key will result in “invalid key”.

Am i correct in understanding the multi_session_key is to have several browser/client to traverse the roon browse api independently? if so, could you please let me know how to call it properly?

Here’s my code:

calling refresh_browse (I added the multi_session_key to the opts array):

refresh_browse( req.query['zoneId'], { item_key: req.query['item_key'], input: req.query['toSearch'] , req.query['multiSessionKey] }, 0, 100, function(myList) { ... }

and on refresh_browse:

function refresh_browse(zone_id, opts, page, listPerPage, cb) {
    var items = [];
    opts = Object.assign({
        hierarchy:          "browse",
        zone_or_output_id:  zone_id,
    }, opts);


    core.services.RoonApiBrowse.browse(opts, (err, r) => {
        if (err) { console.log(err, r); return; }

        if (r.action == 'list') {
            page = ( page - 1 ) * listPerPage;

            core.services.RoonApiBrowse.load({
                hierarchy:          "browse",
                offset:             page,
                set_display_offset: listPerPage,
            }, (err, r) => {
                items = r.items;

                cb(r.items);
            });
        }
    });
}

Thank you very much for your help.

Bastian

I am still the best person to ask this sort of question, hopefully I can arrange to not take so long to answer next time.

That is my understanding of how it should work also.

This looks like maybe it should be this:

refresh_browse( req.query['zoneId'], { item_key: req.query['item_key'], input: req.query['toSearch'] , multi_session_key: req.query['multiSessionKey] }, 0, 100, function(myList) { ... }

If that doesn’t work, could you upload the rest of your extension code somewhere I can get at it? I’ve been putting off responding here because the trivial seeming steps between this code and a running extension seemed too much.

Hi @ben,

Thank you for your reply.

I have made a branch to the repository and added the multi_session_key into the opts of refresh_browse at apps.js.

You can find the branch here: https://github.com/st0g1e/roon-extension-ws-player/tree/multipleSessionBrowseCall

The call looks like this:

refresh_browse( req.query['zoneId'], { pop_all: true, multi_session_key: req.query['multiSessionKey'] }, 1, 100, function(myList) { ... }

and the result list is:

{
  "list": [{
    "title": "Library",
    "subtitle": null,
    "image_key": null,
    "item_key": "8:0",
    "hint": "list"
  }, {
    "title": "Playlists",
    "subtitle": null,
    "image_key": null,
    "item_key": "8:1",
    "hint": "list"
  }, {
    "title": "Internet Radio",
    "subtitle": null,
    "image_key": null,
    "item_key": "8:2",
    "hint": "list"
  }, {
    "title": "Genres",
    "subtitle": null,
    "image_key": null,
    "item_key": "8:3",
    "hint": "list"
  }, {
    "title": "Settings",
    "subtitle": null,
    "image_key": null,
    "item_key": "8:4",
    "hint": "list"
  }]
}

No matter how many times and with different multi_session_key, the item_key are still in the 8: range.

Here are the urls to test:

  1. Get the zones list: http://localhost:3002/roonAPI/listZones
  2. Call the goHome (with the zones from step 1): http://localhost:3002/roonAPI/goHome?zoneId=16017ba12aad269dbdcdd1c14960b5e76ae3&multiSessionKey=12345&list_size=20

Thank you very much for your help.

Bastian

Simple fix, just needed to also pass the multi_session_key to the load request: https://github.com/st0g1e/roon-extension-ws-player/pull/4

2 Likes

It works! Thank you for your help.

One other question i just found out.
On MacOS’ Finder, if I right click on a music file (i tried with flac and m4a) and select “Open With” and choose “Roon()”, then roon crashed.

Were we supposed to be able to open a track this way? i also cannot find Roon’s dictionary on the Script Editor.

Is there anyway that we can open a music file programmatically? i remember reading there is a roon:// format but don’t know much about it.

Thank you again for your help

Bastian

Hi Bastian - sorry of I am a being a bit slow… could you just give example syntax for starting to play an album (or song, or artist) using http call? Also can you use the name of the album of son or can the api only take an ID number?

I am exploring using Snips to start a song/playlist/album/genre calling the Roon API. There are examples using Spotify so should not be too hard, but I obviously need to be able to call a specific item to play in Roon…

Thanks!

Francois

Hi Francois,

Currently there is no way to play tracks or playlist directly that I know of.
The only way is by using roon’s Browse API which returns one level of information at a time.

At the top level, I believe it’s something like (there are more than the following 3);

  • artist
  • playlist
  • radio

Then when you call the api again using the returned data, it will give the next level down. For example, if we pick the artist data:

Artists
  Artist1
  Artist2
     Album1
  Artist3
     Album1
       Track1
       Track2
     Album2
  Artist4

The code which calls roon’s browse api is in apps.js in the refresh_browse function

Hope this helps,
Bastian

I’ve made some Domoticz scripts to start, stop and volume control my Roon devices with these http calls:

http://10.0.0.17:3001/roonAPI/play?zoneId=16016f52e38b6aa9dfe6a4724aa957e484ec
http://10.0.0.17:3001/roonAPI/change_volume?volume=32&outputId=17016f52e38b6aa9dfe6a4724aa957e484ec
http://10.0.0.17:3001/roonAPI/stop?zoneId=16016f52e38b6aa9dfe6a4724aa957e484ec

This is working fine as long as there is a playlist or internet radio assigned to that Roon device. If there is nothing assigned to the Roon device, I would like know the API calls to assign a playlist or radio station to the device. Can that be done with API calls?

Hi @Ron_Witkamp,

There is no straight way to get the playlist and radio list. You can use Roon’s browse api to get the list.

You can look at browse.html (which is called from player.html) on my websocket repository. The piece of code that might interest you is the search() function in browse.js Where it programmatically returns the searched string for Artists, Albums, playlists, and radios.

I’m currently traveling so apologize if it takes a while for me to reply.

Bastian

Thanks Bastian, I will have a look at that code. Enjoy your travel!!!

I once used this as a widget on my iPhone.
I just installed Extensions on my SonicTransporter.

Can anyone confirm this is working?

I don’t get it working.
Only previous, play/pause, next, so the zones isn’t showing.

The Roon remote is working though.

Hi @R1200CL,

I just tested it and it works on my end using iphone’s Safari.

May I know what you mean by widget? Please make sure that the IP address points to the sonictransporter’s.

If you have not change the port when enabling the extension on Roon’s extension page, the url should be similar to:
xxx.xxx.xxx.xxx:3002

Where xxx.xxx.xxx.xxx is your sonictransporter’s is address.

Hope this helps.

Hi @ben,

You helped me out in the past on using roon’s APIs.

I have created a new repository to do the following:

  1. Play the current track to other player (I managed to do this to Audirvana for local files)

  2. List by folder and play the album

  3. Manage Box Sets

I managed to get to these list by exporting all tracks from roon and get their file locations.
Currently it works as long as there are no duplicates.

It would be better if we can play a track/album by the file locations (urls). Is it possible to do this?

Thanks,
bastian

There isn’t an easy way to do this in Roon or the API currently. I can’t comment much on what we might do in the future, mostly because I don’t know. I do think that playing tracks by file location is kinda working against the way Roon is structured.

@ben,

Thanks for your reply.
While I understand the reason why this will not be able to do in Roon’s UI. I hoped that we would be able to do it through the API.

Thanks for the amazing work on these API’s, it really made my day to be able to control Roon for each room in our house by simply talking to Siri or pressing a button in homekit (through homebridge)

To share some of the love, I’ve put your work into a docker container and added a few simple things to make it simpler to run.

Tested on Arm (rpi4, 2GB) and it sticks nicely under the 10 MB memory usage.

https://hub.docker.com/r/keesromkes/roonhttpapi

Feel free to comment or add pull requests in my repo.

Hello, I am writing a lot of automation for various devices with a product named neeo. You can see my github on jac459 (and check the metadriver).
Now I’d like to write an integration for roon. Is this http api still the best option? I didn’t manage to find anything from roon directly except their node api which is not what I am looking for. Thanks in advance for your advises.