Ankündigung

Einklappen
Keine Ankündigung bisher.

Widget time_slider (für Squeezebox/Abspielgeräte-Widget)

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Widget time_slider (für Squeezebox/Abspielgeräte-Widget)

    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
    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 %}
    visu.js
    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());
        } 
    });
    widget_squeezebox.html
    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">&nbsp;</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 %}
    Beispieleinbindung in eine Visu-Seite:
    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>
    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

    #2
    Zitat von Robert Beitrag anzeigen
    Um in einem Lied spulen zu können brauchen wir eine Art Zeitleisten-Schieberegler.
    Unterstütz der LMS das vorspulen innerhalt eines Songs?


    Mal nebenbei:
    Vieleicht wäre es ratsam das man hier auch den Code für das Plugin und auch die items hier mit reinstellt.
    So hätte man alles in einem.

    Kommentar


      #3
      Zitat von macflei Beitrag anzeigen
      Unterstütz der LMS das vorspulen innerhalt eines Songs?


      Mal nebenbei:
      Vieleicht wäre es ratsam das man hier auch den Code für das Plugin und auch die items hier mit reinstellt.
      So hätte man alles in einem.
      Ja, tut er - einfach mal mit den widgets testen - draufdrücken auf den slider spult.

      Plugin und Items sind smarthome.py spezifisch und dort wohl besser aufgehoben - zudem haben wir so eine klare Auflaufstelle für die Visualisierung und eine für das Plugin. Ebenfalls denke ich könnte dies hier auch für die Sonos-Freunde etc interessant sein.

      Kommentar


        #4
        Zitat von Robert Beitrag anzeigen
        Plugin und Items sind smarthome.py spezifisch und dort wohl besser aufgehoben - zudem haben wir so eine klare Auflaufstelle für die Visualisierung und eine für das Plugin. Ebenfalls denke ich könnte dies hier auch für die Sonos-Freunde etc interessant sein.
        Das stimmt natürlich. Aber ein "Anfänger" tut sich leichter das alle in einem Paket zu finden.
        Oder generell eine eigenen Sektion mit fertigen Plugins inkl. Items & co.
        Wo man halt alles als Paket hat.
        Apollo ...... was meinst? Quasi ne Art "Datenbank".

        Kommentar


          #5
          Hallo Robert,

          Schaut ja gar nicht schlecht aus. Warum du allerdings einen eigenen Slider brauchst erschliesst sich mir nicht ganz. Du kannst ja den "normalen" Slider in deinem Widget verändern. Der ist so gebaut, das er bei Wertänderung sich dort hinstellt. Folglich müsste sh.py nur alle x-Sekunden den aktuellen Wert senden. Also, wenn der Slider von 0-100 geht quasi:

          Zu sendender Wert = Zeit im Lied / Gesamtdauer * 100

          oder?

          Gruss
          Join smartVISU on facebook. Web: smartvisu.de.
          Dir gefällt smartVISU? Bitte spenden für die Weiterentwicklung.

          Kommentar


            #6
            Hi Martin,

            das ginge (hatte ich ja auch erwähnt).

            ABER:
            • keine Deaktivierung möglich wenn (Gesamtdauer == 0)
            • ich brauche eine Logik
              • die diese Umrechnung macht
              • die periodisch den neuen Wert sendet

            • ich übertrage diesen relativen Wert möglicherweise zusätzlich zu den beiden absoluten Werten (für numerische Anzeigen etc.)

            Eigentlich würde es reichen, die Play-Funktion mit rein zu nehmen und stur nach 1000msec den Wert um 1 zu erhöhen wenn (Play == True). Die darauf entstehenden Abweichungen dürften nie auffallen und so schont es die Ressourcen.


            GAD_Time, GAD_Duration, GAD_Play
            • Max = GAD_Duration
            • Disabled = (GAD_Duration == 0)
            • Value = GAD_Time bzw. bei Click GAD_Time = Value
            • wenn GAD_Play dann inkrementiere Value alle 1000msec

            und dann lohnt sich halt vielleicht schon das ganz große Widget in dem GAD_Play eh enthalten ist.


            Grüße
            Robert

            Kommentar


              #7
              Zitat von Robert Beitrag anzeigen
              ...und dann lohnt sich halt vielleicht schon das ganz große Widget in dem GAD_Play eh enthalten ist....
              Würd ich auch machen, aber darin würd ich nicht den slider nochmal neu machen, sondern einfach mit einbinden. Und der könnte ja auch aktiviert oder deaktiviert werden.

              Gruss
              Join smartVISU on facebook. Web: smartvisu.de.
              Dir gefällt smartVISU? Bitte spenden für die Weiterentwicklung.

              Kommentar


                #8
                Hallo,

                das hat's noch nicht ins Develop geschafft, oder?

                Gruß,
                Hendrik

                Kommentar


                  #9
                  Hi Robert!
                  Würde mich interessieren, ob du die "Play-Slider" Problematik schon gelöst hast. Wäre genial, wenn du deinen Code nochmals sharen würdest hier

                  Merci vielmals,
                  Andy

                  Kommentar


                    #10
                    *push*

                    Kommentar

                    Lädt...
                    X