Persoenliche Mediazentrale
ulrich
2021-04-12 d027b57c66dcdb183683c34101518df1572c1bf8
Livestreams erste Fassung fertig
3 files added
7 files modified
205 ■■■■ changed files
src/de/uhilger/mediaz/api/AbstractHandler.java 2 ●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/api/ListFileHandler.java 1 ●●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/api/MediaSteuerung.java 63 ●●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/api/StorageHandler.java 4 ●●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/entity/Livestream.java 47 ●●●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/store/FileStorage.java 5 ●●●● patch | view | raw | blame | history
www/ui/data/tpl/form_livestream.txt 11 ●●●●● patch | view | raw | blame | history
www/ui/data/tpl/livestream_liste.txt 7 ●●●●● patch | view | raw | blame | history
www/ui/index.html 2 ●●● patch | view | raw | blame | history
www/ui/js/app.js 63 ●●●● patch | view | raw | blame | history
src/de/uhilger/mediaz/api/AbstractHandler.java
@@ -69,7 +69,7 @@
          response = json;
        } else {
          response = "nicht gefunden";
          returnCode = RTC_NOT_FOUND;
          //returnCode = RTC_NOT_FOUND;
        }
        break;
        
src/de/uhilger/mediaz/api/ListFileHandler.java
@@ -33,7 +33,6 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
src/de/uhilger/mediaz/api/MediaSteuerung.java
@@ -26,6 +26,7 @@
import de.uhilger.mediaz.entity.Abspielliste;
import de.uhilger.mediaz.entity.Einstellung;
import de.uhilger.mediaz.entity.Entity;
import de.uhilger.mediaz.entity.Livestream;
import de.uhilger.mediaz.entity.Titel;
import de.uhilger.mediaz.store.FileStorage;
import de.uhilger.mediaz.store.Storage;
@@ -45,7 +46,8 @@
 * HTTP GET /mz/api/strg/abspieler/play/liste/[name] 
 * HTTP GET /mz/api/strg/abspieler/ende
 *
 * HTTP POST /mz/api/strg/abspieler/play mit dem Titel im Body
 * HTTP POST /mz/api/strg/abspieler/play/titel mit dem Titel im Body
 * HTTP POST /mz/api/strg/abspieler/play/stream mit dem Livestream im Body (nur Name gefuellt)
 *
 * HTTP GET /mz/api/strg/abspieler/pause 
 * HTTP GET /mz/api/strg/abspieler/stop 
