Roon Extension: Roon Web Controller v1.1.1

Even easier, would be great if you and @spockfish could maybe collaborate lol

Using it on Arch Linux on the Core it works for a moment and then it reverts to “This extension is not enabled” even though it is enabled. If I kill it and restart it works for about 60 seconds and then the same.

The screen output is:

<- REQUEST 204 com.roonlabs.ping:1/ping
-> COMPLETE 204 Success

The last output before the pings was:

<- CONTINUE 2 Changed {“zones_changed”:[{“zone_id”:“1601076ad07f01e4b2894bd452da3490e4d8”,“display_name”:“Grace”,“outputs”:[{“output_id”:“1701076ad07f01e4b2894bd452da3490e4d8”,“zone_id”:“1601076ad07f01e4b2894bd452
da3490e4d8”,“can_group_with_output_ids”:[“1701076ad07f01e4b2894bd452da3490e4d8”,“1701adf326a5127d4c43e63dbdc8ddf631cc”,“1701c7783ae2a626252d7518091ed99840bb”],“display_name”:“Grace”,“volume”:{“type”:“db”,“min”:-80
,“max”:0,“value”:-18,“step”:1,“is_muted”:false}}],“state”:“playing”,“is_next_allowed”:true,“is_previous_allowed”:true,“is_pause_allowed”:true,“is_play_allowed”:false,“is_seek_allowed”:true,“settings”:{“loop”:“disa
bled”,“shuffle”:false,“auto_radio”:true},“now_playing”:{“seek_position”:158,“length”:254,“one_line”:{“line1”:“Like the Weather - 10,000 Maniacs”},“two_line”:{“line1”:“Like the Weather”,“line2”:“10,000 Maniacs”},“t
hree_line”:{“line1”:“Like the Weather”,“line2”:“10,000 Maniacs”,“line3”:“MTV Unplugged”},“image_key”:“51669bcff404b53a9deb3ae199f33a10007dae7348f1d78d17164c24e65a786381d563e099b631e0042b962b674ec35fddcc31d505f9085
15f9f09b3da605320e1b52b7c10d675a18ccfcdc42bae409deba8aa548c72100568ca9f7ebaf707ca”}}]}

It shows up twice under authorized extensions. Any help appreciated.

Chester

This is a stab in the dark, but it is possible that the authorization got confused some how.

  • Stop the extension
  • Remove all of the entries for “Web Controller” under “Settings -> Extensions -> View”
  • Remove the “config.json” in the root of the “roon-web-controller” directory
  • Start the extension
  • Enable it in “Settings -> Extensions”

I didn’t have a config.json because of permissions, so I made my user the owner of the dir tree. I now have a config.json, but am getting the same behaviour. Now if I restart, it reuses the previous authorization, but after about 15 to 20 seconds it reverts to the unauthorized message. I could likely provide shell access if you care enough to investigate it. The Roon core is running on Arch as well.

The extension manager still shows it as having been seen “Just now” during the error state, so it seems like the Core is behaving properly.

cw

Can you do me a favor? I would like to see if the page is updating or if there really is a pairing problem.

in the file public/js/site.js, lines 9-20, the code is this:

$(document).ready(function() {
    socket.on("pairStatus", function(payload) {
        pairEnabled=payload.pairEnabled;

        if (pairEnabled == true ) {
            showPage();
            fixFontSize();
        } else {
            showSection('pairDisabled');
        }
    });
});

Change it to this and see if the playing information updates properly:

$(document).ready(function() {
            showPage();
            fixFontSize();
});

For anyone who is interested in testing out the next release, the Release Candidate for the next version is now available in the dev branch on GitHub. The feature list is pretty much locked in, but I will definitely investigate and resolve any bugs that are found.

I am currently doing regression and usability testing as well as working on some improved documentation.

New Features:

  • Library Browser
  • Search (Library Browser -> Library -> Top Line)
  • Added theme button to “Now Playing” screen
  • Split “Now Playing” and “Library” into a standalone pages to allow for custom layouts (example side-by-side layout provided, http://localhost:8080/side-by-side.html)

Upgrade notes:
Due to the use of new Roon APIs, you must remove the old extension authorization and create a new one!

On the Node server:

  1. Stop the extension

In an official Roon Client:

  1. Go to Settings -> Extensions.
  2. Click the “View” button.
  3. Remove all previous instances of “Web Controller”.

On the Node server:

  1. Run git pull
  2. Run npm install
  3. Start the extension node .

In an official Roon Client:

  1. Go to Settings -> Extensions.
  2. Click the “Enable” button beside “Web Controller”.

Get it:
You can get the “dev” branch by running:
git clone -b dev https://github.com/pluggemi/roon-web-controller.git roon-web-controller-dev

This will create a new directory for the dev version. Note that since the main version and the dev version listen on the same port, you will have to stop one to run the other OR create a local configuration file to change the port (see config/local.json.EXAMPLE).

3 Likes

@Mike_Plugge Thanks!

Happy days :grinning:

Works a charm.

Thoughts for consideration:

  • Any way to speed up/ cache list loading or to show progress? Caching would make it a lot snappier. Probably worthwhile caching subtrees in background ahead of user selection e.g. sub-genres.
  • Sort options would be useful e.g. Genres, Albums etc.

@Mike_Plugge running like a boss!
Thanks!

@evand +1!

@Mike_Plugge

It seems I’ve run into a bug…wasn’t doing anything in particular, in fact I’d left it running in Chrome on my Arch laptop and controlled proceedings using my phone whilst relaxing on the sofa.

Got back to find this in the terminal window:

<- REQUEST 2589 com.roonlabs.ping:1/ping -> COMPLETE 2589 Success <- CONTINUE 2 Changed {"zones_changed":[{"zone_id":"16014f7f3ca04ca1e3febdc3d1c8b939822b","display_name":"Mojo","outputs":[{"output_id":"17014f7f3ca04ca1e3febdc3d1c8b939822b","zone_id":"16014f7f3ca04ca1e3febdc3d1c8b939822b","can_group_with_output_ids":["17014f7f3ca04ca1e3febdc3d1c8b939822b"],"display_name":"Mojo","volume":{"type":"number","min":0,"max":100,"value":100,"step":1,"is_muted":true}}],"state":"playing","is_next_allowed":true,"is_previous_allowed":true,"is_pause_allowed":true,"is_play_allowed":false,"is_seek_allowed":true,"settings":{"loop":"disabled","shuffle":false,"auto_radio":true},"now_playing":{"seek_position":94,"length":359,"one_line":{"line1":"What's It All About - Aynsley Lister"},"two_line":{"line1":"What's It All About","line2":"Aynsley Lister"},"three_line":{"line1":"What's It All About","line2":"Aynsley Lister","line3":"Equilibrium"},"image_key":"03d70dbaa4a1a3c810e8a3dab4446269"}}]} <- CONTINUE 2 Changed {"zones_changed":[{"zone_id":"16014f7f3ca04ca1e3febdc3d1c8b939822b","display_name":"Mojo","outputs":[{"output_id":"17014f7f3ca04ca1e3febdc3d1c8b939822b","zone_id":"16014f7f3ca04ca1e3febdc3d1c8b939822b","can_group_with_output_ids":["17014f7f3ca04ca1e3febdc3d1c8b939822b"],"display_name":"Mojo","volume":{"type":"number","min":0,"max":100,"value":100,"step":1,"is_muted":true}}],"state":"playing","is_next_allowed":true,"is_previous_allowed":true,"is_pause_allowed":true,"is_play_allowed":false,"is_seek_allowed":true,"settings":{"loop":"disabled","shuffle":false,"auto_radio":true},"now_playing":{"seek_position":95,"length":359,"one_line":{"line1":"What's It All About - Aynsley Lister"},"two_line":{"line1":"What's It All About","line2":"Aynsley Lister"},"three_line":{"line1":"What's It All About","line2":"Aynsley Lister","line3":"Equilibrium"},"image_key":"03d70dbaa4a1a3c810e8a3dab4446269"}}]} ignoring malformed moo msg

In browser window it reported:

This extension is not enabled. Please use a Roon client to enable it.

Small bug… the background resets to default every so often.

Both great ideas. Sorting the Genre is something I can look into, but I do not think it is something I can implement. What is showed is what the API returns and it is based on the number of albums/artists in each of the Genres. It is the same order as in the official client. The order is dictated by the “item_key” value (see below). Sorting this would take operations on an intermediate array which could slow things down a bit. This would break further if there are more than 100 entries since the API always returns a maximum of 100 entries - even if the application requests another list size. Same is true for the Album sort.

There is a little bit of control over the Artist and Composer sort options in the “Settings” section - but those are both options that are provided by the API, so it controls what the server returns.

Unfortunately, caching is impractical based on what the Roon API provides. (I REALLY wanted to do caching, but couldn’t!)

For a better explanation, I will give you an example of a typical flow of data as returned by the API.

Click home:

[ { title: 'Library',
    subtitle: null,
    image_key: null,
    item_key: '1572:0' },
  { title: 'Playlists',
    subtitle: null,
    image_key: null,
    item_key: '1572:1' },
  { title: 'Internet Radio',
    subtitle: null,
    image_key: null,
    item_key: '1572:2' },
  { title: 'Genres',
    subtitle: null,
    image_key: null,
    item_key: '1572:3' },
  { title: 'Settings',
    subtitle: null,
    image_key: null,
    item_key: '1572:4' } ]

Click Library:

[ { title: 'Search',
    subtitle: null,
    image_key: null,
    item_key: '1573:0',
    input_prompt: { prompt: 'Search', action: 'Go' } },
  { title: 'Artists',
    subtitle: null,
    image_key: null,
    item_key: '1573:1' },
  { title: 'Albums',
    subtitle: null,
    image_key: null,
    item_key: '1573:2' },
  { title: 'Tracks',
    subtitle: null,
    image_key: null,
    item_key: '1573:3' },
  { title: 'Composers',
    subtitle: null,
    image_key: null,
    item_key: '1573:4' } ]

Click Home:

[ { title: 'Library',
    subtitle: null,
    image_key: null,
    item_key: '1574:0' },
  { title: 'Playlists',
    subtitle: null,
    image_key: null,
    item_key: '1574:1' },
  { title: 'Internet Radio',
    subtitle: null,
    image_key: null,
    item_key: '1574:2' },
  { title: 'Genres',
    subtitle: null,
    image_key: null,
    item_key: '1574:3' },
  { title: 'Settings',
    subtitle: null,
    image_key: null,
    item_key: '1574:4' } ]

Notice that the “item_key” field increments with every click. Unfortunately that is what is returned by the API. This behavior is mentioned in these threads as well (Browse API questions and Questions on Browse APIs). And that means that any entry that is cached will have an old/incorrect “item_key” - and navigation fails with an incorrect “item_key”. So caching is not useful.

Unfortunately this also means that if you start browsing on one device, move to another device, then return to the original device, the original device will not browse until you hit the “Refresh” icon to get the current “item_key” (which incidentally is why it is there! :slight_smile:)

The ever changing “item_key” is also one of the reasons why the web app uses HTTP POST to retrieve data from the Node server. HTTP POST requests are never cached and cannot be bookmarked, whereas HTTP GET requests can be.

Another reason is the fact that HTTP POST requests have an unlimited body size, whereas HTTP GET requests are limited to a URL length of 2,048 characters - which may be an issue if components of this web app is embedded in another web app. And since one of the features of this release is support for being embedded in other web pages, URL length could become an issue.

As for this one, that is being returned by the Roon API. That exact message is produced on line 162 of node_modules/node-roon-api/moo.js.

This is likely a connectivity issue between the Node application and the Roon Server itself. It is quite weird to see the number jump from “COMPLETE 2589” to “CONTINUE 2”. Those numbers are typically sequential, so I would have expected “2590” instead of “2”.

Between the Node application and the Roon Server, do you have any network connectivity issues such as Wifi dropping out? Laptop going to sleep? Network Manager acting weird?

Weird - I noticed that too after doing some JSHint related code clean up. I think it has to do with the settings or the state variables being reset because it is actually the theme being reset. Using the color theme will reset to the dark theme (the default) as well…

Lemme do some investigation on that. I just opened an internal bug for this.

1 Like

possibly, the whole setup is wifi … roon server to endpoint, laptop to roon server. I’ll keep an eye on it.

A few more suggestions:

  • It’d be nice to be able to see the bit depth and bitrate of the track that’s being played.
  • Could search be made universally accessible?
  • Recently added albums would be a welcome addition too
  • As would genre information in now playing
1 Like

I know I’m asking a lot, but @Mike_Plugge I suspect you knew it inevitable when you embarked on this project…

Could artist names, album names, track names and Genres be made clickable throughout e.g. clicking on the artist name in now playing takes you to their discography?

All great suggestions and oddly - all things I also wanted. But the API does not provide bit depth or new additions.

Clickable genres, artist, album, and tracks? Tough because of the previously mentioned “item_key” issue.

That and the fact that the “library” and the “now playing” screen are actually 2 completely separate HTML files that do not interact with each other. They are iframes in a 3rd html page used for layout. This was done to support embedding the widgets in other web pages but also to keep the code cleaner.

Universal search location is doable but would require that element to constantly be updated with the current “item_key”. Possibly next version.

I also wanted to do play queue management. But that is not exposed in the API either.

1 Like

Just wanted to say thanks for your efforts. It’s great having the ability to control Roon directly from a browser (and more so in my case from a laptop running Linux). I finally don’t have to go looking for a tablet or phone just to select and play an album.

2 Likes