This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

SONOS app
#61
Hi Erwin,

this solution with Javascript is amazing, it's update immediatly and not overload the CPU not at all,

Thank you very much!!!
Reply
#62
Hi,

Yes i know, this is almost the same approach as the app uses, should have thought about it sooner..

When virtual objects are implemented you can use one of the both methodes.

You probably need a extra condition on media type (track or radio) as the album is not part of the radio stream data. So if media type is radio you probably want to hide or flip the text labels where data is written to.

BR,

Erwin
Reply
#63
Hi Erwin,

I understand I need a javascript code for every Sonos device, Can I use the same label for a additional classes if I have different pages for a Sonos device or is better than I define for example .album_S1, .album_S2, etc

It's possible to add "%" symbol at the end of volume value?

THX.
Reply
#64
Hi,

For adding suffix to values you can simply add them like this:

$(".volume_s1").html(res_parsed[0].volume + ' %');

BR,

Erwin
Reply
#65
Hi Erwin,
I am currently testing the sonos-app and noticed a problem with the favorites-part.
I am using an applemusic-playlist as a favorite - when selecting/loading it (gui or through http-commands) nothing happens - starts playing whatever is in queue. I thought it had something to do with the apple-play-list but when using a sonos-playlist as a favorite the same thing happened. Using a radio station as a favorite works fine and loading the same sonos-playlist from the playlists works fine also.
My plan is to use a KNX-trigger to switch between multiple favorites (radio-stations and apple-music-playlist). I want to use apple-music playlists since it is very easy to use itunes for updating and syncing across all apple-devices and sonos. Hope you can figure this one out.

Some other question i have: i want to use my sonos as doorbell and text-to-speech device: so when playing radio/playlist i would like to interrupt the music, either play an mp3 (doorbell) or a generated mp3 (tts using voiceRSS - this is free for 350 messages a day), and continue the music at the point where it was before.
With the radio station this is no issue but with the playlist it is a different story: i would need to store the tracknumber and time-position in the song and restore that after playing the doorbell/generated-mp3. Any ideas on how to do this? (might be usefull for other people also).
Thanks again for all the help,
Bart
Reply
#66
Hi Bart,

I will check your point for favorites, but you can solve it for now by using a playlist. Playlist can be loaded and optional auto started by this command:

Code:
http://127.0.0.1/apps/data/sonos/sonos.lp?action=loadplaylist&ip=192.168.10.31&listname=My_Playlist&autoplay=true -- use _ for spaces in the name

-- or

http://127.0.0.1/apps/data/sonos/sonos.lp?action=loadplaylist&name=Woon_Kamer&listname=My_Playlist&autoplay=true -- use _ for spaces in the name

For doorbell i will check also how to do this and come back to this asap..

BR,

Erwin
Reply
#67
Hi Erwin,

Is it possible to define another condition for mediatype to hide / show information when the source is TV in a Sonos Play Bar?

BR
Reply
#68
Hi Josep,

No, currently the protocolInfo is detecting only "x-rincon-mp3radio" and "aac" as mediatype 'radio', all others are mediatype 'track'

What you could do is check the first part of the trackuri, it holds the protocolInfo as start..

Use this to fetch it:

Code:
var protocolinfo = res_parsed[5].trackuri.match("x(.*)://");
//console.log(protocolinfo[0])
if (protocolinfo[0] == 'yourdetectedprotocoltype'){
//do your action
}

BR,

Erwin
Reply
#69
Hi Bart,

I added yesterday evening the interupt audio for doorbell and spoken messages to the app (soon as update available) and did it like this:

Code:
http://192.168.10.201/apps/data/sonos/sonos.lp?action=say&ip=192.168.10.32&audiofile=www.yourdomain.com/doorbell.mp3&volume=50&duration=8

With this command it's possible to trigger a audiofile on any player you like (make sure to send it to the master if you have groups), you can set free audio URL, set the volume during interuption and set the total duration of the interuption (depending on your audiofile lenght) and after play the file / interuption it will return to the old state (continue where it was and with old volume)

You can also trigger all players (coordinators and single players) so all groups and players are started at once by using this:

Code:
http://192.168.10.201/apps/data/sonos/sonos.lp?action=sayall&audiofile=www.yourdomain/doorbell.mp3&volume=50&duration=8