@@ -128,25 +130,52 @@
    String path = e.getRequestURI().toString();
    String[] elems = path.split(Server.SLASH);
    FileStorage fs = new FileStorage(App.getInitParameter(App.getRs(App.RB_AP_CONF)));
    String titelJson = bodyLesen(e);
    Gson gson = new Gson();
    Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
    if(o instanceof Titel) {
      Titel titel = (Titel) o;
      String titelUrl = titel.getKatalogUrl() + titel.getPfad() + titel.getName();
      Entity entity = fs.read(FileStorage.ST_ABSPIELER, elems[4]);
      if (entity instanceof Abspieler) {
        Abspieler abspieler = (Abspieler) entity;
        String server = getEinstellung(fs, App.getRs(App.RB_HOST), DEFAULT_HOST);
        String signal = abspielKommando(fs, abspieler, server, titelUrl).toString();
        abspielerKommandoSenden(signal);
        return signal + "gesendet.";
    if(elems[5].equalsIgnoreCase("titel")) {
      String titelJson = bodyLesen(e);
      Gson gson = new Gson();
      Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
      if(o instanceof Titel) {
        Titel titel = (Titel) o;
        String titelUrl = titel.getKatalogUrl() + titel.getPfad() + titel.getName();
        Entity entity = fs.read(FileStorage.ST_ABSPIELER, elems[4]);
        if (entity instanceof Abspieler) {
          Abspieler abspieler = (Abspieler) entity;
          String server = getEinstellung(fs, App.getRs(App.RB_HOST), DEFAULT_HOST);
          String signal = abspielKommando(fs, abspieler, server, titelUrl).toString();
          abspielerKommandoSenden(signal);
          return signal + "gesendet.";
        } else {
          return meldung("Ungueltiger Abspieler.", 404);
        }
      } else {
        return meldung("Ungueltiger Abspieler.", 404);
        return meldung("Ungueltiger Titel.", 404);
      }
    } else if(elems[5].equalsIgnoreCase("stream")) {
      String streamJson = bodyLesen(e);
      Gson gson = new Gson();
      Object o = gson.fromJson(streamJson, fs.typeFromName(Livestream.class.getSimpleName()).getType());
      if(o instanceof Livestream) {
        Entity entity = fs.read(FileStorage.ST_LIVESTREAM, ((Livestream) o).getName());
        if(entity instanceof Livestream) {
          Livestream stream = (Livestream) entity;
          entity = fs.read(FileStorage.ST_ABSPIELER, elems[4]);
          if (entity instanceof Abspieler) {
            Abspieler abspieler = (Abspieler) entity;
            String server = "";
            String signal = abspielKommando(fs, abspieler, server, stream.getUrl()).toString();
            abspielerKommandoSenden(signal);
            return signal + "gesendet.";
          } else {
            return meldung("Ungueltiger Abspieler.", 404);
          }
        } else {
          return meldung("Ungueltiger Livestream.", 404);
        }
      } else {
       return meldung("Ungueltiger Livestream.", 404);
      }
    } else {
      return meldung("Ungueltiger Titel.", 404);
      return meldung("Ungueltiger URL.", 404);
    }
  }
  
src/de/uhilger/mediaz/api/StorageHandler.java
@@ -24,6 +24,7 @@
import de.uhilger.mediaz.Server;
import de.uhilger.mediaz.store.FileStorage;
import de.uhilger.mediaz.entity.Entity;
import static de.uhilger.mediaz.store.FileStorage.ST_ABLAGEORT;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
@@ -86,6 +87,9 @@
        String type = elems[elems.length - 2];
        logger.fine(type);
        list = fs.list(type);
        if(type.equalsIgnoreCase(ST_ABLAGEORT)) {
          list.add("Livestreams");
        }
      } else {
        String type = elems[elems.length - 1];
        logger.fine(type);
src/de/uhilger/mediaz/entity/Livestream.java
New file
@@ -0,0 +1,47 @@
/*
  Mediazentrale - Personal Media Center
  Copyright (C) 2021  Ulrich Hilger
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Affero General Public License for more details.
  You should have received a copy of the GNU Affero General Public License
  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.uhilger.mediaz.entity;
/**
 *
 * @author Ulrich Hilger
 */
public class Livestream implements Entity {
  private String name;
  private String url;
  @Override
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getUrl() {
    return url;
  }
  public void setUrl(String url) {
    this.url = url;
  }
}
src/de/uhilger/mediaz/store/FileStorage.java
@@ -19,7 +19,6 @@
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import de.uhilger.mediaz.App;
import de.uhilger.mediaz.Server;
import de.uhilger.mediaz.entity.Ablageort;
import de.uhilger.mediaz.entity.Abspieler;
@@ -33,6 +32,7 @@
import java.io.IOException;
import java.util.logging.Logger;
import de.uhilger.mediaz.entity.Entity;
import de.uhilger.mediaz.entity.Livestream;
import de.uhilger.mediaz.entity.Titel;
import java.util.ArrayList;
import java.util.HashMap;
@@ -60,6 +60,7 @@
  public static final String ST_EINSTELLUNG = "Einstellung";
  public static final String ST_ABSPIELER = "Abspieler";
  public static final String ST_ABSPIELLISTE = "Abspielliste";
  public static final String ST_LIVESTREAM = "Livestream";
  
  private final String fileBase;
  
@@ -73,6 +74,7 @@
    TypeToken<Einstellung> ttEinstellung = new TypeToken<Einstellung>() {};
    TypeToken<Abspieler> ttAbspieler = new TypeToken<Abspieler>() {};
    TypeToken<Abspielliste> ttAbspielliste = new TypeToken<Abspielliste>() {};
    TypeToken<Livestream> ttLivestream = new TypeToken<Livestream>() {};
    TypeToken<Titel> ttTitel = new TypeToken<Titel>() {};
    types = new HashMap();
    types.put(Ablageort.class.getSimpleName(), ttAblageort);
@@ -80,6 +82,7 @@
    types.put(Abspieler.class.getSimpleName(), ttAbspieler);
    types.put(Abspielliste.class.getSimpleName(), ttAbspielliste);
    types.put(Titel.class.getSimpleName(), ttTitel);
    types.put(Livestream.class.getSimpleName(), ttLivestream);
  }
  
  /**
www/ui/data/tpl/form_livestream.txt
New file
@@ -0,0 +1,11 @@
<form>
  <div class="entity-formular">
    <input name="name" class="entity-element" type="text" id="livestream-name" placeholder="Name" value="{{name}}" />
    <input name="url" class="entity-element" type="text" id="livestream-url" placeholder="Pfad" value="{{url}}" />
    <div class="entity-buttons">
      <button type="submit" class="button-primary" id="ok-btn">Speichern</button>
      <button class="button" id="cancel-btn">Abbrechen</button>
      <button class="button" id="loeschen-btn">L&ouml;schen</button>
    </div>
  </div>
</form>
www/ui/data/tpl/livestream_liste.txt
New file
@@ -0,0 +1,7 @@
<div class='entity-formular'>
  <ul class='entity-liste'>
    {{#ArrayList}}
    <li class='entity-eintrag'>{{.}}</li>
    {{/ArrayList}}
  </ul>
</div>
www/ui/index.html
@@ -52,7 +52,7 @@
            <a id="mi-listen"><i class="icon-list"></i> Abspiellisten</a>
            <a id="mi-orte"><i class="icon-database"></i> Kataloge</a>
            <a id="mi-player"><i class="icon-play"></i> Abspieler</a>
            <a id="mi-radio"><i class="icon-ellipsis-vert"></i> Radio</a>
            <a id="mi-live"><i class="icon-ellipsis-vert"></i> Livestream</a>
            <a id="mi-prefs"><i class="icon-sliders"></i> Einstellungen</a>
          </div>
        </div>         
www/ui/js/app.js
@@ -30,6 +30,7 @@
    self.addEvtListener('#mi-player', 'click', self.abspieler_liste);
    self.addEvtListener('#mi-listen', 'click', self.abspielliste_liste);
    self.addEvtListener('#mi-list', 'click', self.titel_liste);
    self.addEvtListener('#mi-live', 'click', self.livestream_liste);
    
    self.fusszeile_umschalten();
    self.seitenleiste_umschalten();
@@ -37,6 +38,21 @@
  };
  
  /* ---------------- Entitaets-Listen ----------------- */
  this.livestream_selection = function() {
    document.querySelector('.breadcrumb-behaelter').textContent = '';
    document.querySelector('.bereich-name').textContent = 'Livestream-Auswahl';
    self.http_get('../api/store/Livestream/liste/', function(responseText) {
      self.vorlage_laden_und_fuellen("data/tpl/livestream_liste.txt", JSON.parse(responseText), function (html) {
        document.querySelector(".zentraler-inhalt").innerHTML = html;
        self.addEvtListener('.entity-eintrag', 'click', function (event) {
          var t = event.target;
          self.removeClassMulti('selected');
          t.classList.add('selected');
        });
      });
    });
  };
  // auf der obersten Ebene werden die Kataloge angezeigt,
  // darunter der Inhalt des aktuellen Pfades
