From c18e1dfdb92661fcb8d2eaff87517ec5232f0f46 Mon Sep 17 00:00:00 2001
From: ulrich
Date: Fri, 23 Apr 2021 17:53:30 +0000
Subject: [PATCH] Abspielprozess wird nicht mehr auf null gesetzt

---
 src/de/uhilger/avdirektor/handler/OMXPlayer.java |  240 +++++++++++++++++++++++++++--------------------------------
 1 files changed, 110 insertions(+), 130 deletions(-)

diff --git a/src/de/uhilger/avdirektor/handler/OMXPlayer.java b/src/de/uhilger/avdirektor/handler/OMXPlayer.java
index dc0a797..926e9c8 100644
--- a/src/de/uhilger/avdirektor/handler/OMXPlayer.java
+++ b/src/de/uhilger/avdirektor/handler/OMXPlayer.java
@@ -1,144 +1,106 @@
 /*
- * 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.
- */
+    AV-Direktor - Control OMXPlayer on Raspberry Pi via HTTP
+    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.avdirektor.handler;
 
-import com.sun.net.httpserver.HttpExchange;
 import de.uhilger.avdirektor.App;
 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.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.logging.Level;
 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
  */
-public abstract class OMXPlayer implements ProzessLauscher {
+public class OMXPlayer implements Player , ProzessLauscher {
   
   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;
-    }
-  }
+  public static final String NAME = "omxplayer";
   
-  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.info("qPart: " + qPart);
-        String pParts[] = qPart.split("=");
-        map.put(pParts[0], pParts[1]);
-      }
-    }
-    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
-   */
-  public String abspielen(HttpExchange t, String urlStr, String token) {
-    return abspielenMitParametern(t, urlStr, null, token);
-  }
-  
-  public String abspielenMitRueckmeldung(HttpExchange t, String urlStr, String meldeUrlStr, String token) {
-    return abspielenMitParameternUndRueckmeldung(t, 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 t
-   * @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(HttpExchange t, String urlStr, String parameter, String token) {
-    return abspielenMitParameternUndRueckmeldung(t, urlStr, parameter, null, token);
-  }
-  
-  public String abspielenMitParameternUndRueckmeldung(HttpExchange t, String urlStr, String parameter, String meldeUrlStr, String token) {
+  public static final String BLANK = " ";
+  public static final String CMD_DEC_SPEED = "1";
+  public static final String CMD_DEC_VOL = "-";
+  public static final String CMD_INC_SPEED = "2";
+  public static final String CMD_INC_VOL = "+";
+  public static final String CMD_NEXT_AUDIO = "k";
+  public static final String CMD_NEXT_CHAPTER = "o";
+  public static final String CMD_NEXT_SUB = "m";
+  public static final String CMD_PAUSE_RESUME = "p";
+  public static final String CMD_PREV_AUDIO = "j";
+  public static final String CMD_PREV_CHAPTER = "i";
+  public static final String CMD_PREV_SUB = "n";
+  public static final String CMD_STOP = "q";
+  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";
+  public static final String PFEIL_HERAUF = "5b41";
+  public static final String PFEIL_HERUNTER = "5b42";
+  public static final String PFEIL_LINKS = "5b44";
+  public static final String PFEIL_RECHTS = "5b43";
+  public static final String SP_RUECK_30 = "rueck30";
+  public static final String SP_RUECK_600 = "rueck600";
+  public static final String SP_VOR_30 = "rueck30";
+  public static final String SP_VOR_600 = "vor600";
+
+  @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(t);        
+        tilgen();        
       }
-      StringBuilder kommando = new StringBuilder("omxplayer ");
-      if(parameter != null) {
-        kommando.append(parameter);
-        kommando.append(App.BLANK);
-      }
+      List<String> kommando = new ArrayList();
+      kommando.add(NAME);
+      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);
@@ -146,9 +108,7 @@
         mt.setMeldeUrl(meldeUrlStr);
         mt.start();
       }
-      //servletContext.setAttribute(App.PI_PLAYER, player_process);
-      t.setAttribute(App.PI_PLAYER, player_process);
-      //Runtime.getRuntime().exec("killall dbus-daemon");
+      App.setPlayerProcess(player_process);
       antwort = "Abspielen gestartet, url: " + urlStr;
     }
     catch(IOException ex) {
@@ -168,21 +128,19 @@
  entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
  weiterer Kommandos.
    *
-   * @param t 
    * @return die Antwort des Servers
    */
-  public String tilgen(HttpExchange t) {
+  @Override
+  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);
-        // t.removeAttribute(App.PI_PLAYER);
-        antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt.";
+        antwort = "Es ist kein Player zum Beenden vorhanden.";
+        //App.setPlayerProcess(null);
       } else {
-        kommando(t, App.CMD_STOP);
-        //t.removeAttribute(PI_PLAYER);
-        antwort = "Player gestoppt, Kontext bereinigt.";
+        kommando(CMD_STOP); // setzt den Prozess der App auf null
+        antwort = "Player gestoppt.";
       }
     } 
     catch(Exception ex) {
@@ -194,30 +152,42 @@
   
   /**
    * 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
    */
-  public String kommando(HttpExchange t, String k) {
+  @Override
+  public String kommando(String k) {
     String antwort; // = null;
     try {
-      Object o = t.getAttribute(App.PI_PLAYER);
+      //Object o = t.getAttribute(App.PI_PLAYER);
+      Process o = App.getPlayerProcess();
       if(o == null) {
+        //App.setPlayerProcess(null);
         //servletContext.removeAttribute(PI_PLAYER);
-        t.setAttribute(App.PI_PLAYER, null);
+        //t.setAttribute(App.PI_PLAYER, null);
         antwort = "Es wird nichts abgespielt dem ein Kommando gesendet werden kann.";
       } else {
-        Process player_process = (Process) o;
+        Process player_process = o;
         OutputStream os = player_process.getOutputStream();
         Writer out = new BufferedWriter(new OutputStreamWriter(os));
         out.write(k);
         out.flush();
-        if(k.equals(App.CMD_STOP)) {
+        if(k.equals(CMD_STOP)) {
           out.close();
+          
+          /*
+            fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
+            oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
+            dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
+            auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
+            auf null gesetzt.
+          */
+          
+          //App.setPlayerProcess(null);
           //player_process.destroy();
           //player_process = null;
-          t.setAttribute(App.PI_PLAYER, null);
+          //t.setAttribute(App.PI_PLAYER, null);
           //servletContext.removeAttribute(PI_PLAYER);
         }
         antwort = "Kommando '" + k + "' ausgefuehrt.";
@@ -238,7 +208,17 @@
       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});
+          /*
+            fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
+            oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
+            dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
+            auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
+            auf null gesetzt.
+          */
+      //App.setPlayerProcess(null);
     } catch(IOException ex) {
       logger.log(Level.INFO, ex.getMessage(), ex);
     }

--
Gitblit v1.9.3