Hi!
Um in einem Lied spulen zu können brauchen wir eine Art Zeitleisten-Schieberegler.
multimedia.music nimmt dafür einen basic.slider. Allerdings braucht es da mindestens im Hintergrund eine Logik, die die aktuelle Spielzeit auf einen fixen Wert normiert und den Schieberegler-Wert auch entsprechend wieder skaliert. Zudem ist mir unklar, in welcher weise die Zeitleiste aktualisiert wird (der Reiter muss sich ja langsam nach rechts bewegen).
Zudem finde ich es gut, wenn der Slider deaktiviert wird, wenn ein Stream gespielt wird, weil man dann - zumindest bei der Squeezebox - nichts sinnvolles mehr damit anstellen kann.
Daraus ergab sich für mich der Bedarf für mehrere Sachen:
- Slider mit per GAD veränderbaren Max
- Slider der deaktiviert werden kann
- Slider der sich periodisch neue Werte holt ("io.read"?)
Referenz zum Plugin-Thread im sh.py Subforum: https://knx-user-forum.de/smarthome-...nregungen.html
Ich habs versucht:
(alle Dateien in das eigene Pages-Verzeichnis!)
widget_my.html
visu.js
widget_squeezebox.html
Beispieleinbindung in eine Visu-Seite:
Es fehlt quasi ein (zweiter) Timer, der periodisch den Slider vorbewegt (oder das GAD aktiv "polled" - evtl. uncool). Da dies aber nur passieren sollte, wenn auch das "Play"-GAD aktiv ist, müsste man hier schon viele Sachen berücksichtigen.
Evtl. konsolidiert man das ganze auch in ein großer Widget, was quasi alle GADs der Squeezebox nimmt und gleich darauf korrekt reagiert. Evtl. ist das am Ressoucenschonendsten - aber das pack ich nicht wenn mir kein Kenner hilft bzw. mir nicht sagt, dass dieser Weg gangbar und sinnvoll ist. Meine Idealvorstellung ist halt ein dickes Widget, wo auch das Playlisten-Popup evtl. mit abgefrühstückt wird!
Grüße
Robert
Um in einem Lied spulen zu können brauchen wir eine Art Zeitleisten-Schieberegler.
multimedia.music nimmt dafür einen basic.slider. Allerdings braucht es da mindestens im Hintergrund eine Logik, die die aktuelle Spielzeit auf einen fixen Wert normiert und den Schieberegler-Wert auch entsprechend wieder skaliert. Zudem ist mir unklar, in welcher weise die Zeitleiste aktualisiert wird (der Reiter muss sich ja langsam nach rechts bewegen).
Zudem finde ich es gut, wenn der Slider deaktiviert wird, wenn ein Stream gespielt wird, weil man dann - zumindest bei der Squeezebox - nichts sinnvolles mehr damit anstellen kann.
Daraus ergab sich für mich der Bedarf für mehrere Sachen:
- Slider mit per GAD veränderbaren Max
- Slider der deaktiviert werden kann
- Slider der sich periodisch neue Werte holt ("io.read"?)
Referenz zum Plugin-Thread im sh.py Subforum: https://knx-user-forum.de/smarthome-...nregungen.html
Ich habs versucht:
(alle Dateien in das eigene Pages-Verzeichnis!)
widget_my.html
HTML-Code:
/** * A list with selectable item * * @param unique id for this widget * @param a gad/item for the list * @param a gad/item for the selected item * @param the text to be displayed on top of the list */ {% macro list(id, gad_list, gad_item, txt ) %} <ul id="{{ uid(page, id) }}" data-widget="basic.list" data-item="{{ gad_list }}, {{ gad_item }}" data-role="listview" data-dividertheme="c"> <li data-icon="false"><a href="#">View details</a></li> <li data-icon="false"><a href="#">Edit</a></li> <li data-icon="false"><a href="#">Disable</a></li> <li data-icon="false"><a href="#">Delete</a></li> </ul> {% endmacro %} /** * Displays a slider-control * * @param unique id for this widget * @param a gad/item current time (progress) * @param a gad/item total duration (maximum) * @param seconds between two values (optional, default 5s) * @param the orientation ('none', 'vertical', 'bottomup', 'semicircle') */ {% macro time_slider(id, gad_time, gad_duration, step, mode) %} <input id="{{ uid(page, id) }}" data-widget="my.time_slider" data-item="{{ gad_time }}, {{ gad_duration }}" type="range" value="0" min="0" max="1" disabled="1" step="{{ step|default(5) }}" orientation="{{ mode }}" data-highlight="true" /> {% endmacro %}
Code:
// ----- my.list ------------------------------------------------------------ $(document).delegate('a[data-widget="my.list"]', { 'update': function(event, response) { // hier muss der Liste mit clear und dann append ausgefüllt werden $('ul').append('<li><a>hello</a></li>').listview('refresh'); }, 'click': function(event) { var items = $('#' + uid).attr('data-item').explode(); io.write(items[1], 'Test'); } }); // ----- my.time_slider ---------------------------------------------------------- // The slider had to be handled in a more complex manner. A 'lock' is used // to stop the change after a refresh. And a timer is used to fire the trigger // only every 400ms if it was been moved. There should be no trigger on init. $(document).delegate('input[data-widget="my.time_slider"]', { 'update': function(event, response) { // DEBUG: console.log("[basic.slider] update '" + this.id + "': " + response + " timer: " + $(this).attr('timer') + " lock: " + $(this).attr('lock')); $(this).attr('lock', 1); if (response[1] == 0) { $('#' + this.id).val(0).slider('disable'); } else { $('#' + this.id).attr('max',response[1]).val(response[0]).slider('enable'); } $('#' + this.id).slider('refresh'); $('#' + this.id).attr('mem', $(this).val()); }, 'slidestop': function(event) { if ($(this).val() != $(this).attr('mem')) { var items = $(this).attr('data-item').explode(); io.write(items[0], $(this).val()); } }, 'change': function(event) { // DEBUG: console.log("[basic.slider] change '" + this.id + "': " + $(this).val() + " timer: " + $(this).attr('timer') + " lock: " + $(this).attr('lock')); if( ( $(this).attr('timer') === undefined || $(this).attr('timer') == 0 && $(this).attr('lock') == 0 ) && ($(this).val() != $(this).attr('mem')) ) { if ($(this).attr('timer') !== undefined) $(this).trigger('click'); $(this).attr('timer', 1); setTimeout("$('#" + this.id + "').attr('timer', 0);", 400); } $(this).attr('lock', 0); }, 'click': function(event) { var items = $(this).attr('data-item').explode(); io.write(items[0], $(this).val()); } });
HTML-Code:
/** * ----------------------------------------------------------------------------- * @package smartVISU * @author Martin Gleiß * @copyright 2012 * @license GPL <http://www.gnu.de> * ----------------------------------------------------------------------------- */ /** * Squeezebox Multimedia Player * * @param unique id for this widget * @param the gad/item for play * @param the gad/item for pause * @param the gad/item for stop (optional) * @param the gad/item for playlist forward * @param the gad/item for playlist backward * @param the gad/item for the volume (optional) * @param the gad/item to mute the music (optional) * @param the gad/item for the song title (optional) * @param the gad/item for the song artist (optional) * @param the gad/item for repeat (optional) * @param the gad/item to load the default playlist (optional) * @param the gad/item for the duration (optional) * @param the gad/item for the time/position (optional) * * @author Robert Budde * derived from "multimedia" by Axel Otterstätter - thanks! */ {% macro control(id, gad_power, gad_play, gad_pause, gad_stop, gad_playlistforward, gad_playlistbackward, gad_vol, gad_mute, gad_title, gad_artist, gad_repeat, gad_defaultplaylist, gad_duration, gad_time) %} {% import "basic.html" as basic %} {% import "widget_my.html" as my %} {% set uid = uid(page, id) %} <div id="{{ uid }}" class="music"> {% if gad_vol %} <div class="vol"> <img class="slider-bottomup-scale" src="pages/base/pics/scale_buttomup.png"> {{ basic.slider(id~'vol', gad_vol, 0, 100, 5, 'bottomup') }} </div> {% endif %} <div class="control"> {% if gad_power %} {{ basic.dual(id~'power', gad_power, icon1~'control_standby.png', icon0~'control_standby.png') }} {% endif %} {% if gad_mute %} {{ basic.dual(id~'mute', gad_mute, icon1~'audio_volume_mute.png', icon0~'audio_volume_mute.png', 1, 0) }} {% endif %} {% if gad_repeat %} {{ basic.dual(id~'repeat', gad_repeat, icon1~'audio_repeat.png', icon0~'audio_repeat.png') }} {% endif %} {% if gad_defaultplaylist %} {{ basic.button(id~'defaultplaylist', gad_defaultplaylist, 'Default Playlist', icon0~'audio_playlist.png', 1) }} {% endif %} </div> <div class="title"> {% if gad_artist %} {{ basic.value(id~'artist', gad_artist) }} <br /> {% endif %} {% if gad_title %} {{ basic.value(id~'title', gad_title) }} {% endif %} </div> <div class="set"> {% if gad_duration %} {% if gad_time %} <div class="pos"> <div class="scale"> </div> {{ my.time_slider(id~'time', gad_time, gad_duration, 1) }} </div> {% endif %} {% endif %} <div data-role="controlgroup" data-type="horizontal"> {{ basic.button(id~'playlistbackward', gad_playlistbackward, 'backward', icon0~'control_arrow_left.png', 1) }} {{ basic.dual(id~'play', gad_play, icon1~'audio_play.png', icon0~'audio_play.png', 1, 1) }} {{ basic.dual(id~'pause', gad_pause, icon1~'audio_pause.png', icon0~'audio_pause.png') }} {% if gad_stop %} {{ basic.dual(id~'stop', gad_stop, icon1~'audio_stop.png', icon0~'audio_stop.png', 1, 1) }} {% endif %} {{ basic.button(id~'playlistforward', gad_playlistforward, 'forward', icon0~'control_arrow_right.png', 1) }} </div> </div> </div> {% endmacro %}
HTML-Code:
{% import "widget_squeezebox.html" as squeezebox %} ... <div class="block"> <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true"> <div data-role="collapsible" data-collapsed="false"> <h3>Squeezebox Radio</h3> {{ squeezebox.control('Detailseite.Hobbyraum.Squeezebox', 'Squeezebox_1.Power', 'Squeezebox_1.Play', 'Squeezebox_1.Pause', 'Squeezebox_1.Stop', 'Squeezebox_1.Playlist_Forward', 'Squeezebox_1.Playlist_Backward', 'Squeezebox_1.Volume', 'Squeezebox_1.Mute', 'Squeezebox_1.Title', 'Squeezebox_1.Artist', 'Squeezebox_1.Repeat', 'Squeezebox_1.Playlist_Load_Internetradio', 'Squeezebox_1.Duration', 'Squeezebox_1.Time') }} </div> <div data-role="collapsible"> <h3>Erweitert</h3> Name: {{ basic.value('KG_Hobbyraum.Hobbyraum.Squeezebox.Name', 'Squeezebox_1.Name') }} <br /> IP-Adresse: {{ basic.value('KG_Hobbyraum.Hobbyraum.Squeezebox.IP', 'Squeezebox_1.IP') }} <br /> Signalstärke: {{ basic.value('KG_Hobbyraum.Hobbyraum.Squeezebox.Signal_Strength', 'Squeezebox_1.Signal_Strength', '%') }} </div> </div> </div>
Evtl. konsolidiert man das ganze auch in ein großer Widget, was quasi alle GADs der Squeezebox nimmt und gleich darauf korrekt reagiert. Evtl. ist das am Ressoucenschonendsten - aber das pack ich nicht wenn mir kein Kenner hilft bzw. mir nicht sagt, dass dieser Weg gangbar und sinnvoll ist. Meine Idealvorstellung ist halt ein dickes Widget, wo auch das Playlisten-Popup evtl. mit abgefrühstückt wird!
Grüße
Robert
Kommentar