App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
ulrich
2021-04-01 2dd7a5b331b57db5c7aa5bef9540e3e198848060
weiterspielen (erste Fassung fertig)
1 files added
6 files modified
217 ■■■■■ changed files
resources/start 2 ●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/OMXLogLeser.java 17 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/Server.java 4 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/LogHandler.java 4 ●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/OMXPlayer.java 95 ●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/PlayHandler.java 26 ●●●●● patch | view | raw | blame | history
src/de/uhilger/avdirektor/handler/PlayOnHandler.java 69 ●●●●● patch | view | raw | blame | history
resources/start
@@ -1,3 +1,3 @@
#!/bin/sh
java -Djava.util.logging.config.file=logging.properties -jar av-direktor.jar port=9090 nfs-prefix="/media/mc" &
java -Djava.util.logging.config.file=logging.properties -jar av-direktor.jar port=9090 player=omx &
src/de/uhilger/avdirektor/OMXLogLeser.java
@@ -29,6 +29,16 @@
  private static final long MILLIS = (long) 1000;
  
  private static final long MINSEC = (long) 60;
  public String logDirLesen(File logDir) throws IOException, FileNotFoundException, ParseException {
    Blocks blocks = new Blocks();
    File[] files = logDir.listFiles();
    for(File file : files) {
      lesen(file, blocks);
    }
    return blocks.getTimeString();
  }
      
  /**
   * 
@@ -42,12 +52,13 @@
   * 
   * 
   * @param logfile
   * @param blocks
   * @return  die Spieldauer als String im Format H:MM:SS
   * @throws FileNotFoundException
   * @throws IOException
   * @throws ParseException 
   */
  public String lesen(File logfile) throws FileNotFoundException, IOException, ParseException {
  public void lesen(File logfile, Blocks blocks) throws FileNotFoundException, IOException, ParseException {
    boolean inPause = false;
    logger.info("Starting to parse log..");
    Date parseStart = new Date();
@@ -58,7 +69,7 @@
    ++lineCount;
    String lastLine = "";
    String line = r.readLine();
    Blocks blocks = new Blocks();
    //Blocks blocks = new Blocks();
    Block currentBlock = new Block();
    while(line != null) {
      ++lineCount;
@@ -88,7 +99,7 @@
    logger.log(Level.INFO, 
            "{0} lines parsed in {1} seconds and {2} milliseconds.", 
            new Object[]{lineCount, timeSeconds, restMillis});
    return blocks.getTimeString();
    //return blocks.getTimeString();
  }
  
  class Block {
src/de/uhilger/avdirektor/Server.java
@@ -25,10 +25,9 @@
import de.uhilger.avdirektor.handler.OMXPlayer;
import de.uhilger.avdirektor.handler.PingHandler;
import de.uhilger.avdirektor.handler.PlayHandler;
import de.uhilger.avdirektor.handler.Player;
import de.uhilger.avdirektor.handler.PlayOnHandler;
import de.uhilger.avdirektor.handler.SeekHandler;
import de.uhilger.avdirektor.handler.StopServerHandler;
import de.uhilger.avdirektor.handler.VLCPlayer;
import java.io.IOException;
import java.util.logging.Logger;
import java.net.InetSocketAddress;
@@ -63,6 +62,7 @@
    server.createContext("/avd/ping", new PingHandler(OMXPlayer.F_PING));
    server.createContext("/avd/server/stop", new StopServerHandler());
    server.createContext("/avd/log", new LogHandler());
    server.createContext("/avd/playon", new PlayOnHandler(OMXPlayer.F_PLAY));
    server.createContext("/avd/ui", new FileHandler(App.getInitParameter(App.IP_WWW_DATA)));
    //server.setExecutor(null); // creates a default executor
    server.setExecutor(Executors.newFixedThreadPool(20));
src/de/uhilger/avdirektor/handler/LogHandler.java
@@ -37,6 +37,7 @@
  @Override
  protected String process(HttpExchange t, String params) {
    /*
    OMXLogLeser leser = new OMXLogLeser();
    String lines = "Log nicht lesbar.";
    try {
@@ -47,7 +48,8 @@
    } catch (ParseException ex) {
      Logger.getLogger(LogHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
    return lines;
    */
    return "";
  }
  
}
src/de/uhilger/avdirektor/handler/OMXPlayer.java
@@ -22,12 +22,16 @@
import de.uhilger.avdirektor.MeldeThread;
import de.uhilger.avdirektor.ProzessLauscher;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -61,6 +65,7 @@
  public static final String CMD_TOGGLE_SUB = "s";
  public static final String F_PING = "ping";
  public static final String F_PLAY = "play";
  public static final String F_PLAY_ON = "playon";
  public static final String F_SEEK = "seek";
  public static final String OPT_HDMI_AUDIO = "-o%20hdmi";
  public static final String OPT_LOCAL_AUDIO = "-o%20local";
@@ -73,81 +78,27 @@
  public static final String SP_VOR_30 = "rueck30";
  public static final String SP_VOR_600 = "vor600";
  /**
   * Einen Prozess zum Abspielen mit dem omxplayer starten
   * @param urlStr  URL der Quelle, die abgespielt werden soll
   * @param token
   * @return Antwort des Servers
   */
  /*
  public String abspielen(String urlStr, String token) {
    return abspielenMitParametern(urlStr, null, token);
  }
  */
  /*
  public String abspielenMitRueckmeldung(String urlStr, String meldeUrlStr, String token) {
    return abspielenMitParameternUndRueckmeldung(urlStr, null, meldeUrlStr, token);
  }
  */
  /**
   * Einen Prozess zum Abspielen mit dem omxplayer starten
   * und Parameter uebergeben.Moegliche Parameter fuer das Abspielen mit dem omxplayer
 beschreibt die Seite
  <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 urlStr  der URL der Quelle, die abgespielt werden soll
   * @param parameter  die Parameter, die vom omxplayer angewendet werden sollen
   * @param token
   * @return Antwort des Servers
   */
  /*
  public String abspielenMitParametern(String urlStr, String parameter, String token) {
    return abspielenMitParameternUndRueckmeldung(urlStr, parameter, null, token);
  }
  */
  @Override
  public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
    String antwort;// = null;
    try {
      //Object o = t.getAttribute(App.PI_PLAYER);
      Process o = App.getPlayerProcess();
      if(o != null) {
        tilgen();        
      }
      StringBuilder kommando = new StringBuilder("omxplayer ");
      if(parameter != null) {
        kommando.append(parameter);
        kommando.append(BLANK);
      }
      List<String> kommando = new ArrayList();
      kommando.add("omxplayer");
      kommando.addAll(Arrays.asList(parameter.split(BLANK)));
      if(urlStr.startsWith("http")) {
        kommando.append(urlStr.replace(" ", "%20"));
        kommando.append("?t=");
        kommando.append(token);
        kommando.add(urlStr.replace(" ", "%20"));
      } else {
        /*
          //url z.B.: Filme/H/HEAT_D2.m4v
          hier muss noch der Pfad hinzugefuegt werden, unter
          dem auf dem raspi die Datenquelle via NFS eingebunden ist,
          z.B. /media/mc/
          dieser Teil des Pfades muss in pirc als Init-Parameter oder
          etwas aehnliches hinterlegt sein, weil es lokal zum jeweils
          verwendeten raspi gehoert
        */
        String pfad = App.getInitParameter("nfs-prefix");
        kommando.append(pfad);
        kommando.append(urlStr);
      }
        kommando.add(App.getInitParameter("nfs-prefix") + urlStr);
      }
      logger.log(Level.FINE, "parameter: {0}", parameter);
      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
      Process player_process = Runtime.getRuntime().exec(kommando.toString());
      ProcessBuilder pb = new ProcessBuilder(kommando);
      pb.directory(new File(System.getProperty("omx.wd")));
      Process player_process = pb.start();
      if(meldeUrlStr != null) {
        MeldeThread mt = new MeldeThread();
        mt.setProcess(player_process);
@@ -155,10 +106,7 @@
        mt.setMeldeUrl(meldeUrlStr);
        mt.start();
      }
      //servletContext.setAttribute(App.PI_PLAYER, player_process);
      //t.setAttribute(App.PI_PLAYER, player_process);
      App.setPlayerProcess(player_process);
      //Runtime.getRuntime().exec("killall dbus-daemon");
      antwort = "Abspielen gestartet, url: " + urlStr;
    }
    catch(IOException ex) {
@@ -184,16 +132,12 @@
  public String tilgen() {
    String antwort; // = null;
    try {
      //Object o = t.getAttribute(App.PI_PLAYER);
      Process o = App.getPlayerProcess();
      if(o == null) {
        //t.setAttribute(App.PI_PLAYER, null);
        App.setPlayerProcess(null);
        // t.removeAttribute(App.PI_PLAYER);
        antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt.";
        App.setPlayerProcess(null);
      } else {
        kommando(CMD_STOP);
        //t.removeAttribute(PI_PLAYER);
        kommando(CMD_STOP); // setzt den Prozess der App auf null
        antwort = "Player gestoppt, Kontext bereinigt.";
      }
    } 
@@ -253,7 +197,10 @@
      conn.setRequestMethod("GET");
      conn.connect();
      int status = conn.getResponseCode();
      logger.log(Level.INFO, "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.", new Object[]{meldeUrlStr, status});
      logger.log(Level.INFO,
              "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.",
              new Object[]{meldeUrlStr, status});
      App.setPlayerProcess(null);
    } catch(IOException ex) {
      logger.log(Level.INFO, ex.getMessage(), ex);
    }
src/de/uhilger/avdirektor/handler/PlayHandler.java
@@ -20,8 +20,11 @@
import com.sun.net.httpserver.HttpExchange;
import de.uhilger.avdirektor.App;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
/**
 * Play
@@ -51,14 +54,6 @@
    super(cmd);
  }
  @Override
  protected String process(HttpExchange t, String params) {
    String antwort = App.getPlayer().abspielen(
            getParam(map, "titel"), params, getParam(map, "r"), "1");
    logger.log(Level.FINE, antwort);
    return antwort;
  }
  protected StringBuilder buildParams(HttpExchange t) {
    StringBuilder params = super.buildParams(t);
    params.append("-b -o ");
@@ -74,4 +69,19 @@
    return params;
  }
  
  @Override
  protected String process(HttpExchange t, String params) {
    if(cmd.equalsIgnoreCase(OMXPlayer.F_PLAY)) {
      try {
        FileUtils.deleteDirectory(new File(System.getProperty("omx.wd"), "omx-logs"));
      } catch (IOException ex) {
        logger.log(Level.SEVERE, null, ex);
      }
    }
    String antwort = App.getPlayer().abspielen(
            getParam(map, "titel"), params, getParam(map, "r"), "1");
    logger.log(Level.FINE, antwort);
    return antwort;
  }
}
src/de/uhilger/avdirektor/handler/PlayOnHandler.java
New file
@@ -0,0 +1,69 @@
package de.uhilger.avdirektor.handler;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import de.uhilger.avdirektor.App;
import de.uhilger.avdirektor.OMXLogLeser;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
/**
 * z.B.
 * http://rpi4-az:9090/avd/playon?th=1&ti=240&o=local&log=true&titel=http://amd-srv:9090/srv/Filme/C/casino_royale.m4v
 * @author ulrich
 */
public class PlayOnHandler extends PlayHandler {
  private static final Logger logger = Logger.getLogger(PlayOnHandler.class.getName());
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd-hh-MM-ss");
  public PlayOnHandler(String cmd) {
    super(cmd);
  }
  /*
    1. buildParams
    2. process
  */
  @Override
  protected StringBuilder buildParams(HttpExchange t) {
    String wd = System.getProperty("omx.wd");
    File targetDir = new File(wd, "omx-logs");
    try {
      File logFile = new File(wd, "omxplayer.log");
      Date date = new Date(logFile.lastModified());
      File srcFile = new File(wd, "omxplayer-" + sdf.format(date) + ".log");
      logFile.renameTo(srcFile);
      targetDir.mkdirs();
      FileUtils.moveFileToDirectory(srcFile, targetDir, false);
    } catch (IOException ex) {
      Logger.getLogger(PlayOnHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
    StringBuilder params = super.buildParams(t);
    params.append(" --pos ");
    try {
      // hier das Ergebnis der Log-Auswertung angeben
      params.append(logsLesen(targetDir));
    } catch (IOException ex) {
      Logger.getLogger(PlayOnHandler.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ParseException ex) {
      Logger.getLogger(PlayOnHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
    return params;
  }
  private String logsLesen(File logDir) throws IOException, FileNotFoundException, ParseException {
    OMXLogLeser leser = new OMXLogLeser();
    return leser.logDirLesen(logDir);
  }
}