PS: I noticed they sell boxes on the internet that offer this function for around €500,- (: But i have to say it's a real cool function Smile

BR,

Erwin
Reply
#70
Hi Erwin,

I would like to know if its possible to add a time bar into visualization using CSS or Javascript. Like this image that I attach, thanks!

   
Reply
#71
Hi Josep,

Yes almost anything is possible, you just have to know how to do it (;

This one is quite tricky as the duration and playing time are strings like 0:00:00 from sonos so you have to split them, multiply them and calculate the percentage between start and end and the current position. 

With this 0-100% (var passed) you can scale a element to your bar.

Here is the code i used in the app:

Code:
function FormattedTimeToSeconds(formattedtime) {
    var a = formattedtime.split(':'); // split it at the colons
    // minutes are worth 60 seconds. Hours are worth 60 minutes. 
    var seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); 
    return seconds;
}

var passed = 0;
var durationseconds = FormattedTimeToSeconds(duration);
var playingtimeseconds = FormattedTimeToSeconds(playingtime)
if (durationseconds > playingtimeseconds){
    passed = durationseconds - (durationseconds - playingtimeseconds);
    passed = Math.floor(((passed / durationseconds) * 100) * 1); // set to * x for each 100px
} else {
    passed = 0;
}

BR,

Erwin
Reply
#72
Hi Erwin,

Thank you very much, This function FormattedTimeSeconds is very interesting for use in other places too, I only have an another question, I don't understand very well how CSS works, it is possible to define a bar with this format without modify the rest of the bars format or when I change the CSS in bar element this change in everything?
Reply
#73
Hi Josep,

Use a 3 byte RGB object, set it to read only and give it the additional class 'playprogress' and pick any color on the object (;

Then use this script:

Code:
     function FormattedTimeToSeconds(formattedtime) {
       var a = formattedtime.split(':'); // split it at the colons
       // minutes are worth 60 seconds. Hours are worth 60 minutes. 
       var seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); 
       return seconds;
       }

     var passed = 0;
     var durationseconds = FormattedTimeToSeconds(res_parsed[6].duration);
     var playingtimeseconds = FormattedTimeToSeconds(res_parsed[7].playingtime)
     if (durationseconds > playingtimeseconds){
         passed = durationseconds - (durationseconds - playingtimeseconds);
         passed = Math.floor(((passed / durationseconds) * 100) * 4); // set to * x for each 100px
     } else {
         passed = 0;
     }  
     $("#plan-" + currentPlanId).find(".playprogress").css( "min-width", "0px", 'important' );
     $("#plan-" + currentPlanId).find(".playprogress").css( "max-width", passed + "px", 'important' );
     $("#plan-" + currentPlanId).find(".playprogress").css( "width", passed + "px" );

BR,

Erwin
Reply
#74
App has been updated to the latest in the store.
Reply
#75
Erwin, you have to use another class name, because "progress" is used by sliders and this will break any slider in the same plan. You can use several classes if needed, but the one you are targeting via JS must not clash with base class names.
Reply
#76
Hi Admin,

Thanks (: I should have known this..

The class is changed in the sample now.

BR,

Erwin
Reply
#77
Hi Erwin,

I put this code into Java Script section, I make a 3byte object read only and only value display and with playprogress in additiona class but it's not working, it's correct to put this code in Javascript section?
Reply
#78
Hi,

Yes, but you have to place it inside the polling routine you already have.

BR,

Erwin
Reply
#79
Hi Erwin,

This code that I put into custom Javascript section I need to recall ciclally? How can I make this? Thank you.

Sorry Erwin,

I put the code into Sonos javascript previous sentence and now I works fine, It's possible to change the bar dessigns, making the ends not rounded or change the size and height?

Thank you very much!
Reply
#80
Hi Josep,

Here is the full (renewed) sample:

Code:
$(function(){
 setInterval(function(){
   // Only poll if current page = 1
   //console.log(currentPlanId)
   var sonosip = "127.0.0.1"
   if (currentPlanId == 1 || currentPlanId == 2 || currentPlanId == 3  ){
     if (currentPlanId == 1 ) {
         sonosip = "192.168.10.26"
     }
     if (currentPlanId == 2 ) {
         sonosip = "192.168.10.27"
     }
     if (currentPlanId == 3 ) {
         sonosip = "192.168.10.28"
     }
     // Request data from sonos API
     $.post("/apps/data/sonos/sonos.lp",
     { action: "getextendedstate", ip: sonosip },
     function(data) {
     var res_parsed = JSON.parse(data);
       if (typeof data !== 'undefined'){
         //console.log(res_parsed)

         var protocolinfo = res_parsed[5].trackuri.match("x(.*)://");
         //console.log(protocolinfo[0])

         // Update text label with additional class 'volume'
         $("#plan-" + currentPlanId).find(".volume").html(res_parsed[0].volume + ' %');

         // Update text label with additional class 'mute'
         $("#plan-" + currentPlanId).find(".mute").html(res_parsed[1].mute);

         // Update text label with additional class 'crossfade'
         $("#plan-" + currentPlanId).find(".crossfade").html(res_parsed[2].crossfade);

         // Update text label with additional class 'playmode'    
         $("#plan-" + currentPlanId).find(".playmode").html(res_parsed[3].playmode);

         // Update text label with additional class 'transport'
         $("#plan-" + currentPlanId).find(".transport").html(res_parsed[4].transport);

         // Update text label with additional class 'trackuri'
         $("#plan-" + currentPlanId).find(".trackuri").html(res_parsed[5].trackuri);

         // Update text label with additional class 'duration'
         $("#plan-" + currentPlanId).find(".duration").html(res_parsed[6].duration);

         // Update text label with additional class 'playingtime'
         $("#plan-" + currentPlanId).find(".playingtime").html(res_parsed[7].playingtime);

         // Update text label with additional class 'tracktitle'
         $("#plan-" + currentPlanId).find(".tracktitle").html(res_parsed[8].tracktitle);

         // Update text label with additional class 'creator'
         $("#plan-" + currentPlanId).find(".creator").html(res_parsed[9].creator);

         // Hide Album when mediatype = radio
         if (res_parsed[12].mediatype == 'radio'){
           $("#plan-" + currentPlanId).find(".album").css( "display", "none" );
         } else {
           $("#plan-" + currentPlanId).find(".album").css( "display", "block" );
           // Update text label with additional class 'album'
           $("#plan-" + currentPlanId).find(".album").html(res_parsed[10].album);
         }

         // Update image container with additional class 'albumart'
         $("#plan-" + currentPlanId).find(".albumart").find("img").attr('src', res_parsed[11].albumart);

         // Update text label with additional class 'mediatype'
         $("#plan-" + currentPlanId).find(".mediatype").html(res_parsed[12].mediatype);
         //$("#plan-" + currentPlanId).find(".trackuri").html(res_parsed[13].trackuri);
         //$("#plan-" + currentPlanId).find(".trackurimetadata").html(res_parsed[14].trackurimetadata);
         //$("#plan-" + currentPlanId).find(".albumartbase64").html(res_parsed[15].albumartbase64);
         //$("#plan-" + currentPlanId).find(".sonosplayerip").html(res_parsed[16].sonosplayerip);

         function FormattedTimeToSeconds(formattedtime) {
           var a = formattedtime.split(':'); // split it at the colons
           // minutes are worth 60 seconds. Hours are worth 60 minutes.
           var seconds = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]);
           return seconds;
         }

         var passed = 0;
         var durationseconds = FormattedTimeToSeconds(res_parsed[6].duration);
         var playingtimeseconds = FormattedTimeToSeconds(res_parsed[7].playingtime)
         if (durationseconds > playingtimeseconds){
             passed = durationseconds - (durationseconds - playingtimeseconds);
             passed = Math.floor(((passed / durationseconds) * 100) * 4); // set to * x for each 100px
         } else {
             passed = 0;
         }  
         $("#plan-" + currentPlanId).find(".playprogress").css("min-width", "0px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("height", "15px", 'important');
          $("#plan-" + currentPlanId).find(".playprogress").css("border-radius", "0px", 'important');
         $("#plan-" + currentPlanId).find(".playprogress").css("max-width", passed + "px", 'important');
         $("#plan-" + currentPlanId).find(".playprogress").css("width", passed + "px");
       }
   }
 ); }; }, 1000);
});

BR,

Erwin
Reply


Forum Jump: