ChriD / node-raumserver

A nodejs module/server to control the raumfeld multiroomsystem via HTTP-Requests
58 stars 14 forks source link

Adding actual playling title to playlist #71

Closed davie2000 closed 5 years ago

davie2000 commented 5 years ago

As discussed shortly earlier (issue #69) and as follow-up to issue #49 I want to use node-raumserver to add the actual playing title in a given room to a given playlist; something like: addTitleToPlaylist?room=WoZi&playlist=SongsWeLike

Finally I have to add a new requestHandler 'lib.request.addTitleToPlaylist.js' which fires the raumkernel-action addItemToPlaylist(_playlistName, _mediaItemId) from lib.queueController.nativePlaylist.js.

But how can I get the "_mediaItemId" of the actual playing song in room "WoZi"? And how can I get an object of type "Raumkernel.queueController.nativePlaylist" to call the method?

Answers are appreciated from everybody, not just ChriD ;-)

ChriD commented 5 years ago

But how can I get the "_mediaItemId" of the actual playing song in room "WoZi"?

You can look at the gentRendererStateRequest. There you can see how to get the mediaRenderer Object. And on the mediaRenderer Object, there should be a rendererState object and in the rendererState object there should be a mediaItem object which representates the current mediaItem which is played on the zone renderer. I think you can do something like following in the request class:

var mediaRenderer = this.managerDisposer.deviceManager.getVirtualMediaRenderer(id)
mediaRenderer.rendererState.mediaItem.iDontKnowTheKeys

And how can I get an object of type "Raumkernel.queueController.nativePlaylist" to call the method?

There should be a raumkernel object in all of the requests so you should be able to do following this.raumkernel.nativePlaylistController.addItemToPlaylist("RAUMKERNELTEST", "0/My Music/Artists/4%20Non%20Blondes/4%20Non%20Blondes+What%27s%20Up", 294967295, true);

davie2000 commented 5 years ago

Thanks for your fast answer, ChriD!

I was creating a new class "Request_AddItemToPlaylist" (file: "...lib/requestHandlers/lib.request.addItemToPlaylist.js") with this content: https://pastebin.com/VAZa82Zk

When I call "addItemToPlaylist?id=WoZi&playlist=BestOf" then I got the error errorMessage | "TypeError: Cannot read property 'refID' of undefined" So my mediaRenderer is undefined yet and 'refID' seems to be wrong somehow.

I took a look at the answer from "getRendererState" and found that the value of "refID" (underneath "mediaItem") looked like the right identifier ("0/My Music/AllTracks/8c6db9bc365e0ad1a772e5493944423d"). The error comes independently from using mediaRenderer.rendererState.mediaItem.refID or ...mediaItem["refID"]

ChriD commented 5 years ago

I think you are almost there. In fact you can use the given parameter _mediaRendererVirtual instead of using var mediaRenderer = this.managerDisposer.deviceManager.getVirtualMediaRenderer(id) (sorry for that, i did not have a sight on the code as i wrote this) That won't fix the problem though. But try to use currentMediaItemData instead of mediaItem. That may do the trick.

And you may consider renaming the request to something like Request_AddCurrentItemToPlaylist? Only to be sure there will be no conflict in future (as we may need a AddItemToPlaylist request where we can provide the itemReference?)

davie2000 commented 5 years ago

Thank you very much again for your fast and helpful answer! I changed the code as you advised, but still getting the same error.

It seems that capitalized variables (in answer of "getRendererState") are usable in the requestHandler and others are not. So _mediaRendererVirtual.rendererState.CurrentTransportActions is filled (e.g. "Next,Pause,...") but _mediaRendererVirtual.rendererState.udn or ...mediaItem is still "undefined".

Here is my newest code showing that: https://pastebin.com/WAtP9m6b errorMessage | "Error: blaNext,Pause,Previous,Repeat,Seek,Shuffle,Stopbluundefined"

ChriD commented 5 years ago

use _mediaRendererVirtual.currentMediaItemData instead of _mediaRendererVirtual.rendererState.currentMediaItem

( i am not sure if refID is present on the currentMediaItemData or its something like containerId, so you may output the result of JSON.stringify(_mediaRendererVirtual.currentMediaItemData), then you can see whats present)

davie2000 commented 5 years ago

"Data" did the trick - thank you very much, man! You have my deepest respect for helping "from the far" with having all the code in mind!!!

Here is the working version of the new requestHandler addCurrentItemToPlaylist: https://pastebin.com/2suu9bcv Tested with and implemented for only one physical Raumfeld Box!

You can use it for example to add the currently playing title to an existing playlist called "BestOf" like this: http://192.168.xxx.xxx:8080/raumserver/controller/addCurrentItemToPlaylist?playlist=BestOf

Next step is to package this command into a "shortcut" to call it with Siri similar to "Hey Siri, like this song". So we can easily sort songs we like or don't like ("Hey Siri, don't like this song") ... and gives me the chance to clean up our (manually maintained) imported playlists afterwards.

PS: @ChriD Maybe you want to extend and clean-up the code and put it into your sources? However, this thread is solved for me.

ChriD commented 5 years ago

Good to hear that it worked! I'll add the request to the repository. I hope i can do it on the weekend.

Thank you for contributing :-)

ChriD commented 5 years ago

This is a copy from pastebin for me to create the request and to not loose the code ;-)

'use strict';
var RequestMediaRenderer = require('../lib.base.requestMediaRenderer');

module.exports = class Request_AddCurrentItemToPlaylist extends RequestMediaRenderer
{
    constructor()
    {
        super();
    }

    runAction(_resolve, _reject, _mediaRendererVirtual, _mediaRendererRoom, _roomUdn)
    {
        var _playlistName = this.getQueryValue("playlist");
        var _mediaItemId = _mediaRendererVirtual.currentMediaItemData.refID; // actual playing track

                if(!_playlistName)
        {
            this.logError("'playlist' parameter has to be set");
            _reject(new Error("'playlist' parameter has to be set"));
            return;
                }

        if(_mediaItemId)
        {
            this.raumkernel.nativePlaylistController.addItemToPlaylist(_playlistName, _mediaItemId).then(function(_data){
                    _resolve(_data);
                }).catch(function(_data){
                    _reject(_data);
                });
        }
        else
        {
                    this.logError("Currently playing track is not available!");
            _reject(new Error("Currently playing track is not available!"));
        }
    }

}
davie2000 commented 5 years ago

Here one can find the whole "Siri-Story": Raumfeld mit Siri steuern - Anleitung (german only)

ChriD commented 5 years ago

added to master branch and published to npm