App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
ulrich
2021-03-29 cfe3676d7c9667824c52bb5e5c782d4a9a89b672
commit | author | age
60719c 1 /*
U 2     AV-Direktor - Control OMXPlayer on Raspberry Pi via HTTP
3     Copyright (C) 2021  Ulrich Hilger
4
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU Affero General Public License as
7     published by the Free Software Foundation, either version 3 of the
8     License, or (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Affero General Public License for more details.
14
15     You should have received a copy of the GNU Affero General Public License
16     along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
8e2038 19 package de.uhilger.avdirektor.handler;
U 20
21 import de.uhilger.avdirektor.App;
22 import de.uhilger.avdirektor.MeldeThread;
23 import de.uhilger.avdirektor.ProzessLauscher;
24 import java.io.BufferedWriter;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.io.OutputStreamWriter;
28 import java.io.Writer;
29 import java.net.HttpURLConnection;
30 import java.net.URL;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33
34 /**
cc2a32 35  * Methoden zur Ausfuehrung des Programmes omxplayer des Raspberry Pi 
U 36  * sowie zum Senden von Kommandos an eine laufende Instanz des 
37  * omxplayer.
38  * 
39  * Die Klasse OMXPlayer stellt als abstrakte Basisklasse ihre Methoden 
40  * den Handler-Klassen zur Verfuegung.
8e2038 41  *
U 42  * @author ulrich
43  */
cfe367 44 public class OMXPlayer implements Player , ProzessLauscher {
8e2038 45   
U 46   private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName());
0c8d27 47   
cfe367 48   public static final String BLANK = " ";
0af362 49   public static final String CMD_DEC_SPEED = "1";
U 50   public static final String CMD_DEC_VOL = "-";
cfe367 51   public static final String CMD_INC_SPEED = "2";
0af362 52   public static final String CMD_INC_VOL = "+";
cfe367 53   public static final String CMD_NEXT_AUDIO = "k";
U 54   public static final String CMD_NEXT_CHAPTER = "o";
55   public static final String CMD_NEXT_SUB = "m";
56   public static final String CMD_PAUSE_RESUME = "p";
57   public static final String CMD_PREV_AUDIO = "j";
58   public static final String CMD_PREV_CHAPTER = "i";
59   public static final String CMD_PREV_SUB = "n";
60   public static final String CMD_STOP = "q";
61   public static final String CMD_TOGGLE_SUB = "s";
62   public static final String F_PING = "ping";
0af362 63   public static final String F_PLAY = "play";
U 64   public static final String F_SEEK = "seek";
cfe367 65   public static final String OPT_HDMI_AUDIO = "-o%20hdmi";
U 66   public static final String OPT_LOCAL_AUDIO = "-o%20local";
67   public static final String PFEIL_HERAUF = "5b41";
68   public static final String PFEIL_HERUNTER = "5b42";
69   public static final String PFEIL_LINKS = "5b44";
70   public static final String PFEIL_RECHTS = "5b43";
71   public static final String SP_RUECK_30 = "rueck30";
72   public static final String SP_RUECK_600 = "rueck600";
73   public static final String SP_VOR_30 = "rueck30";
74   public static final String SP_VOR_600 = "vor600";
0af362 75
U 76
8e2038 77   /**
U 78    * Einen Prozess zum Abspielen mit dem omxplayer starten
79    * @param urlStr  URL der Quelle, die abgespielt werden soll
80    * @param token
81    * @return Antwort des Servers
82    */
b6a8f0 83   /*
a7f0a1 84   public String abspielen(String urlStr, String token) {
U 85     return abspielenMitParametern(urlStr, null, token);
8e2038 86   }
b6a8f0 87   */
8e2038 88   
b6a8f0 89   /*
a7f0a1 90   public String abspielenMitRueckmeldung(String urlStr, String meldeUrlStr, String token) {
U 91     return abspielenMitParameternUndRueckmeldung(urlStr, null, meldeUrlStr, token);
8e2038 92   }
b6a8f0 93   */
8e2038 94   
U 95   /**
96    * Einen Prozess zum Abspielen mit dem omxplayer starten 
97    * und Parameter uebergeben.Moegliche Parameter fuer das Abspielen mit dem omxplayer 
98  beschreibt die Seite 
99   <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.
100    * App.OPT_LOCAL_AUDIO oder App.OPT_HDMI_AUDIO.
101  Mehrere Parameter werden mit App.BLANK getrennt.
102    * @param urlStr  der URL der Quelle, die abgespielt werden soll
103    * @param parameter  die Parameter, die vom omxplayer angewendet werden sollen
104    * @param token
105    * @return Antwort des Servers
106    */
b6a8f0 107   /*
a7f0a1 108   public String abspielenMitParametern(String urlStr, String parameter, String token) {
U 109     return abspielenMitParameternUndRueckmeldung(urlStr, parameter, null, token);
8e2038 110   }
b6a8f0 111   */
8e2038 112   
cfe367 113   @Override
b6a8f0 114   public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
8e2038 115     String antwort;// = null;
U 116     try {
a7f0a1 117       //Object o = t.getAttribute(App.PI_PLAYER);
U 118       Process o = App.getPlayerProcess();
8e2038 119       if(o != null) {
a7f0a1 120         tilgen();        
8e2038 121       }
U 122       StringBuilder kommando = new StringBuilder("omxplayer ");
123       if(parameter != null) {
124         kommando.append(parameter);
0af362 125         kommando.append(BLANK);
8e2038 126       }
U 127       if(urlStr.startsWith("http")) {
128         kommando.append(urlStr.replace(" ", "%20"));
129         kommando.append("?t=");
130         kommando.append(token);
131       } else {
132         /*
133           //url z.B.: Filme/H/HEAT_D2.m4v
134         
135           hier muss noch der Pfad hinzugefuegt werden, unter 
136           dem auf dem raspi die Datenquelle via NFS eingebunden ist,
137           z.B. /media/mc/
138           dieser Teil des Pfades muss in pirc als Init-Parameter oder 
139           etwas aehnliches hinterlegt sein, weil es lokal zum jeweils 
140           verwendeten raspi gehoert
141   
142         */
143         
144         String pfad = App.getInitParameter("nfs-prefix");
145         kommando.append(pfad);
146         
147         kommando.append(urlStr);
148       }
149       logger.log(Level.FINE, "kommando: {0}", kommando.toString());
150       Process player_process = Runtime.getRuntime().exec(kommando.toString());
151       if(meldeUrlStr != null) {
152         MeldeThread mt = new MeldeThread();
153         mt.setProcess(player_process);
154         mt.lauscherHinzufuegen(this);
155         mt.setMeldeUrl(meldeUrlStr);
156         mt.start();
157       }
158       //servletContext.setAttribute(App.PI_PLAYER, player_process);
a7f0a1 159       //t.setAttribute(App.PI_PLAYER, player_process);
U 160       App.setPlayerProcess(player_process);
8e2038 161       //Runtime.getRuntime().exec("killall dbus-daemon");
U 162       antwort = "Abspielen gestartet, url: " + urlStr;
163     }
164     catch(IOException ex) {
165       antwort = "Fehler: " + ex.getMessage();
166     }
167     return antwort;
168   }
169     
170   /**
171    * Einen eventuell laufenden Abspielprozess beenden und den 
172    * Servlet-Kontext bereinigen.Diese Methode kann auch verwendet werden, wenn es beim normalen
173  Abspielen zu Fehlern kommt und womoeglich der Servlet-Kontext noch 
174  eine Referenz zu einem Abspielprozess enthaelt, die nicht mehr 
175  aktuell ist.
176    * 
177    * Mit der Methode tilgen kann man eine solche Referenz 
178  entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
179  weiterer Kommandos.
180    *
181    * @return die Antwort des Servers
182    */
cfe367 183   @Override
a7f0a1 184   public String tilgen() {
8e2038 185     String antwort; // = null;
U 186     try {
a7f0a1 187       //Object o = t.getAttribute(App.PI_PLAYER);
U 188       Process o = App.getPlayerProcess();
8e2038 189       if(o == null) {
a7f0a1 190         //t.setAttribute(App.PI_PLAYER, null);
U 191         App.setPlayerProcess(null);
8e2038 192         // t.removeAttribute(App.PI_PLAYER);
U 193         antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt.";
194       } else {
0af362 195         kommando(CMD_STOP);
8e2038 196         //t.removeAttribute(PI_PLAYER);
U 197         antwort = "Player gestoppt, Kontext bereinigt.";
198       }
199     } 
200     catch(Exception ex) {
201       antwort = "Fehler: " + ex.getMessage();
202     }
203     return antwort;
204   }
205   
206   
207   /**
208    * Dem laufenden Abspielprozess ein Kommando uebermitteln
209    * @param k  das Kommando laut 
210    * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
211    * @return die Antwort des Servers
212    */
cfe367 213   @Override
a7f0a1 214   public String kommando(String k) {
8e2038 215     String antwort; // = null;
U 216     try {
a7f0a1 217       //Object o = t.getAttribute(App.PI_PLAYER);
U 218       Process o = App.getPlayerProcess();
8e2038 219       if(o == null) {
a7f0a1 220         App.setPlayerProcess(null);
8e2038 221         //servletContext.removeAttribute(PI_PLAYER);
a7f0a1 222         //t.setAttribute(App.PI_PLAYER, null);
8e2038 223         antwort = "Es wird nichts abgespielt dem ein Kommando gesendet werden kann.";
U 224       } else {
a7f0a1 225         Process player_process = o;
8e2038 226         OutputStream os = player_process.getOutputStream();
U 227         Writer out = new BufferedWriter(new OutputStreamWriter(os));
228         out.write(k);
229         out.flush();
0af362 230         if(k.equals(CMD_STOP)) {
8e2038 231           out.close();
a7f0a1 232           App.setPlayerProcess(null);
8e2038 233           //player_process.destroy();
U 234           //player_process = null;
a7f0a1 235           //t.setAttribute(App.PI_PLAYER, null);
8e2038 236           //servletContext.removeAttribute(PI_PLAYER);
U 237         }
238         antwort = "Kommando '" + k + "' ausgefuehrt.";
239       }
240     } 
241     catch(IOException ex) {
242       antwort = "Fehler: " + ex.getMessage();
243     }
244     return antwort;
245   }
246   
247   /* ------ Implementierung ProzessLauscher ----------------- */
248   
249   @Override
250   public void prozessBeendet(String meldeUrlStr) {
251     try {
252       HttpURLConnection conn = (HttpURLConnection) new URL(meldeUrlStr).openConnection();
253       conn.setRequestMethod("GET");
254       conn.connect();
255       int status = conn.getResponseCode();
256       logger.log(Level.INFO, "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.", new Object[]{meldeUrlStr, status});
257     } catch(IOException ex) {
258       logger.log(Level.INFO, ex.getMessage(), ex);
259     }
260   }
261   
262 }