@@ -55,11 +71,15 @@
          self.addEvtListener('.entity-eintrag', 'click', function (event) {
            var t = event.target;
            self.katName = t.textContent;
            self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
              var ablageort = JSON.parse(responseText);
              self.ortPfad = ablageort.url;
              self.media_liste();
            });
            if(self.katName !== "Livestreams") {
              self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
                var ablageort = JSON.parse(responseText);
                self.ortPfad = ablageort.url;
                self.media_liste();
              });
            } else {
              self.livestream_selection();
            }
          });
        });
      });
@@ -161,6 +181,15 @@
      });
  };
  
  this.livestream_liste = function() {
    self.entitaet_liste('Livestream','../api/store/Livestream/liste/',
      "data/tpl/livestream_liste.txt", '../api/store/Livestream/',
      "self.livestream_form", function(responseText) {
        var livestream = JSON.parse(responseText);
        self.livestream_form(livestream);
      });
  };
  this.abspielliste_liste = function() {
    self.entitaet_liste('Abspielliste','../api/store/Abspielliste/liste/', 
      "data/tpl/abspielliste_liste.txt", '../api/store/Abspielliste/', 
@@ -191,6 +220,14 @@
      '#abspieler-name', function() { 
          self.abspieler_auswahl_fuellen();
          self.abspieler_liste();
    });
  };
  this.livestream_form = function(ls) {
    self.entitaet_form('Livestream', ls, ls.name,
      "data/tpl/form_livestream.txt", '../api/store/Livestream/',
      '#livestream-name', function() {
          self.livestream_liste();
    });
  };
@@ -322,9 +359,16 @@
      url: /media/test/M/Muenchener-Freiheit/01-Ohne-Dich-schlaf-ich-heut-Nacht-nicht-ein.mp3      
      */
      console.log('plname: ' + playername + ' url: ' + titel.katalogUrl + titel.pfad + titel.name);
      self.http_post('../api/strg/' + playername, JSON.stringify(titel), function(responseText) {
      self.http_post('../api/strg/' + playername + '/titel', JSON.stringify(titel), function(responseText) {
        self.meldung_mit_timeout(responseText, 1500);
      });
      });
    } else if(bereichName === 'Livestream-Auswahl') {
      var streamName = document.querySelector(".selected").textContent;
      var playername = document.querySelector('#abspieler').value;
      var stream = new Livestream(streamName, '-');
      self.http_post('../api/strg/' + playername + '/stream', JSON.stringify(stream), function(responseText) {
        self.meldung_mit_timeout(responseText, 1500);
      });
    } else {
      var abs = document.querySelector('#abspieler').value;
      var lst = document.querySelector('#playlist').value;
@@ -772,6 +816,11 @@
  this.url = u;
}
function Livestream(n, u) {
  this.name = n;
  this.url = u;
}
function Abspielliste(n) {
  this.name = n;
}