App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
ulrich
2021-03-21 8e20383acd0ab64b0b54ffb94508db13cc056269
commit | author | age
8e2038 1 /*
U 2  * To change this license header, choose License Headers in Project Properties.
3  * To change this template file, choose Tools | Templates
4  * and open the template in the editor.
5  */
6 package de.uhilger.avdirektor.handler;
7
8 import com.sun.net.httpserver.HttpExchange;
9 import de.uhilger.avdirektor.App;
10 import de.uhilger.avdirektor.MeldeThread;
11 import de.uhilger.avdirektor.ProzessLauscher;
12 import java.io.BufferedWriter;
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.io.OutputStreamWriter;
16 import java.io.Writer;
17 import java.net.HttpURLConnection;
18 import java.net.URL;
19 import java.util.logging.Level;
20 import java.util.logging.Logger;
21
22 /**
23  *
24  * @author ulrich
25  */
26 public abstract class OMXPlayer implements ProzessLauscher {
27   
28   private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName());
29   
30   
31   /**
32    * Einen Prozess zum Abspielen mit dem omxplayer starten
33    * @param t
34    * @param urlStr  URL der Quelle, die abgespielt werden soll
35    * @param token
36    * @return Antwort des Servers
37    */
38   public String abspielen(HttpExchange t, String urlStr, String token) {
39     return abspielenMitParametern(t, urlStr, null, token);
40   }
41   
42   public String abspielenMitRueckmeldung(HttpExchange t, String urlStr, String meldeUrlStr, String token) {
43     return abspielenMitParameternUndRueckmeldung(t, urlStr, null, meldeUrlStr, token);
44   }
45   
46   /**
47    * Einen Prozess zum Abspielen mit dem omxplayer starten 
48    * und Parameter uebergeben.Moegliche Parameter fuer das Abspielen mit dem omxplayer 
49  beschreibt die Seite 
50   <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.
51    * App.OPT_LOCAL_AUDIO oder App.OPT_HDMI_AUDIO.
52  Mehrere Parameter werden mit App.BLANK getrennt.
53    * @param t
54    * @param urlStr  der URL der Quelle, die abgespielt werden soll
55    * @param parameter  die Parameter, die vom omxplayer angewendet werden sollen
56    * @param token
57    * @return Antwort des Servers
58    */
59   public String abspielenMitParametern(HttpExchange t, String urlStr, String parameter, String token) {
60     return abspielenMitParameternUndRueckmeldung(t, urlStr, parameter, null, token);
61   }
62   
63   public String abspielenMitParameternUndRueckmeldung(HttpExchange t, String urlStr, String parameter, String meldeUrlStr, String token) {
64     String antwort;// = null;
65     try {
66       Object o = t.getAttribute(App.PI_PLAYER);
67       if(o != null) {
68         tilgen(t);        
69       }
70       StringBuilder kommando = new StringBuilder("omxplayer ");
71       if(parameter != null) {
72         kommando.append(parameter);
73         kommando.append(App.BLANK);
74       }
75       if(urlStr.startsWith("http")) {
76         kommando.append(urlStr.replace(" ", "%20"));
77         kommando.append("?t=");
78         kommando.append(token);
79       } else {
80         /*
81           //url z.B.: Filme/H/HEAT_D2.m4v
82         
83           hier muss noch der Pfad hinzugefuegt werden, unter 
84           dem auf dem raspi die Datenquelle via NFS eingebunden ist,
85           z.B. /media/mc/
86           dieser Teil des Pfades muss in pirc als Init-Parameter oder 
87           etwas aehnliches hinterlegt sein, weil es lokal zum jeweils 
88           verwendeten raspi gehoert
89   
90         */
91         
92         String pfad = App.getInitParameter("nfs-prefix");
93         kommando.append(pfad);
94         
95         kommando.append(urlStr);
96       }
97       logger.log(Level.FINE, "kommando: {0}", kommando.toString());
98       Process player_process = Runtime.getRuntime().exec(kommando.toString());
99       if(meldeUrlStr != null) {
100         MeldeThread mt = new MeldeThread();
101         mt.setProcess(player_process);
102         mt.lauscherHinzufuegen(this);
103         mt.setMeldeUrl(meldeUrlStr);
104         mt.start();
105       }
106       //servletContext.setAttribute(App.PI_PLAYER, player_process);
107       //Runtime.getRuntime().exec("killall dbus-daemon");
108       antwort = "Abspielen gestartet, url: " + urlStr;
109     }
110     catch(IOException ex) {
111       antwort = "Fehler: " + ex.getMessage();
112     }
113     return antwort;
114   }
115     
116   /**
117    * Einen eventuell laufenden Abspielprozess beenden und den 
118    * Servlet-Kontext bereinigen.Diese Methode kann auch verwendet werden, wenn es beim normalen
119  Abspielen zu Fehlern kommt und womoeglich der Servlet-Kontext noch 
120  eine Referenz zu einem Abspielprozess enthaelt, die nicht mehr 
121  aktuell ist.
122    * 
123    * Mit der Methode tilgen kann man eine solche Referenz 
124  entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung 
125  weiterer Kommandos.
126    *
127    * @param t 
128    * @return die Antwort des Servers
129    */
130   public String tilgen(HttpExchange t) {
131     String antwort; // = null;
132     try {
133       Object o = t.getAttribute(App.PI_PLAYER);
134       if(o == null) {
135         t.setAttribute(App.PI_PLAYER, null);
136         // t.removeAttribute(App.PI_PLAYER);
137         antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt.";
138       } else {
139         kommando(t, App.CMD_STOP);
140         //t.removeAttribute(PI_PLAYER);
141         antwort = "Player gestoppt, Kontext bereinigt.";
142       }
143     } 
144     catch(Exception ex) {
145       antwort = "Fehler: " + ex.getMessage();
146     }
147     return antwort;
148   }
149   
150   
151   /**
152    * Dem laufenden Abspielprozess ein Kommando uebermitteln
153    * @param t
154    * @param k  das Kommando laut 
155    * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
156    * @return die Antwort des Servers
157    */
158   public String kommando(HttpExchange t, String k) {
159     String antwort; // = null;
160     try {
161       Object o = t.getAttribute(App.PI_PLAYER);
162       if(o == null) {
163         //servletContext.removeAttribute(PI_PLAYER);
164         t.setAttribute(App.PI_PLAYER, null);
165         antwort = "Es wird nichts abgespielt dem ein Kommando gesendet werden kann.";
166       } else {
167         Process player_process = (Process) o;
168         OutputStream os = player_process.getOutputStream();
169         Writer out = new BufferedWriter(new OutputStreamWriter(os));
170         out.write(k);
171         out.flush();
172         if(k.equals(App.CMD_STOP)) {
173           out.close();
174           //player_process.destroy();
175           //player_process = null;
176           t.setAttribute(App.PI_PLAYER, null);
177           //servletContext.removeAttribute(PI_PLAYER);
178         }
179         antwort = "Kommando '" + k + "' ausgefuehrt.";
180       }
181     } 
182     catch(IOException ex) {
183       antwort = "Fehler: " + ex.getMessage();
184     }
185     return antwort;
186   }
187   
188   /* ------ Implementierung ProzessLauscher ----------------- */
189   
190   @Override
191   public void prozessBeendet(String meldeUrlStr) {
192     try {
193       HttpURLConnection conn = (HttpURLConnection) new URL(meldeUrlStr).openConnection();
194       conn.setRequestMethod("GET");
195       conn.connect();
196       int status = conn.getResponseCode();
197       logger.log(Level.INFO, "Abspielen beendet, Meldung an {0} mit Statuscode {1} gesendet.", new Object[]{meldeUrlStr, status});
198     } catch(IOException ex) {
199       logger.log(Level.INFO, ex.getMessage(), ex);
200     }
201   }
202   
203 }