App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
undisclosed
2022-12-30 82594dab993741669b50fe1ec784f528fd836bc2
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
229976 19 package de.uhilger.calypso.handler;
8e2038 20
229976 21 import de.uhilger.calypso.App;
U 22 import de.uhilger.calypso.MeldeThread;
23 import de.uhilger.calypso.ProzessLauscher;
8e2038 24 import java.io.BufferedWriter;
2dd7a5 25 import java.io.File;
8e2038 26 import java.io.IOException;
U 27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.Writer;
2dd7a5 30 import java.util.ArrayList;
U 31 import java.util.Arrays;
32 import java.util.List;
8e2038 33 import java.util.logging.Level;
U 34 import java.util.logging.Logger;
35
36 /**
cc2a32 37  * Methoden zur Ausfuehrung des Programmes omxplayer des Raspberry Pi 
U 38  * sowie zum Senden von Kommandos an eine laufende Instanz des 
39  * omxplayer.
40  * 
41  * Die Klasse OMXPlayer stellt als abstrakte Basisklasse ihre Methoden 
42  * den Handler-Klassen zur Verfuegung.
8e2038 43  *
U 44  * @author ulrich
45  */
82594d 46 public class OMXPlayer extends BasePlayer implements Player , ProzessLauscher {
8e2038 47   
U 48   private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName());
0c8d27 49   
6ff352 50   public static final String NAME = "omxplayer";
U 51   
cfe367 52   public static final String BLANK = " ";
37f9ab 53   public static final String CMD_TOGGLE_INFO = "z";
0af362 54   public static final String CMD_DEC_SPEED = "1";
U 55   public static final String CMD_DEC_VOL = "-";
cfe367 56   public static final String CMD_INC_SPEED = "2";
37f9ab 57   public static final String CMD_INC_VOL = "="; // oder "+";
cfe367 58   public static final String CMD_NEXT_AUDIO = "k";
U 59   public static final String CMD_NEXT_CHAPTER = "o";
60   public static final String CMD_NEXT_SUB = "m";
61   public static final String CMD_PAUSE_RESUME = "p";
62   public static final String CMD_PREV_AUDIO = "j";
63   public static final String CMD_PREV_CHAPTER = "i";
64   public static final String CMD_PREV_SUB = "n";
65   public static final String CMD_STOP = "q";
66   public static final String CMD_TOGGLE_SUB = "s";
67   public static final String F_PING = "ping";
0af362 68   public static final String F_PLAY = "play";
2dd7a5 69   public static final String F_PLAY_ON = "playon";
0af362 70   public static final String F_SEEK = "seek";
cfe367 71   public static final String OPT_HDMI_AUDIO = "-o%20hdmi";
U 72   public static final String OPT_LOCAL_AUDIO = "-o%20local";
73   public static final String PFEIL_HERAUF = "5b41";
74   public static final String PFEIL_HERUNTER = "5b42";
75   public static final String PFEIL_LINKS = "5b44";
76   public static final String PFEIL_RECHTS = "5b43";
77   public static final String SP_RUECK_30 = "rueck30";
78   public static final String SP_RUECK_600 = "rueck600";
79   public static final String SP_VOR_30 = "rueck30";
80   public static final String SP_VOR_600 = "vor600";
0af362 81
cfe367 82   @Override
b6a8f0 83   public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
8e2038 84     String antwort;// = null;
U 85     try {
a7f0a1 86       Process o = App.getPlayerProcess();
8e2038 87       if(o != null) {
a7f0a1 88         tilgen();        
8e2038 89       }
2dd7a5 90       List<String> kommando = new ArrayList();
6ff352 91       kommando.add(NAME);
2dd7a5 92       kommando.addAll(Arrays.asList(parameter.split(BLANK)));
8e2038 93       if(urlStr.startsWith("http")) {
2dd7a5 94         kommando.add(urlStr.replace(" ", "%20"));
8e2038 95       } else {
2dd7a5 96         kommando.add(App.getInitParameter("nfs-prefix") + urlStr);        
U 97       }      
98       logger.log(Level.FINE, "parameter: {0}", parameter);
8e2038 99       logger.log(Level.FINE, "kommando: {0}", kommando.toString());
2dd7a5 100       ProcessBuilder pb = new ProcessBuilder(kommando);
U 101       pb.directory(new File(System.getProperty("omx.wd")));
102       Process player_process = pb.start();
8e2038 103       if(meldeUrlStr != null) {
U 104         MeldeThread mt = new MeldeThread();
105         mt.setProcess(player_process);
106         mt.lauscherHinzufuegen(this);
107         mt.setMeldeUrl(meldeUrlStr);
108         mt.start();
109       }
a7f0a1 110       App.setPlayerProcess(player_process);
8e2038 111       antwort = "Abspielen gestartet, url: " + urlStr;
U 112     }
113     catch(IOException ex) {
114       antwort = "Fehler: " + ex.getMessage();
115     }
116     return antwort;
117   }
118     
119   /**
120    * Einen eventuell laufenden Abspielprozess beenden und den 
121    * Servlet-Kontext bereinigen.Diese Methode kann auch verwendet werden, wenn es beim normalen
122  Abspielen zu Fehlern kommt und womoeglich der Servlet-Kontext noch 
123  eine Referenz zu einem Abspielprozess enthaelt, die nicht mehr 
124  aktuell ist.
125    * 
126    * Mit der Methode tilgen kann man eine solche Referenz 
127  entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
128  weiterer Kommandos.
129    *
130    * @return die Antwort des Servers
131    */
82594d 132   /*
cfe367 133   @Override
a7f0a1 134   public String tilgen() {
8e2038 135     String antwort; // = null;
U 136     try {
a7f0a1 137       Process o = App.getPlayerProcess();
8e2038 138       if(o == null) {
c18e1d 139         antwort = "Es ist kein Player zum Beenden vorhanden.";
U 140         //App.setPlayerProcess(null);
8e2038 141       } else {
2dd7a5 142         kommando(CMD_STOP); // setzt den Prozess der App auf null
c18e1d 143         antwort = "Player gestoppt.";
8e2038 144       }
U 145     } 
146     catch(Exception ex) {
147       antwort = "Fehler: " + ex.getMessage();
148     }
149     return antwort;
150   }
82594d 151   */
8e2038 152   
U 153   /**
154    * Dem laufenden Abspielprozess ein Kommando uebermitteln
155    * @param k  das Kommando laut 
156    * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
157    * @return die Antwort des Servers
158    */
cfe367 159   @Override
a7f0a1 160   public String kommando(String k) {
8e2038 161     String antwort; // = null;
U 162     try {
a7f0a1 163       //Object o = t.getAttribute(App.PI_PLAYER);
U 164       Process o = App.getPlayerProcess();
8e2038 165       if(o == null) {
c18e1d 166         //App.setPlayerProcess(null);
8e2038 167         //servletContext.removeAttribute(PI_PLAYER);
a7f0a1 168         //t.setAttribute(App.PI_PLAYER, null);
8e2038 169         antwort = "Es wird nichts abgespielt dem ein Kommando gesendet werden kann.";
U 170       } else {
a7f0a1 171         Process player_process = o;
8e2038 172         OutputStream os = player_process.getOutputStream();
U 173         Writer out = new BufferedWriter(new OutputStreamWriter(os));
174         out.write(k);
175         out.flush();
0af362 176         if(k.equals(CMD_STOP)) {
8e2038 177           out.close();
c18e1d 178           
U 179           /*
180             fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
181             oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
182             dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
183             auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
184             auf null gesetzt.
185           */
186           
187           //App.setPlayerProcess(null);
8e2038 188           //player_process.destroy();
U 189           //player_process = null;
a7f0a1 190           //t.setAttribute(App.PI_PLAYER, null);
8e2038 191           //servletContext.removeAttribute(PI_PLAYER);
U 192         }
193         antwort = "Kommando '" + k + "' ausgefuehrt.";
194       }
195     } 
196     catch(IOException ex) {
197       antwort = "Fehler: " + ex.getMessage();
198     }
199     return antwort;
200   }
201   
202   /* ------ Implementierung ProzessLauscher ----------------- */
203   
82594d 204   /*
8e2038 205   @Override
U 206   public void prozessBeendet(String meldeUrlStr) {
207     try {
208       HttpURLConnection conn = (HttpURLConnection) new URL(meldeUrlStr).openConnection();
209       conn.setRequestMethod("GET");
210       conn.connect();
211       int status = conn.getResponseCode();
2dd7a5 212       logger.log(Level.INFO, 
U 213               "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.", 
214               new Object[]{meldeUrlStr, status});
c18e1d 215           /*
U 216             fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
217             oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
218             dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
219             auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
220             auf null gesetzt.
221           */
222       //App.setPlayerProcess(null);
82594d 223   /*
8e2038 224     } catch(IOException ex) {
U 225       logger.log(Level.INFO, ex.getMessage(), ex);
226     }
227   }
82594d 228   */
8e2038 229 }