/* 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 . */ package de.uhilger.avdirektor.handler; 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.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 class OMXPlayer implements Player , ProzessLauscher { private static final Logger logger = Logger.getLogger(OMXPlayer.class.getName()); public static final String NAME = "omxplayer"; 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 { Process o = App.getPlayerProcess(); if(o != null) { tilgen(); } List kommando = new ArrayList(); kommando.add(NAME); kommando.addAll(Arrays.asList(parameter.split(BLANK))); if(urlStr.startsWith("http")) { kommando.add(urlStr.replace(" ", "%20")); } else { kommando.add(App.getInitParameter("nfs-prefix") + urlStr); } logger.log(Level.FINE, "parameter: {0}", parameter); logger.log(Level.FINE, "kommando: {0}", 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); mt.lauscherHinzufuegen(this); mt.setMeldeUrl(meldeUrlStr); mt.start(); } App.setPlayerProcess(player_process); antwort = "Abspielen gestartet, url: " + urlStr; } catch(IOException ex) { antwort = "Fehler: " + ex.getMessage(); } return antwort; } /** * Einen eventuell laufenden Abspielprozess beenden und den * Servlet-Kontext bereinigen.Diese Methode kann auch verwendet werden, wenn es beim normalen Abspielen zu Fehlern kommt und womoeglich der Servlet-Kontext noch eine Referenz zu einem Abspielprozess enthaelt, die nicht mehr aktuell ist. * * Mit der Methode tilgen kann man eine solche Referenz entfernen und gibt so das Objekt wieder frei fuer die Ausfuehrung weiterer Kommandos. * * @return die Antwort des Servers */ @Override public String tilgen() { String antwort; // = null; try { Process o = App.getPlayerProcess(); if(o == null) { antwort = "Es ist kein Player zum Beenden vorhanden, aber der Servlet-Kontext wurde bereinigt."; App.setPlayerProcess(null); } else { kommando(CMD_STOP); // setzt den Prozess der App auf null antwort = "Player gestoppt, Kontext bereinigt."; } } catch(Exception ex) { antwort = "Fehler: " + ex.getMessage(); } return antwort; } /** * Dem laufenden Abspielprozess ein Kommando uebermitteln * @param k das Kommando laut * Liste der Kommandos * @return die Antwort des Servers */ @Override public String kommando(String k) { String antwort; // = null; try { //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); antwort = "Es wird nichts abgespielt dem ein Kommando gesendet werden kann."; } else { Process player_process = o; OutputStream os = player_process.getOutputStream(); Writer out = new BufferedWriter(new OutputStreamWriter(os)); out.write(k); out.flush(); if(k.equals(CMD_STOP)) { out.close(); App.setPlayerProcess(null); //player_process.destroy(); //player_process = null; //t.setAttribute(App.PI_PLAYER, null); //servletContext.removeAttribute(PI_PLAYER); } antwort = "Kommando '" + k + "' ausgefuehrt."; } } catch(IOException ex) { antwort = "Fehler: " + ex.getMessage(); } return antwort; } /* ------ Implementierung ProzessLauscher ----------------- */ @Override public void prozessBeendet(String meldeUrlStr) { try { HttpURLConnection conn = (HttpURLConnection) new URL(meldeUrlStr).openConnection(); 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}); App.setPlayerProcess(null); } catch(IOException ex) { logger.log(Level.INFO, ex.getMessage(), ex); } } }