App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
ulrich
2021-03-22 cc2a321cfbbbb6156b119dcd9a5c46b2da1b96f0
Code aufgeraeumt
6 files modified
1 files deleted
251 ■■■■■ changed files
src/de/uhilger/avdirektor/App.java 13 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/Server.java 7 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/CmdHandler.java 23 ●●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/OMXPlayer.java 138 ●●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/PingHandler.java 7 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/PlayHandler.java 44 ●●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/StopHandler.java 19 ●●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/App.java
@@ -6,14 +6,23 @@
import java.util.logging.Logger;
/**
 *
 * Hauptklasse des av-director
 *
 * Aufruf mit
 * java -jar av-director.jar port=9000
 * java -jar av-director.jar nfs-prefix="/media/mc" port=9000
 * java -Djava.util.logging.config.file=logging.properties -jar ..
 *
 * Der Parameter nfs-prefix bewirkt, dass beim Abspielen relative Pfade
 * mit diesem Praefix verbunden werden und setzt voraus, dass auf der
 * Maschine ein NFS-Mount ueber /etc/fstab eingerichtet ist.
 *
 * @author ulrich
 */
public class App {
  
  private static final Logger logger = Logger.getLogger(App.class.getName());
  public static final String PI_PLAYER = "pi_player";
  //public static final String FBI_PROC = "fbi_proc";
  
src/de/uhilger/avdirektor/Server.java
@@ -1,9 +1,9 @@
package de.uhilger.avdirektor;
import com.sun.net.httpserver.HttpServer;
import de.uhilger.avdirektor.handler.CmdHandler;
import de.uhilger.avdirektor.handler.PingHandler;
import de.uhilger.avdirektor.handler.PlayHandler;
import de.uhilger.avdirektor.handler.StopHandler;
import de.uhilger.avdirektor.handler.StopServerHandler;
import java.io.IOException;
import java.util.logging.Logger;
@@ -31,12 +31,9 @@
  public void start() throws IOException {
    logger.info("Server starting on port " + port);
    StopHandler sh = new StopHandler();
    sh.setCmd(App.CMD_STOP);
    HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
    server.createContext("/avd/play", new PlayHandler());
    server.createContext("/avd/stop", sh);
    server.createContext("/avd/stop", new CmdHandler(App.CMD_STOP));
    server.createContext("/avd/ping", new PingHandler());
    server.createContext("/avd/server/stop", new StopServerHandler());
    server.setExecutor(null); // creates a default executor
src/de/uhilger/avdirektor/handler/CmdHandler.java
@@ -1,8 +1,3 @@
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.uhilger.avdirektor.handler;
import com.sun.net.httpserver.HttpExchange;
@@ -17,13 +12,23 @@
 *
 * @author ulrich
 */
public abstract class CmdHandler extends OMXPlayer implements HttpHandler {
public class CmdHandler extends OMXPlayer implements HttpHandler {
  private static final Logger logger = Logger.getLogger(CmdHandler.class.getName());
  
  protected String cmd;
  private String cmd;
  
  public abstract void setCmd(String cmd);
  public CmdHandler(String cmd) {
    this.cmd = cmd;
  }
  public void setCmd(String cmd) {
    this.cmd = cmd;
  }
  public String getCmd(String cmd) {
    return this.cmd;
  }
  @Override
  public void handle(HttpExchange t) throws IOException {
@@ -33,7 +38,7 @@
    String antwort = this.kommando(cmd);
    logger.log(Level.FINE, antwort);
    
    String response = getResponseString(map, "cmd", antwort);
    String response = getResponseString(map, cmd, antwort);
    t.sendResponseHeaders(200, response.length());
    OutputStream os = t.getResponseBody();
    os.write(response.getBytes());
src/de/uhilger/avdirektor/handler/OMXPlayer.java
@@ -1,8 +1,3 @@
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.uhilger.avdirektor.handler;
import com.sun.net.httpserver.HttpExchange;
@@ -23,6 +18,12 @@
import java.util.logging.Logger;
/**
 * Methoden zur Ausfuehrung des Programmes omxplayer des Raspberry Pi
 * sowie zum Senden von Kommandos an eine laufende Instanz des
 * omxplayer.
 *
 * Die Klasse OMXPlayer stellt als abstrakte Basisklasse ihre Methoden
 * den Handler-Klassen zur Verfuegung.
 *
 * @author ulrich
 */
@@ -30,85 +31,8 @@
  
  private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName());
  
  protected String getParam(Map map, String key) {
    Object o = map.get(key);
    if(o != null) {
      return o.toString();
    } else {
      return null;
    }
  }
  /*
    bei etwas wie
    http://rpi4-az:9090/avd/play?t=/Filme/S/sound_city.m4v&p=--timeout=60%20--threshold=60
    sind = nicht nur nach dem Query-Parameter sondern auch in dessen Wert
    also erstmal nach & zerlegen:
    t=/Filme/S/sound_city.m4v
    p=--timeout=60%20--threshold=60
    dann die Position beim ersten = von links abschneiden
  */
  protected Map getQueryMap(HttpExchange t) {
    HashMap map = new HashMap();
    String query = t.getRequestURI().getQuery();
    if(query != null && query.length() > 0) {
      String qParts[] = query.split("&");
      for(String qPart : qParts) {
        logger.finer("qPart: " + qPart);
        String pParts[] = qPart.split("=");
        map.put(pParts[0], pParts[1]);
        logger.finer("pParts[0]: " + pParts[0] + ", pParts[1]: " + pParts[1]);
        /*
        if(qPart.contains(" ")) {
          String pParts[] = qPart.split(" ");
          for(String pPart : pParts) {
            String ppParts[] = pPart.split("=");
            map.put(ppParts[0], ppParts[1]);
            logger.finer("ppParts[0]: " + ppParts[0] + ", ppParts[1]: " + ppParts[1]);
          }
        } else {
          String pParts[] = qPart.split("=");
          map.put(pParts[0], pParts[1]);
          logger.finer("pParts[0]: " + pParts[0] + ", pParts[1]: " + pParts[1]);
        }
        */
        /*
        String pParts[] = qPart.split("=");
        for(String pPart : pParts) {
          logger.finer("pPart: " + pPart);
        }
        */
      }
    }
    return map;
  }
  protected String getResponseString(Map map, String cmd, String antwort) {
    Set keys = map.keySet();
    StringBuilder buf = new StringBuilder();
    buf.append("play");
    buf.append(System.lineSeparator());
    keys.forEach((Object key) -> {
      buf.append("key: ");
      buf.append(key);
      buf.append(System.lineSeparator());
      buf.append("value: ");
      buf.append(map.get(key));
      buf.append(System.lineSeparator());
      //logger.log(Level.FINE, "key {0} value {1}", new Object[]{key, map.get(key)});
    });
    buf.append(antwort);
    return buf.toString();
  }
  /**
   * Einen Prozess zum Abspielen mit dem omxplayer starten
   * @param t
   * @param urlStr  URL der Quelle, die abgespielt werden soll
   * @param token
   * @return Antwort des Servers
@@ -128,7 +52,6 @@
  <a href="https://github.com/huceke/omxplayer/blob/master/README.md"target="_blank">Aufstellung der Parameter</a>.Die Zeichenkette parameter enthaelt Eintraege wie z.B.
   * App.OPT_LOCAL_AUDIO oder App.OPT_HDMI_AUDIO.
 Mehrere Parameter werden mit App.BLANK getrennt.
   * @param t
   * @param urlStr  der URL der Quelle, die abgespielt werden soll
   * @param parameter  die Parameter, die vom omxplayer angewendet werden sollen
   * @param token
@@ -205,7 +128,6 @@
 entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
 weiterer Kommandos.
   *
   * @param t
   * @return die Antwort des Servers
   */
  public String tilgen() {
@@ -233,7 +155,6 @@
  
  /**
   * Dem laufenden Abspielprozess ein Kommando uebermitteln
   * @param t
   * @param k  das Kommando laut 
   * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
   * @return die Antwort des Servers
@@ -271,6 +192,53 @@
    return antwort;
  }
  
  /* --- --- */
  protected String getParam(Map map, String key) {
    Object o = map.get(key);
    if(o != null) {
      return o.toString();
    } else {
      return null;
    }
  }
  /*
    Den Query-Teil einer URL in die Parameter zerlegen
  */
  protected Map getQueryMap(HttpExchange t) {
    HashMap map = new HashMap();
    String query = t.getRequestURI().getQuery();
    if(query != null && query.length() > 0) {
      String qParts[] = query.split("&");
      for(String qPart : qParts) {
        logger.finer("qPart: " + qPart);
        String pParts[] = qPart.split("=");
        map.put(pParts[0], pParts[1]);
        logger.finer("pParts[0]: " + pParts[0] + ", pParts[1]: " + pParts[1]);
      }
    }
    return map;
  }
  protected String getResponseString(Map map, String cmd, String antwort) {
    Set keys = map.keySet();
    StringBuilder buf = new StringBuilder();
    buf.append(cmd);
    buf.append(System.lineSeparator());
    keys.forEach((Object key) -> {
      buf.append("key: ");
      buf.append(key);
      buf.append(System.lineSeparator());
      buf.append("value: ");
      buf.append(map.get(key));
      buf.append(System.lineSeparator());
      //logger.log(Level.FINE, "key {0} value {1}", new Object[]{key, map.get(key)});
    });
    buf.append(antwort);
    return buf.toString();
  }
  /* ------ Implementierung ProzessLauscher ----------------- */
  
  @Override
src/de/uhilger/avdirektor/handler/PingHandler.java
@@ -19,21 +19,16 @@
public class PingHandler implements HttpHandler {
  
  private static final Logger logger = Logger.getLogger(PingHandler.class.getName());
  @Override
  public void handle(HttpExchange t) throws IOException {
    logger.log(Level.FINE, "RequestURI: {0}", t.getRequestURI().toString());
    
    String antwort = "ping Antwort";
    String response = antwort;
    String response = "ping";
    t.sendResponseHeaders(200, response.length());
    OutputStream os = t.getResponseBody();
    os.write(response.getBytes());
    os.close();    
  }
  
}
src/de/uhilger/avdirektor/handler/PlayHandler.java
@@ -4,48 +4,12 @@
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * Es koennen mehrere Varianten beim Abspielen verwendet werden.
 * 
 * Abspielen eines Titels
 * abspielenMitParameternUndRueckmeldung(urlStr, null, null, 1)
 *
 * Abspielen eines Titels mit Rueckmeldung (z.B. fuer Playlisten)
 * abspielenMitParameternUndRueckmeldung(urlStr, null, meldeUrlStr, 1)
 *
 * Abspielen mit Parametern
 * abspielenMitParameternUndRueckmeldung(urlStr, parameter, null, 1)
 *
 * Abspielen mit Parametern und Rueckmeldung
 * abspielenMitParameternUndRueckmeldung(urlStr, parameter, meldeUrlStr, 1)
 *
 * Token wird zur Zeit nicht genutzt, hier kann einfach eine beliebige
 * Zahl uebergeben werden.
 *
 * Die drei Parameter t, p, r werden als Query im URL erwartet. Beispiele:
 * t = titel
 * p = parameter
 * r = url fuer rueckmeldung
 *
 *
 * /avd/play?t=/Pfad/zum/Titel.mp3
 * /avd/play?t=/Pfad/zum/Titel.mp3&p=-o=local%20-timeout=60
 * /avd/play?t=/Pfad/zum/Titel.mp3&r=http:/uhilger.de/rueckmelde/pfad
 * /avd/play?t=/Pfad/zum/Titel.mp3&p=-o=local%20-timeout=60&r=http:/uhilger.de/rueckmelde/pfad
 *
 * String urlStr, String parameter, String meldeUrlStr, String token
 *
 *
 *
 *
 *
 * @author ulrich
 */
public class PlayHandler extends OMXPlayer implements HttpHandler {
@@ -53,12 +17,12 @@
  private static final Logger logger = Logger.getLogger(PlayHandler.class.getName());
  /*
  rpi4-az:9090/avd/play?titel=/Filme/S/sound_city.m4v&to=60&ti=60&o=local
    rpi4-az:9090/avd/play?titel=/Filme/S/sound_city.m4v&th=60&ti=60&o=local
  
    OMXPlayer.abspielenMitParameternUndRueckmeldung(
      String urlStr, String parameter, String meldeUrlStr, String token)
  
    Parameter des Aufrufs play als query
    Parameter des Aufrufs play als query (th threshold, ti timeout)
  
    ?titel=/Filme/S/sound_city.m4v
    &ti=60
@@ -69,8 +33,6 @@
    r muss ganz wegbleiben, wenn keine Rueckmeldung gewuescht ist
  */
  @Override
  public void handle(HttpExchange t) throws IOException {
    logger.log(Level.FINE, "RequestURI: {0}", t.getRequestURI().toString());
@@ -93,4 +55,6 @@
    os.write(response.getBytes());
    os.close();    
  }
}
src/de/uhilger/avdirektor/handler/StopHandler.java
File was deleted