App zur Steuerung des mpv Mediaplayers auf einem Raspberry Pi über HTTP
undisclosed
2023-01-08 929228226e08e352769810f729f0e9644a781bec
commit | author | age
929228 1 /*
U 2     Calypso - Media Player Remote Control via HTTP for Raspberry Pi
3     Copyright (C) 2021-2023  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
19 package de.uhilger.calypso.neu.http;
20
21 import com.sun.net.httpserver.HttpContext;
22 import com.sun.net.httpserver.HttpExchange;
23 import de.uhilger.calypso.neu.actor.PlayActor;
24 import de.uhilger.calypso.neu.actor.ShellActor;
25 import de.uhilger.calypso.neu.actor.StopServerActor;
26 import java.io.IOException;
27 import java.util.Collection;
28 import java.util.Map;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31
32 /**
33  * Der ApiHandler ist die proprietaer fuer Calypso vorgesehene 
34  * Weise, HTTP-Anfragen zu verarbeiten.
35  *
36  * Der ApiHandler ist ein HttpHandler, der vom Server ueber die 
37  * gesamte Laufzeit des Programmes hinweg gehalten wird. Deswegen 
38  * beschraenkt sich der Programmcode des ApiHandlers auf die
39  * Verteilung der Kommandos auf Aktoren. Die Aktoren werden je nach 
40  * Bedarf instanziiert und enthalten zusammengenommen den Code 
41  * des Anwendungskerns.
42  *
43  * @author Ulrich Hilger
44  */
45 public class ApiHandler extends HttpApi {
46
47   public static final int PLAYERCMD = 2;
48   public static final int SERVERCMD = 3;
49   public static final String PLAY = "play";
50   public static final String PAUSE = "pause";
51   public static final String SEEK = "seek";
52   public static final String STOP = "stop";
53   public static final String SERVER = "server";
54   public static final String PING = "ping";
55   
56   public static final String PLAYER = "player-proc";
57   
58   /**
59    * Die HTTP-Anfrage ausführen
60    * 
61    * WICHTIG: Die HTTP-Parameter aus dem Query-Teil muessen in 
62    * der Reihenfolge sein, die vom Shell-Skript erwartet wird. 
63    *
64    * @param elems die Elemente des URI-Pfads
65    * @param parameter die Parameter des Query-Teils der URI
66    * @param exchange das Objekt mit Infos zum HTTP-Aufruf
67    * @return die Antwort, die gesendet werden soll
68    */
69   @Override
70   protected String process(String[] elems, Map parameter, HttpExchange exchange) {
71     String antwort;
72     Object o;
73
74     switch (elems[PLAYERCMD]) {
75       case PLAY:
76         PlayActor a = new PlayActor();
77         o = a.run(parameter);
78         if (o instanceof Process) {
79           exchange.getHttpContext().getAttributes().put(PLAYER, o);
80           antwort = "Abspielprozess gestartet.";
81         } else {
82           // kein Prozess, es ist etwas schief gelaufen
83           antwort = "Abspielen konnte nicht gestartet werden.";
84         }
85         break;
86
87       case PAUSE:
88       case SEEK:
89         ShellActor pa = new ShellActor();      
90         try {
91           pa.run(getSkriptDir(exchange), elems[PLAYERCMD], toShellParams(parameter));
92           antwort = elems[PLAYERCMD] + " ausgefuehrt";
93         } catch (IOException ex) {
94           Logger.getLogger(ApiHandler.class.getName()).log(Level.SEVERE, null, ex);
95           antwort = "Fehler bei der Ausfuehrung von " + elems[PLAYERCMD];
96         }        
97         break;
98
99       case STOP:
100         o = exchange.getHttpContext().getAttributes().get(PLAYER);
101         if(o instanceof Process) {
102           Process p = (Process) o;
103           p.destroy();
104           antwort = "Player gestoppt.";
105         } else {
106           antwort = "Es wurde kein Player-Prozess zum Stoppen gefunden.";
107         }
108         break;
109         
110       case SERVER:
111         if(elems[SERVERCMD].equals(STOP)) {
112           new StopServerActor().run(exchange.getHttpContext());
113           antwort = "Calypso: Der Server wird angehalten und die App beendet.";
114         } else {
115           antwort = elems[SERVERCMD] + " ist ein unbekanntes Serverkommando";
116         }
117         break;
118         
119       case PING:
120         antwort = elems[PLAYERCMD];
121         break;
122         
123       default:
124         antwort = "Kommando " + elems[PLAYERCMD] + " unbekannt";
125         break;
126     }
127
128     return antwort;
129   }
130   
131   private String[] toShellParams(Map parameter) {
132     Collection<String> c = parameter.values();
133     return c.toArray(String[]::new);
134   }
135
136   private String getSkriptDir(HttpExchange exchange) {
137     HttpContext context = exchange.getHttpContext();
138     Object o = context.getAttributes().get(Server.SKRIPT_DIR);
139     if (o instanceof String) {
140       return (String) o;
141     } else {
142       // kein Skript-Dir
143       return "";
144     }
145   }
146 }