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