App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
ulrich
2021-04-04 6ff352870ec1dfea573fb3e6de370f8020fe0d04
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;
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;
30 import java.net.HttpURLConnection;
31 import java.net.URL;
2dd7a5 32 import java.util.ArrayList;
U 33 import java.util.Arrays;
34 import java.util.List;
8e2038 35 import java.util.logging.Level;
U 36 import java.util.logging.Logger;
37
38 /**
cc2a32 39  * Methoden zur Ausfuehrung des Programmes omxplayer des Raspberry Pi 
U 40  * sowie zum Senden von Kommandos an eine laufende Instanz des 
41  * omxplayer.
42  * 
43  * Die Klasse OMXPlayer stellt als abstrakte Basisklasse ihre Methoden 
44  * den Handler-Klassen zur Verfuegung.
8e2038 45  *
U 46  * @author ulrich
47  */
cfe367 48 public class OMXPlayer implements Player , ProzessLauscher {
8e2038 49   
U 50   private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName());
0c8d27 51   
6ff352 52   public static final String NAME = "omxplayer";
U 53   
cfe367 54   public static final String BLANK = " ";
0af362 55   public static final String CMD_DEC_SPEED = "1";
U 56   public static final String CMD_DEC_VOL = "-";
cfe367 57   public static final String CMD_INC_SPEED = "2";
0af362 58   public static final String CMD_INC_VOL = "+";
cfe367 59   public static final String CMD_NEXT_AUDIO = "k";
U 60   public static final String CMD_NEXT_CHAPTER = "o";
61   public static final String CMD_NEXT_SUB = "m";
62   public static final String CMD_PAUSE_RESUME = "p";
63   public static final String CMD_PREV_AUDIO = "j";
64   public static final String CMD_PREV_CHAPTER = "i";
65   public static final String CMD_PREV_SUB = "n";
66   public static final String CMD_STOP = "q";
67   public static final String CMD_TOGGLE_SUB = "s";
68   public static final String F_PING = "ping";
0af362 69   public static final String F_PLAY = "play";
2dd7a5 70   public static final String F_PLAY_ON = "playon";
0af362 71   public static final String F_SEEK = "seek";
cfe367 72   public static final String OPT_HDMI_AUDIO = "-o%20hdmi";
U 73   public static final String OPT_LOCAL_AUDIO = "-o%20local";
74   public static final String PFEIL_HERAUF = "5b41";
75   public static final String PFEIL_HERUNTER = "5b42";
76   public static final String PFEIL_LINKS = "5b44";
77   public static final String PFEIL_RECHTS = "5b43";
78   public static final String SP_RUECK_30 = "rueck30";
79   public static final String SP_RUECK_600 = "rueck600";
80   public static final String SP_VOR_30 = "rueck30";
81   public static final String SP_VOR_600 = "vor600";
0af362 82
cfe367 83   @Override
b6a8f0 84   public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
8e2038 85     String antwort;// = null;
U 86     try {
a7f0a1 87       Process o = App.getPlayerProcess();
8e2038 88       if(o != null) {
a7f0a1 89         tilgen();        
8e2038 90       }
2dd7a5 91       List<String> kommando = new ArrayList();
6ff352 92       kommando.add(NAME);
2dd7a5 93       kommando.addAll(Arrays.asList(parameter.split(BLANK)));
8e2038 94       if(urlStr.startsWith("http")) {
2dd7a5 95         kommando.add(urlStr.replace(" ", "%20"));
8e2038 96       } else {
2dd7a5 97         kommando.add(App.getInitParameter("nfs-prefix") + urlStr);        
U 98       }      
99       logger.log(Level.FINE, "parameter: {0}", parameter);
8e2038 100       logger.log(Level.FINE, "kommando: {0}", kommando.toString());
2dd7a5 101       ProcessBuilder pb = new ProcessBuilder(kommando);
U 102       pb.directory(new File(System.getProperty("omx.wd")));
103       Process player_process = pb.start();
8e2038 104       if(meldeUrlStr != null) {
U 105         MeldeThread mt = new MeldeThread();
106         mt.setProcess(player_process);
107         mt.lauscherHinzufuegen(this);
108         mt.setMeldeUrl(meldeUrlStr);
109         mt.start();
110       }
a7f0a1 111       App.setPlayerProcess(player_process);
8e2038 112       antwort = "Abspielen gestartet, url: " + urlStr;
U 113     }
114     catch(IOException ex) {
115       antwort = "Fehler: " + ex.getMessage();
116     }
117     return antwort;
118   }
119     
120   /**
121    * Einen eventuell laufenden Abspielprozess beenden und den 
122    * Servlet-Kontext bereinigen.Diese Methode kann auch verwendet werden, wenn es beim normalen
123  Abspielen zu Fehlern kommt und womoeglich der Servlet-Kontext noch 
124  eine Referenz zu einem Abspielprozess enthaelt, die nicht mehr 
125  aktuell ist.
126    * 
127    * Mit der Methode tilgen kann man eine solche Referenz 
128  entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
129  weiterer Kommandos.
130    *
131    * @return die Antwort des Servers
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) {
U 139         antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt.";
2dd7a5 140         App.setPlayerProcess(null);
8e2038 141       } else {
2dd7a5 142         kommando(CMD_STOP); // setzt den Prozess der App auf null
8e2038 143         antwort = "Player gestoppt, Kontext bereinigt.";
U 144       }
145     } 
146     catch(Exception ex) {
147       antwort = "Fehler: " + ex.getMessage();
148     }
149     return antwort;
150   }
151   
152   
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) {
a7f0a1 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();
a7f0a1 178           App.setPlayerProcess(null);
8e2038 179           //player_process.destroy();
U 180           //player_process = null;
a7f0a1 181           //t.setAttribute(App.PI_PLAYER, null);
8e2038 182           //servletContext.removeAttribute(PI_PLAYER);
U 183         }
184         antwort = "Kommando '" + k + "' ausgefuehrt.";
185       }
186     } 
187     catch(IOException ex) {
188       antwort = "Fehler: " + ex.getMessage();
189     }
190     return antwort;
191   }
192   
193   /* ------ Implementierung ProzessLauscher ----------------- */
194   
195   @Override
196   public void prozessBeendet(String meldeUrlStr) {
197     try {
198       HttpURLConnection conn = (HttpURLConnection) new URL(meldeUrlStr).openConnection();
199       conn.setRequestMethod("GET");
200       conn.connect();
201       int status = conn.getResponseCode();
2dd7a5 202       logger.log(Level.INFO, 
U 203               "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.", 
204               new Object[]{meldeUrlStr, status});
205       App.setPlayerProcess(null);
8e2038 206     } catch(IOException ex) {
U 207       logger.log(Level.INFO, ex.getMessage(), ex);
208     }
209   }
210   
211 }