From 929228226e08e352769810f729f0e9644a781bec Mon Sep 17 00:00:00 2001
From: undisclosed
Date: Sun, 08 Jan 2023 13:35:06 +0000
Subject: [PATCH] Calypso neu gebaut auf Nutzung von mpv, alte Fassung entfernt

---
 src/de/uhilger/calypso/neu/MeldeThread.java           |   10 
 /dev/null                                             |   72 ------
 src/de/uhilger/calypso/neu/ProzessLauscher.java       |    3 
 src/de/uhilger/calypso/neu/actor/PlayActor.java       |   87 +++++++
 src/de/uhilger/calypso/neu/http/Server.java           |   69 +++++
 src/de/uhilger/calypso/neu/http/ApiHandler.java       |  146 ++++++++++++
 src/de/uhilger/calypso/neu/AppProperties.java         |   15 -
 src/de/uhilger/calypso/neu/Rueckmelder.java           |   46 +++
 src/de/uhilger/calypso/neu/App.java                   |   19 +
 src/de/uhilger/calypso/neu/http/HttpApi.java          |   97 ++++++++
 src/de/uhilger/calypso/neu/actor/StopServerActor.java |   53 ++++
 src/de/uhilger/calypso/neu/actor/ShellActor.java      |   73 ++++++
 12 files changed, 599 insertions(+), 91 deletions(-)

diff --git a/src/de/uhilger/calypso/App.java b/src/de/uhilger/calypso/App.java
deleted file mode 100644
index 3b17088..0000000
--- a/src/de/uhilger/calypso/App.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
-    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso;
-
-import de.uhilger.calypso.handler.MPVPlayer;
-import de.uhilger.calypso.handler.MPlayer;
-import de.uhilger.calypso.handler.OMXPlayer;
-import de.uhilger.calypso.handler.Player;
-import de.uhilger.calypso.handler.VLCPlayer;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Hauptklasse von Calypso
- * 
- * Aufruf mit<br>
- * java -jar calypso.jar port=9000 ctx="/calypso"<br>
- * java -jar calypso.jar nfs-prefix="/media/mc" port=9000<br>
- * java -Djava.util.logging.config.file=logging.properties -jar ..<br>
- * 
- * Der Parameter nfs-prefix bewirkt, dass beim Abspielen relative Pfade 
- * mit diesem Praefix verbunden werden und setzt voraus, dass auf der 
- * Maschine ein NFS-Mount ueber /etc/fstab eingerichtet ist.<br>
- * <br>
- * Anmerkung anlaesslich der Aenderung auf VLC (2.1.2023):<br>
- * Mit Calypso wurde erstmals jdk.httpserver anstelle von Tomcat 
- * einsetzt. Es war in diesem Punkt noch ein Laborversuch und sollte 
- * unter Wiederverwendung der wesentlichen Teile bei Gelegenheit 
- * neu gebaut werden.
- * 
- * @author Ulrich Hilger
- * @version 0.2 vom 2.1.2023, 0.1 vom 20.03.2021 als Nachfolger von Pirc (02.2013-03.2021)
- */
-public class App {
-  
-  private static final Logger logger = Logger.getLogger(App.class.getName());
-  
-  public static final String IP_PORT = "port";
-  public static final String IP_WWW_DATA = "www-data";
-  public static final String IP_NFS_PREFIX = "nfs-prefix";
-  public static final String IP_PLAYER = "player";
-  public static final String VLC_PLAYER = "vlc";
-  public static final String OMX_PLAYER = "omx";
-  public static final String M_PLAYER = "mpl";
-  public static final String MPV_PLAYER = "mpv";
-  public static final String OMX_WD = "omx.wd";
-  public static final String CTX = "ctx";
-  public static final String CONF_PATH = "conf";
-  
-  public static final String DEFAULT_CTX = "/calypso";
-  
-  private static HashMap initParams;  
-  private static Process playerproc;
-  private static Player player;
-  
-  /**
-   * @param args the command line arguments
-   */
-  public static void main(String[] args) {
-    Logger.getLogger(App.class.getName()).log(Level.INFO, new File(".").getAbsolutePath());
-    initParams = new HashMap();
-    for(String arg: args) {
-      String[] argParts = arg.split("=");
-      initParams.put(argParts[0], argParts[1]);
-    }
-        
-    String playerType = getInitParameter(IP_PLAYER);
-    switch(playerType) {
-      case MPV_PLAYER:
-        player = new MPVPlayer();
-        break;
-      case M_PLAYER:
-        player = new MPlayer();
-        break;
-      case VLC_PLAYER:
-        player = new VLCPlayer();
-        break;
-      case OMX_PLAYER:
-        player = new OMXPlayer();
-        break;
-    }
-    Server server = new Server(Integer.parseInt(getInitParameter(IP_PORT)));
-    server.setPath(getInitParameter(CONF_PATH));
-    String ctx = getInitParameter(CTX);
-    if(ctx != null && ctx.length() > 0) {
-      server.setContextName(ctx);    
-    } else {
-      server.setContextName(DEFAULT_CTX);
-    }
-    try {
-      server.start(playerType);
-    } catch (IOException ex) {
-      Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
-    }
-  }
-  
-  public static void stop() {
-    System.exit(0);
-  }
-  
-  public static String getInitParameter(String pname) {
-    String param = null;
-    Object o = initParams.get(pname);
-    if(o != null) {
-      param = o.toString();
-    }
-    return param;
-  } 
-  
-  public static Process getPlayerProcess() {
-    return playerproc;
-  }
-  
-  public static void setPlayerProcess(Process p) {
-    playerproc = p;
-  }
-  
-  public static Player getPlayer() {
-    return player;
-  }
-
-  public static void setPlayer(Player pl) {
-    player = pl;
-  }
-  
-  
-  
-}
diff --git a/src/de/uhilger/calypso/Betrachter.java b/src/de/uhilger/calypso/Betrachter.java
deleted file mode 100644
index 3890072..0000000
--- a/src/de/uhilger/calypso/Betrachter.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package de.uhilger.calypso;
-
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.net.URL;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.imageio.ImageIO;
-import org.tw.pi.framebuffer.FrameBuffer;
-
-/**
- * Klasse zum Betrachten von Fotografien auf dem Fernseher 
- * mit dem Raspberry Pi
- * 
- * Diese Klasse verwendet die Klasse JavaFrameBuffer 
- * von Thomas Welsch, die die Ausgabe direkt in den 
- * FrameBuffer des Raspberry Pi erlaubt. 
- * 
- * Der JavaFrameBuffer ist mit Calypso 
- * enthalten und erfordert, dass beim Start die native 
- * Programmbibliothek namens 'libFrameBuffer.so' eingebunden wird, die im Verteilpaket 
- * von Calypso enthalten ist. Zum Einbinden der nativen Biliothek genuegt die 
- * Angabe von -Djava.library.path=/pfad/zum/lib-ordner im Startskript von 
- * Calypso.
- * 
- * Durch die Verwendung des Framebuffer kann das Betrachten von 
- * Bildern auf dem Fernseher erfolgen ohne, dass auf dem Raspberry Pi 
- * eine grafische Bedienoberflaeche wie z.B. das X Windowing System, 
- * XBMC oder OpenELEC, usw. laufen muss. Es genuegt Java  
- * im 'headless mode', was zudem die Bedienbarkeit aus der Ferne via 
- * HTTP hinzufuegt.
- * 
- * @author Ulrich Hilger, https://uhilger.de
- * @author Published under the terms and conditions of
- * the <a href="http://www.gnu.org/licenses/agpl-3.0" target="_blank">GNU Affero General Public License</a>
- * 
- * @version 2 vom 11. Februar 2022, Version 1 war vom 15.1.2014
- */
-public class Betrachter {
-
-  public static final long serialVersionUID = 42L;
-  
-  private static final Logger logger = Logger.getLogger(Betrachter.class.getName());
-  
-  public static final String P_FBDEV = "fbdev";
-  public static final String STANDARD_FBDEV = "/dev/fb0";
-
-  public static final String P_URL = "u";
-  public static final String P_X = "x";
-  public static final String P_Y = "y";
-  public static final String P_WIDTH = "w";
-  public static final String P_HEIGHT = "h";
-  
-  //public static final String PATH_ZEIGEN = "/zeigen";
-  //public static final String PATH_LOESCHEN = "/loeschen";
-  
-  private FrameBuffer jfb;
-  private BufferedImage img;
-  private Graphics2D g;
-
-  public void init(String devName) {
-    String device = devName;
-    if(device == null) {
-      device = STANDARD_FBDEV;
-    }
-    jfb = new FrameBuffer(device, false);
-    img = jfb.getScreen();
-    g = img.createGraphics();
-  }
-  
-  public void close() {
-    jfb.close();
-  }
-  
-  public void jfbHelloWorld() {
-    g.setColor(Color.RED);
-    g.drawString("Hello World !", 50, 50);
-    jfb.updateScreen();
-  }
-  
-  /**
-   * Anzeigen eines Bildes mit Hilfe des JavaFrameBuffers
-   * 
-   * Diese Methode laedt ein Bild via HTTP oder HTTPS und 
-   * schreibt es in den Framebuffer zur Anzeige
-   * 
-   * @param urlStr  Adresse des Bildes, das angezeigt werden soll
-   * @param x waagerechte Koordinate der gewuenschten Position der linken oberen Ecke des Bildes
-   * @param y senkrechte Koordinate der gewuenschten Position der linken oberen Ecke des Bildes
-   * @param w Breite in Bildpunkten, in der das Bild angezeigt werden soll
-   * @param h Hoehe in Bildpunkten, in der das Bild angezeigt werden soll
-   */
-  public String jfbBildZeigen(String urlStr, int x, int y, int w, int h) {
-    String antwort = "jfbBildZeigen hat nicht geklappt";
-    BufferedImage webimg = null;
-    try {
-      /*
-        vgl. http://java.kompf.de/java2d.html
-      */
-      //System.setProperty("sun.java2d.opengl","true");      
-      URL url = new URL(urlStr);
-      webimg = ImageIO.read(url);
-      g.drawImage(webimg, x, y, w, h, null);    
-      jfb.updateScreen();
-      antwort = urlStr + " geladen";
-    } catch (Exception e) {
-      antwort = e.getMessage();
-    }
-    return antwort;
-  }
-  
-  /**
-   * Leeren des FrameBuffers 
-   * 
-   * Hier wird einfach ein Linux-Prozess eroeffnet, der das 
-   * Kommando dd if=/dev/zero of=/dev/fb0 ausfuehrt und 
-   * den Framebuffer mit Nullwerten fuellt
-   */
-  public String fbLeeren(String deviceName) {
-    String antwort = "fbLeeren hat nicht geklappt";
-    try {
-      String cmd = "dd if=/dev/zero of=" + deviceName;
-      Process leeren = Runtime.getRuntime().exec(cmd);      
-      /*MeldeThread t = new MeldeThread();
-      t.setProcess(leeren);
-      t.lauscherHinzufuegen(new ProzessLauscherImpl() {
-        @Override
-        public void prozessBeendet() {
-          // etwas tun, wenn fertig...
-        }
-      });
-      t.start();*/
-      antwort = "Prozess gestartet";
-    } catch(Exception ex) {
-      logger.log(Level.FINE, ex.getMessage(), ex);
-    }
-    return antwort;
-  } 
-  
-  
-  
-}
diff --git a/src/de/uhilger/calypso/OMXLogLeser.java b/src/de/uhilger/calypso/OMXLogLeser.java
deleted file mode 100644
index 8450481..0000000
--- a/src/de/uhilger/calypso/OMXLogLeser.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package de.uhilger.calypso;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class OMXLogLeser {
-  
-  private static final Logger logger = Logger.getLogger(OMXLogLeser.class.getName());
-  
-  public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
-  
-  private static final long MILLIS = (long) 1000;
-  
-  private static final long MINSEC = (long) 60;
-  
-  
-  public String logDirLesen(File logDir) throws IOException, FileNotFoundException, ParseException {
-    Blocks blocks = new Blocks();
-    File[] files = logDir.listFiles();
-    for(File file : files) {
-      lesen(file, blocks);
-    }
-    return blocks.getTimeString();
-  }
-      
-  /**
-   * 
-   * <p>Die Spieldauer laut OMX-Log ergibt sich aus dem Zeitstempel des 
-   * letzten Eintrags abzueglich des Zeitstempels des 
-   * ersten Eintrags abzueglich der Pausen</p>
-   * 
-   * <p>Eine Pause ist der Zeitraum vom Zeitstempel eines Eintrags mit 
-   * <code>Keyboard: character p (0x70)</code> bis zum Zeitstempel des 
-   * n&auml;chsten Eintrags mit <code>Keyboard: character p</code></p>
-   * 
-   * 
-   * @param logfile
-   * @param blocks
-   * @return  die Spieldauer als String im Format H:MM:SS
-   * @throws FileNotFoundException
-   * @throws IOException
-   * @throws ParseException 
-   */
-  public void lesen(File logfile, Blocks blocks) throws FileNotFoundException, IOException, ParseException {    
-    boolean inPause = false;
-    logger.info("Starting to parse log..");
-    Date parseStart = new Date();
-    long lineCount = 0;
-    InputStream is = new FileInputStream(logfile);
-    BufferedReader r = new BufferedReader(new InputStreamReader(is));
-    String firstLine = r.readLine();
-    ++lineCount;
-    String lastLine = "";
-    String line = r.readLine();
-    //Blocks blocks = new Blocks();
-    Block currentBlock = new Block();
-    while(line != null) {
-      ++lineCount;
-      if(currentBlock.getStart() == null) {
-        currentBlock.setStart(line.substring(0, 8));
-      }
-      if(line.contains("Keyboard: character p")) {
-        if(inPause) {
-          currentBlock.setStart(line.substring(0, 8));          
-        } else {
-          currentBlock.setEnd(line.substring(0, 8));
-          blocks.add(currentBlock);
-          currentBlock = new Block();
-        }
-        inPause = !inPause;
-      }
-      lastLine = line;
-      line = r.readLine();
-    }
-    currentBlock.setEnd(lastLine.substring(0, 8));
-    blocks.add(currentBlock);
-    Date parseEnd = new Date();
-    long timeMillis = parseEnd.getTime() - parseStart.getTime();
-    long timeSeconds = timeMillis / MILLIS;
-    long secMillis = timeSeconds * MILLIS;
-    long restMillis = timeMillis - secMillis;
-    logger.log(Level.INFO, 
-            "{0} lines parsed in {1} seconds and {2} milliseconds.", 
-            new Object[]{lineCount, timeSeconds, restMillis});
-    //return blocks.getTimeString();
-  }
-  
-  class Block {
-    private String start = null;
-    private String end = null;
-    
-    public long getDuration() throws ParseException {
-      Date startDate = sdf.parse(start);
-      Date endDate = sdf.parse(end);
-      return endDate.getTime() - startDate.getTime();
-    }
-
-    public String getStart() {
-      return start;
-    }
-
-    public void setStart(String start) {
-      //logger.log(Level.FINER, "Start: ''{0}''", start);
-      this.start = start;
-    }
-
-    public String getEnd() {
-      return end;
-    }
-
-    public void setEnd(String end) {
-      //logger.log(Level.FINER, "End: ''{0}''", end);
-      this.end = end;
-    }
-    
-    
-  }
-  
-  class Blocks {
-    
-    private final List<Block> blocks = new ArrayList();
-    
-    public void add(Block block) {
-      blocks.add(block);
-    }
-    
-    public long getDuration() throws ParseException {
-      long duration = (long) 0;
-      Iterator<Block> i = blocks.iterator();
-      while(i.hasNext()) {
-        Block b = i.next();
-        duration += b.getDuration();
-      }
-      return duration;
-    }
-    
-    public String getTimeString() throws ParseException {
-      long diff = getDuration();
-      long h = diff / MILLIS / MINSEC / MINSEC;
-      long hmillis = h * MINSEC * MINSEC  * MILLIS;
-      long m = (diff - hmillis) / MILLIS / MINSEC;
-      long mmillis = m * MINSEC * MILLIS;
-      long s = (diff - hmillis - mmillis) / MILLIS;
-      //logger.log(Level.FINER, "{0}:{1}:{2}", new Object[]{h, m, s});
-      return h + ":" + m + ":" + s;
-    }
-  }
-}
diff --git a/src/de/uhilger/calypso/Server.java b/src/de/uhilger/calypso/Server.java
deleted file mode 100644
index 9948ece..0000000
--- a/src/de/uhilger/calypso/Server.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
-    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
-*/
-package de.uhilger.calypso;
-
-import com.sun.net.httpserver.HttpServer;
-import de.uhilger.calypso.handler.BasePlayer;
-import de.uhilger.calypso.handler.CmdHandler;
-import de.uhilger.calypso.handler.DBusHandler;
-import de.uhilger.calypso.handler.FileHandler;
-import de.uhilger.calypso.handler.LogHandler;
-import de.uhilger.calypso.handler.MPVKillHandler;
-import de.uhilger.calypso.handler.MPVPlayHandler;
-import de.uhilger.calypso.handler.MPVPlayer;
-import de.uhilger.calypso.handler.MPVSeekHandler;
-import de.uhilger.calypso.handler.MPlayHandler;
-import de.uhilger.calypso.handler.MPlayer;
-import de.uhilger.calypso.handler.OMXPlayer;
-import de.uhilger.calypso.handler.PingHandler;
-import de.uhilger.calypso.handler.PlayHandler;
-import de.uhilger.calypso.handler.PlayOnHandler;
-import de.uhilger.calypso.handler.SeekHandler;
-import de.uhilger.calypso.handler.SocketHandler;
-import de.uhilger.calypso.handler.StopServerHandler;
-import de.uhilger.calypso.handler.VLCKillHandler;
-import de.uhilger.calypso.handler.VLCPlayer;
-import de.uhilger.calypso.handler.VLCSeekHandler;
-import java.io.File;
-import java.io.IOException;
-import java.util.logging.Logger;
-import java.net.InetSocketAddress;
-import java.util.concurrent.Executors;
-import java.util.logging.Level;
-
-/**
- * Die Klasse Server implementiert die HTTP-Schnittstelle zum 
- * Mediaplayer. Es wird ein Player-Prozesss fuer das Abspielen 
- * eines Titels gestartet. Mit Stopp oder Ende des Titels endet 
- * auch der Abspielprozess.<br>
- * <br>
- * zum Abspielen:<br>
- * /calypso/play?title=http://ein.titel.mp3&r=http://rueckmelde.url<br>
- * <br>
- * waehrend des Abspielens:<br>
- * /calypso/pause<br>
- * /calypso/seek?pos=[sekunden]<br>
- * /calypso/stop<br>
- * <br>
- * sonstige Funktionen:<br>
- * /calypso/ping<br>
- * /calypso/server/stop<br>
- * <br>
- * verworfene Funktionen<br>
- * /calypso/vol-inc<br>
- * /calypso/vol-dec<br>
- * Die Lautstaerke wird in aller Regel am Geraet geregelt, an das der 
- * Zuspieler (der Raspi) angeschlossen ist. Eine Regelung ueber den 
- * Zuspieler ist daher eher selten erforderlich.
- * 
- * @author Ulrich Hilger
- */
-public class Server {
-
-  private static final Logger logger = Logger.getLogger(Server.class.getName());
-
-  private int port;
-
-  private String contextName;
-
-  private String path;
-  
-  public Server(int port) {
-    this.port = port;
-  }
-
-  public void setPort(int port) {
-    this.port = port;
-  }
-  
-  public void setPath(String path) {
-    this.path = path;
-  }
-
-  /**
-   *
-   * @param contextName e.g. '/calypso' or '/cal'
-   */
-  public void setContextName(String contextName) {
-    this.contextName = contextName;
-  }
-
-  public void start(String playerType) throws IOException {
-    logger.log(Level.INFO, "Server starting on port {0}", port);
-
-    HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
-    
-    if (playerType.equals(App.OMX_PLAYER)) {
-      server.createContext(contextName + "/play", new PlayHandler(BasePlayer.F_PLAY));
-      server.createContext(contextName + "/seek", new SeekHandler(OMXPlayer.F_SEEK));
-      server.createContext(contextName + "/stop", new CmdHandler(OMXPlayer.CMD_STOP));
-      server.createContext(contextName + "/pause", new CmdHandler(OMXPlayer.CMD_PAUSE_RESUME));
-      server.createContext(contextName + "/vol-inc", new CmdHandler(OMXPlayer.CMD_INC_VOL));
-      server.createContext(contextName + "/vol-dec", new CmdHandler(OMXPlayer.CMD_DEC_VOL));
-      server.createContext(contextName + "/info", new CmdHandler(OMXPlayer.CMD_TOGGLE_INFO));
-      server.createContext(contextName + "/log", new LogHandler());
-      server.createContext(contextName + "/playon", new PlayOnHandler(OMXPlayer.F_PLAY_ON));
-    } else if (playerType.equals(App.VLC_PLAYER)) {
-      server.createContext(contextName + "/play", new PlayHandler(BasePlayer.F_PLAY));
-      server.createContext(contextName + "/pause", new DBusHandler(VLCPlayer.CMD_PAUSE_RESUME));
-      //server.createContext(contextName + "/pause", new CmdHandler("pause"));
-      //server.createContext(contextName + "/seek", new DBusHandler(VLCPlayer.CMD_SEEK));
-      server.createContext(contextName + "/seek", new VLCSeekHandler(VLCPlayer.CMD_SEEK));
-      server.createContext(contextName + "/stop", new VLCKillHandler());
-    } else if (playerType.equals(App.M_PLAYER)) {
-      server.createContext(contextName + "/play", new MPlayHandler());
-      server.createContext(contextName + "/pause", new CmdHandler(MPlayer.CMD_PAUSE_RESUME));
-      server.createContext(contextName + "/stop", new CmdHandler(MPlayer.CMD_STOP));
-    } else if (playerType.equals(App.MPV_PLAYER)) {
-      server.createContext(contextName + "/play", new MPVPlayHandler());
-      server.createContext(contextName + "/pause", new SocketHandler(path + MPVPlayer.CMD_PAUSE_RESUME));
-      server.createContext(contextName + "/seek", new MPVSeekHandler(path + MPVPlayer.CMD_SEEK));
-      server.createContext(contextName + "/stop", new MPVKillHandler());
-    }
-    server.createContext(contextName + "/ui", new FileHandler(App.getInitParameter(App.IP_WWW_DATA)));
-    server.createContext(contextName + "/ping", new PingHandler(BasePlayer.F_PING));
-    server.createContext(contextName + "/server/stop", new StopServerHandler());
-    //server.setExecutor(null); // creates a default executor
-    server.setExecutor(Executors.newFixedThreadPool(20));
-    server.start();
-  }
-
-}
diff --git a/src/de/uhilger/calypso/handler/AbstractHandler.java b/src/de/uhilger/calypso/handler/AbstractHandler.java
deleted file mode 100644
index a46d368..0000000
--- a/src/de/uhilger/calypso/handler/AbstractHandler.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public abstract class AbstractHandler implements HttpHandler {
-
-  private static final Logger logger = Logger.getLogger(AbstractHandler.class.getName());
-  
-  protected String cmd;
-  protected Map map;
-  
-  @Override
-  public void handle(HttpExchange t) throws IOException {
-    logger.log(Level.FINE, "RequestURI: {0}", t.getRequestURI().toString());
-    StringBuilder params = buildParams(t);
-    String antwort = process(t, params.toString());
-    sendResponse(t, cmd, antwort);
-  }
-  
-  protected abstract String process(HttpExchange t, String params);
-  
-  protected StringBuilder buildParams(HttpExchange t) {
-    map = getQueryMap(t);
-    StringBuilder params = new StringBuilder();
-    return params;
-  }
-  
-  protected void sendResponse(HttpExchange t, String cmd, String antwort) throws IOException {
-    String response = getResponseString(map, cmd, antwort);
-    t.sendResponseHeaders(200, response.length());
-    OutputStream os = t.getResponseBody();
-    os.write(response.getBytes());
-    os.close();    
-  }
-  
-  public void setCmd(String cmd) {
-    this.cmd = cmd;
-  }
-  
-  public String getCmd(String cmd) {
-    return this.cmd;
-  }
-
-  /* --- --- */
-  
-  /*
-    Den Query-Teil einer URL in die Parameter zerlegen
-  
-    Die Zerlegung erfolgt mit String.split nach 
-    &amp; und dann nach =
-  */
-  protected Map getQueryMap(HttpExchange t) {
-    HashMap map = new HashMap();
-    String query = t.getRequestURI().getQuery();
-    if(query != null && query.length() > 0) {
-      String qParts[] = query.split("&");
-      for(String qPart : qParts) {
-        logger.finer("qPart: " + qPart);
-        String pParts[] = qPart.split("=");
-        map.put(pParts[0], pParts[1]);
-        logger.finer("pParts[0]: " + pParts[0] + ", pParts[1]: " + pParts[1]);
-      }
-    }
-    return map;
-  }
-  
-  protected String getResponseString(Map map, String cmd, String antwort) {
-    Set keys = map.keySet();
-    StringBuilder buf = new StringBuilder();
-    buf.append(cmd);
-    buf.append(System.lineSeparator());
-    keys.forEach((Object key) -> {
-      buf.append("key: ");
-      buf.append(key);
-      buf.append(System.lineSeparator());
-      buf.append("value: "); 
-      buf.append(map.get(key));
-      buf.append(System.lineSeparator());
-      //logger.log(Level.FINE, "key {0} value {1}", new Object[]{key, map.get(key)});
-    });
-    buf.append(antwort);
-    return buf.toString();
-  }    
-  
-}
diff --git a/src/de/uhilger/calypso/handler/BasePlayer.java b/src/de/uhilger/calypso/handler/BasePlayer.java
deleted file mode 100644
index 19576a4..0000000
--- a/src/de/uhilger/calypso/handler/BasePlayer.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import de.uhilger.calypso.App;
-import static de.uhilger.calypso.handler.OMXPlayer.CMD_STOP;
-import java.io.BufferedWriter;
-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.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulli
- */
-public abstract class BasePlayer implements Player {
-  
-  private static final Logger logger = Logger.getLogger(BasePlayer.class.getName());
-  
-  public static final String F_PLAY = "play";
-  public static final String F_PING = "ping";
-
-  
-  @Override
-  public void prozessBeendet(String meldeUrlStr) {
-    logger.log(Level.INFO, 
-              "Abspielen beendet, sende Meldung an {0}.", 
-              new Object[]{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});
-          /*
-            fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
-            oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
-            dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
-            auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
-            auf null gesetzt.
-          */
-      //App.setPlayerProcess(null);
-    } catch(IOException ex) {
-      logger.log(Level.INFO, ex.getMessage(), ex);
-    }
-  }
-
-  @Override
-  public String tilgen() {
-    logger.log(Level.INFO,"Player tilgen.");
-    String antwort; // = null;
-    try {
-      Process o = App.getPlayerProcess();
-      if(o == null) {
-        antwort = "Es ist kein Player zum Beenden vorhanden.";
-        //App.setPlayerProcess(null);
-      } else {
-        kommando(CMD_STOP); // setzt den Prozess der App auf null
-        antwort = "Player gestoppt.";
-      }
-    } 
-    catch(Exception ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-    public String getParam(Map map, String key) {
-    Object o = map.get(key);
-    if(o != null) {
-      return o.toString();
-    } else {
-      return null;
-    }
-  }
-  
-  /**
-   * Dem laufenden Abspielprozess ein Kommando uebermitteln
-   * @param k  das Kommando laut 
-   * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
-   * @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();
-        antwort = "Kommando '" + k + "' ausgefuehrt.";
-      }
-    } 
-    catch(IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-}
diff --git a/src/de/uhilger/calypso/handler/CmdHandler.java b/src/de/uhilger/calypso/handler/CmdHandler.java
deleted file mode 100644
index a8abc29..0000000
--- a/src/de/uhilger/calypso/handler/CmdHandler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class CmdHandler extends AbstractHandler {
-
-  private static final Logger logger = Logger.getLogger(CmdHandler.class.getName());
-  
-  public CmdHandler(String cmd) {
-    this.cmd = cmd;
-  }
-  
-  protected String process(HttpExchange t, String params) {
-    String antwort = App.getPlayer().kommando(cmd);
-    logger.log(Level.FINE, antwort);
-    return antwort;
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/DBusHandler.java b/src/de/uhilger/calypso/handler/DBusHandler.java
deleted file mode 100644
index 0f6be4d..0000000
--- a/src/de/uhilger/calypso/handler/DBusHandler.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Obwohl ein laufendes VLC-Programm mit Tastaturbefehlen gesteuert 
- * werden kann, funktioniert es nicht, dem Prozess einen Tastaturbefehl
- * wie z.B. S fuer Stopp ueber process.getOutputStream zu 'schreiben', 
- * moeglicherweise, weil auf dem Raspberry Pi das VLC als Kommando-
- * zeilenprogramm ohne UI laeuft. Im Augenblick gelingt nur die Steuerung 
- * ueber dbus. Hier muss noch geprueft werden, ob das auch mit Windows und 
- * Mac OS klappt, was aber fuer einen Einsatz auf dem Raspberry Pi 
- * nebensaechlich ist.
- * 
- * Die Steuerung von VLC via dbus wiederum folgt dem Standard mpris 
- * (Media Player Remote Interfacing Specification) von freedesktop.org, 
- * der von zahlreichen Mediaplayern unterstuetzt wird.
- * 
- * @author Ulrich Hilger
- */
-public class DBusHandler extends CmdHandler {
-  
-  private static final Logger logger = Logger.getLogger(DBusHandler.class.getName());
-
-  public DBusHandler(String cmd) {
-    super(cmd);
-  }
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-      String antwort;// = null;
-    try {
-      StringBuilder kommando = new StringBuilder();
-      kommando.append(VLCPlayer.DBUS_PREFIX);
-      kommando.append(cmd);
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      antwort = "Kommando ausgefuehrt: " + kommando;
-    } catch (IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-}
diff --git a/src/de/uhilger/calypso/handler/FileHandler.java b/src/de/uhilger/calypso/handler/FileHandler.java
deleted file mode 100644
index caaf149..0000000
--- a/src/de/uhilger/calypso/handler/FileHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class FileHandler implements HttpHandler {
-  
-  private static final Logger logger = Logger.getLogger(FileHandler.class.getName());
-  
-  private final String basePath;
-  
-  public FileHandler(String basePath) {
-    this.basePath = basePath;
-  }
-
-  @Override
-  public void handle(HttpExchange t) throws IOException {
-    String ctxPath = t.getHttpContext().getPath();
-    String uriPath = t.getRequestURI().getPath();
-    String fName = uriPath.substring(ctxPath.length());
-    if(fName.endsWith("/")) {
-      fName += "index.html";
-    }
-    OutputStream os = t.getResponseBody();
-    File file = new File(basePath, fName);
-    if(file.exists()) {    
-      t.sendResponseHeaders(200, file.length());
-      InputStream in = new FileInputStream(file);
-      int b = in.read();
-      while(b > -1) {
-        os.write(b);
-        b = in.read();
-      }
-      in.close();
-    } else {
-      String response = fName + " not found.";
-      byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
-      t.sendResponseHeaders(404, bytes.length);
-      os.write(bytes);
-    }
-    os.flush();
-    os.close();    
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/LogHandler.java b/src/de/uhilger/calypso/handler/LogHandler.java
deleted file mode 100644
index f22421c..0000000
--- a/src/de/uhilger/calypso/handler/LogHandler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.OMXLogLeser;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.text.ParseException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class LogHandler extends AbstractHandler {
-  
-  private static final Logger logger = Logger.getLogger(LogHandler.class.getName());
-  
-  @Override
-  public void handle(HttpExchange t) throws IOException {
-    logger.log(Level.FINE, "RequestURI: {0}", t.getRequestURI().toString());
-    StringBuilder params = buildParams(t);
-    String antwort = process(t, params.toString());
-    sendResponse(t, cmd, antwort);
-  }
-  
-  @Override
-  protected void sendResponse(HttpExchange t, String cmd, String antwort) throws IOException {
-    t.sendResponseHeaders(200, antwort.length());
-    OutputStream os = t.getResponseBody();
-    os.write(antwort.getBytes());
-    os.close();    
-  }
-  
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-    /*
-    OMXLogLeser leser = new OMXLogLeser();
-    String lines = "Log nicht lesbar.";
-    try {
-      logger.info(new File(".").getAbsolutePath());
-      lines = leser.lesen(new File("omxplayer.log"));
-    } catch (IOException ex) {
-      Logger.getLogger(LogHandler.class.getName()).log(Level.SEVERE, null, ex);
-    } catch (ParseException ex) {
-      Logger.getLogger(LogHandler.class.getName()).log(Level.SEVERE, null, ex);
-    }
-    */
-    return "";
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/MPVKillHandler.java b/src/de/uhilger/calypso/handler/MPVKillHandler.java
deleted file mode 100644
index f3240f0..0000000
--- a/src/de/uhilger/calypso/handler/MPVKillHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-
-/**
- *
- * @author Ulrich Hilger
- */
-public class MPVKillHandler extends AbstractHandler {
-  
-  @Override
-  protected String process(HttpExchange t, String params) {
-      Process p = App.getPlayerProcess();
-      p.destroy();
-      App.setPlayerProcess(null);
-    String antwort = "Player-Prozess beendet.";
-    return antwort;
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/MPVPlayHandler.java b/src/de/uhilger/calypso/handler/MPVPlayHandler.java
deleted file mode 100644
index 52e84a1..0000000
--- a/src/de/uhilger/calypso/handler/MPVPlayHandler.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author Ulrich Hilger
- */
-public class MPVPlayHandler extends AbstractHandler {
-  
-  private static final Logger logger = Logger.getLogger(MPVPlayHandler.class.getName());
-  
-  @Override
-  protected String process(HttpExchange t, String params) {
-    Player player = App.getPlayer();
-    String antwort = player.abspielen(
-            player.getParam(map, "titel"), params, player.getParam(map, "r"), "1");
-    logger.log(Level.FINE, antwort);
-    return antwort;
-  }
-
-  
-  
-}
diff --git a/src/de/uhilger/calypso/handler/MPVPlayer.java b/src/de/uhilger/calypso/handler/MPVPlayer.java
deleted file mode 100644
index fc169dd..0000000
--- a/src/de/uhilger/calypso/handler/MPVPlayer.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import de.uhilger.calypso.MeldeThread;
-import java.io.IOException;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class MPVPlayer extends BasePlayer implements Player {
-  
-  private static final Logger logger = Logger.getLogger(MPVPlayer.class.getName());
-
-  /*
-echo '{ "command": ["get_property", "playback-time"] }' | socat - /tmp/mpvsocket
-{"data":190.482000,"error":"success"}
-
-echo 'show-text ${playback-time}' | socat - /tmp/mpvsocket  
-  
-  { "command": ["set_property", "pause", true] }
-  { "error": "success" }
-  
-{"command": ["cycle", "pause"]}  
-
-  */
-  public static final String SOCK_PREFIX = "";
-  public static final String CMD_PAUSE_RESUME = "pause";
-  public static final String CMD_SEEK = "seek";
-
-  @Override
-  public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
-    String antwort;// = null;
-    try {
-      //Object o = t.getAttribute(App.PI_PLAYER);
-      Process o = App.getPlayerProcess();
-      if(o != null) {
-        tilgen();        
-      }
-      StringBuilder kommando = new StringBuilder("mpv --input-ipc-server=/tmp/mpvsocket --no-terminal ");
-      
-      /*
-      mpv versucht Musikstuecke mit Album-Bildern in den Metadaten als Video 
-      abzuspielen und bricht ab.
-      (diese Einstellung muss noch parametriert und erweitert werden)
-      */
-      if(urlStr.contains(".mp3")) {
-        kommando.append("--vo=null ");
-      }
-      /*
-      if(parameter != null) {
-        kommando.append(parameter);
-        kommando.append(BLANK);
-      }
-      */
-      if(urlStr.startsWith("http")) {
-        kommando.append(urlStr.replace(" ", "%20"));
-        kommando.append("?t=");
-        kommando.append(token);
-      } else {
-        /*
-          //url z.B.: Filme/H/HEAT_D2.m4v
-        
-          hier muss noch der Pfad hinzugefuegt werden, unter 
-          dem auf dem raspi die Datenquelle via NFS eingebunden ist,
-          z.B. /media/mc/
-          dieser Teil des Pfades muss in pirc als Init-Parameter oder 
-          etwas aehnliches hinterlegt sein, weil es lokal zum jeweils 
-          verwendeten raspi gehoert
-  
-        */
-        
-        String pfad = App.getInitParameter("nfs-prefix");
-        kommando.append(pfad);
-        
-        kommando.append(urlStr);
-      }
-      //kommando.append(" vlc://quit");
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      if(meldeUrlStr != null) {
-        MeldeThread mt = new MeldeThread();
-        mt.setProcess(player_process);
-        mt.lauscherHinzufuegen(this);
-        mt.setMeldeUrl(meldeUrlStr);
-        mt.start();
-      }
-      //servletContext.setAttribute(App.PI_PLAYER, player_process);
-      //t.setAttribute(App.PI_PLAYER, player_process);
-      App.setPlayerProcess(player_process);
-      //Runtime.getRuntime().exec("killall dbus-daemon");
-      antwort = "Abspielen gestartet, url: " + urlStr;
-    }
-    catch(IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-  
-  /*
-  public String kommando(String k) {
-    if(k.equalsIgnoreCase(VLCPlayer.CMD_STOP)) {
-      Process p = App.getPlayerProcess();
-      p.destroy();
-      App.setPlayerProcess(null);
-    }
-    String antwort = "Kommando '" + k + "' ausgefuehrt.";
-    return antwort;
-  }
-*/
-
-  @Override
-  public StringBuilder buildParams(HttpExchange t, Map m) {
-    return new StringBuilder();
-  }
-
-
-}
diff --git a/src/de/uhilger/calypso/handler/MPVSeekHandler.java b/src/de/uhilger/calypso/handler/MPVSeekHandler.java
deleted file mode 100644
index 097c6d4..0000000
--- a/src/de/uhilger/calypso/handler/MPVSeekHandler.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * http://server:9090/calypso/seek?pos=30 (30 Sekunden vor) oder pos=-30 (zurueck)
- * 
- * echo '{"command": ["seek", '30']}' | socat - /tmp/mpvsocket
- * echo '{"command": ["seek", '-30']}' | socat - /tmp/mpvsocket
- * 
- * in einem Shell Skript
- * echo '{"command": ["seek", '$1']}' | socat - /tmp/mpvsocket
- * 
- * 
- * @author Ulrich Hilger
- */
-public class MPVSeekHandler extends CmdHandler {
-
-  private static final Logger logger = Logger.getLogger(MPVSeekHandler.class.getName());
-
-  public MPVSeekHandler(String cmd) {
-    super(cmd);
-  }
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-    String antwort;// = null;
-    try {
-      StringBuilder kommando = new StringBuilder();
-      //kommando.append(VLCPlayer.DBUS_PREFIX);
-      kommando.append(cmd);
-      kommando.append(params);
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      antwort = "Kommando ausgefuehrt: " + kommando;
-    } catch (IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-  @Override
-  protected StringBuilder buildParams(HttpExchange t) {
-    Player player = App.getPlayer();
-    StringBuilder params = super.buildParams(t);
-
-    if (player instanceof MPVPlayer) {
-      String pos = player.getParam(map, "pos");
-      if (!pos.isEmpty()) {
-        params.append(" ");
-        params.append(pos);
-      }
-    }
-
-    logger.log(Level.FINER, "params: " + params.toString());
-    return params;
-  }
-}
diff --git a/src/de/uhilger/calypso/handler/MPlayHandler.java b/src/de/uhilger/calypso/handler/MPlayHandler.java
deleted file mode 100644
index 7ccb685..0000000
--- a/src/de/uhilger/calypso/handler/MPlayHandler.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author Ulrich Hilger
- */
-public class MPlayHandler extends AbstractHandler {
-  
-  private static final Logger logger = Logger.getLogger(MPlayHandler.class.getName());
-  
-  @Override
-  protected String process(HttpExchange t, String params) {
-    Player player = App.getPlayer();
-    String antwort = player.abspielen(
-            player.getParam(map, "titel"), params, player.getParam(map, "r"), "1");
-    logger.log(Level.FINE, antwort);
-    return antwort;
-  }
-
-  
-  
-}
diff --git a/src/de/uhilger/calypso/handler/MPlayer.java b/src/de/uhilger/calypso/handler/MPlayer.java
deleted file mode 100644
index 6539233..0000000
--- a/src/de/uhilger/calypso/handler/MPlayer.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import de.uhilger.calypso.MeldeThread;
-import java.io.IOException;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author Ulrich Hilger
- */
-public class MPlayer extends BasePlayer {
-
-  private static final Logger logger = Logger.getLogger(MPlayer.class.getName());
-
-  public static final String CMD_STOP = "q";
-  public static final String CMD_PAUSE_RESUME = "p";
-
-  @Override
-  public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
-    String antwort;// = null;
-    try {
-      //Object o = t.getAttribute(App.PI_PLAYER);
-      Process o = App.getPlayerProcess();
-      if(o != null) {
-        tilgen();        
-      }
-      StringBuilder kommando = new StringBuilder("mplayer -cache 2048 -cache-min 80 -really-quiet -framedrop ");
-      /*
-      if(parameter != null) {
-        kommando.append(parameter);
-        kommando.append(BLANK);
-      }
-      */
-      if(urlStr.startsWith("http")) {
-        kommando.append(urlStr.replace(" ", "%20"));
-        //kommando.append("?t=");
-        //kommando.append(token);
-      } else {
-        /*
-          //url z.B.: Filme/H/HEAT_D2.m4v
-        
-          hier muss noch der Pfad hinzugefuegt werden, unter 
-          dem auf dem raspi die Datenquelle via NFS eingebunden ist,
-          z.B. /media/mc/
-          dieser Teil des Pfades muss in pirc als Init-Parameter oder 
-          etwas aehnliches hinterlegt sein, weil es lokal zum jeweils 
-          verwendeten raspi gehoert
-  
-        */
-        
-        String pfad = App.getInitParameter("nfs-prefix");
-        kommando.append(pfad);
-        
-        kommando.append(urlStr);
-      }
-      //kommando.append(" vlc://quit");
-      //kommando.append(" >>/dev/null 2>&1");
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      if(meldeUrlStr != null) {
-        MeldeThread mt = new MeldeThread();
-        mt.setProcess(player_process);
-        mt.lauscherHinzufuegen(this);
-        mt.setMeldeUrl(meldeUrlStr);
-        mt.start();
-      }
-      //servletContext.setAttribute(App.PI_PLAYER, player_process);
-      //t.setAttribute(App.PI_PLAYER, player_process);
-      App.setPlayerProcess(player_process);
-      //Runtime.getRuntime().exec("killall dbus-daemon");
-      antwort = "Abspielen gestartet, url: " + urlStr;
-    }
-    catch(IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-  @Override
-  public StringBuilder buildParams(HttpExchange t, Map m) {
-    return new StringBuilder();
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/OMXPlayer.java b/src/de/uhilger/calypso/handler/OMXPlayer.java
deleted file mode 100644
index f012ad9..0000000
--- a/src/de/uhilger/calypso/handler/OMXPlayer.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import de.uhilger.calypso.MeldeThread;
-import de.uhilger.calypso.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.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-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 extends BasePlayer 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_TOGGLE_INFO = "z";
-  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 = "="; // oder "+";
-  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_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<String> 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;
-  }
-  
-  @Override
-  public StringBuilder buildParams(HttpExchange t, Map map) {
-    StringBuilder params = new StringBuilder();
-    params.append("-o ");
-    params.append(getParam(map, "o"));
-    params.append(" --threshold ");
-    params.append(getParam(map, "th"));
-    params.append(" --timeout ");
-    params.append(getParam(map, "ti"));
-    String log = getParam(map, "log");
-    if (log != null && log.equalsIgnoreCase("true")) {
-      params.append(" --genlog");
-    }
-    return params;
-  }
-  
-    
-  /**
-   * 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.";
-        //App.setPlayerProcess(null);
-      } else {
-        kommando(CMD_STOP); // setzt den Prozess der App auf null
-        antwort = "Player gestoppt.";
-      }
-    } 
-    catch(Exception 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});
-          /*
-            fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
-            oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
-            dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
-            auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
-            auf null gesetzt.
-          */
-      //App.setPlayerProcess(null);
-  /*
-    } catch(IOException ex) {
-      logger.log(Level.INFO, ex.getMessage(), ex);
-    }
-  }
-  */
-}
diff --git a/src/de/uhilger/calypso/handler/PingHandler.java b/src/de/uhilger/calypso/handler/PingHandler.java
deleted file mode 100644
index 5ecd735..0000000
--- a/src/de/uhilger/calypso/handler/PingHandler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class PingHandler extends CmdHandler {
-  
-  private static final Logger logger = Logger.getLogger(PingHandler.class.getName());
-
-  public PingHandler(String cmd) {
-    super(cmd);
-  }
-
-  protected String process(HttpExchange t, String params) {
-    logger.log(Level.FINE, cmd);
-    return cmd;
-  }  
-  
-  protected void sendResponse(HttpExchange t, String cmd, String antwort) throws IOException {
-    t.sendResponseHeaders(200, antwort.length());
-    OutputStream os = t.getResponseBody();
-    os.write(antwort.getBytes());
-    os.close();    
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/PlayHandler.java b/src/de/uhilger/calypso/handler/PlayHandler.java
deleted file mode 100644
index 7b09208..0000000
--- a/src/de/uhilger/calypso/handler/PlayHandler.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
- */
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.io.IOException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Play
- *
- * rpi4-az:9090/avd/play?titel=/Filme/S/sound_city.m4v&th=60&ti=60&o=local
- *
- * OMXPlayer.abspielenMitParameternUndRueckmeldung( String urlStr, String
- * parameter, String meldeUrlStr, String token)
- *
- * Parameter des Aufrufs play als query (th threshold, ti timeout)
- *
- * ?titel=/Filme/S/sound_city.m4v &ti=60 &th=60 &o=local|hdmi|both
- * &r=http://uhilger.de/mc/api/usw
- *
- * r muss ganz wegbleiben, wenn keine Rueckmeldung gewuescht ist
- *
- * @author ulrich
- */
-public class PlayHandler extends CmdHandler {
-
-  private static final Logger logger = Logger.getLogger(PlayHandler.class.getName());
-
-  public PlayHandler(String cmd) {
-    super(cmd);
-  }
-
-  
-  @Override
-  protected StringBuilder buildParams(HttpExchange t) {
-    StringBuilder params = super.buildParams(t);
-    params.append(App.getPlayer().buildParams(t, map));
-    return params;
-  }
-  
-  
-  /*
-  protected StringBuilder buildParams(HttpExchange t) {
-    StringBuilder params = super.buildParams(t);
-    params.append("-o ");
-    params.append(getParam(map, "o"));
-    params.append(" --threshold ");
-    params.append(getParam(map, "th"));
-    params.append(" --timeout ");
-    params.append(getParam(map, "ti"));
-    String log = getParam(map, "log");
-    if (log != null && log.equalsIgnoreCase("true")) {
-      params.append(" --genlog");
-    }
-    return params;
-  }
-  */
-  
-  @Override
-  protected String process(HttpExchange t, String params) {
-    if (cmd.equalsIgnoreCase(BasePlayer.F_PLAY)) {
-      try {
-        //FileUtils.deleteDirectory(new File(System.getProperty("omx.wd"), "omx-logs"));
-        FileSystem fs = FileSystems.getDefault();
-        Path path = fs.getPath(System.getProperty("omx.wd"), "omx-logs");
-        if(path.toFile().exists()) {
-          deleteDirectory(path);
-        }
-        //Files.delete(path);
-      } catch (IOException ex) {
-        logger.log(Level.SEVERE, null, ex);
-      }
-    }
-    Player player = App.getPlayer();
-    String antwort = player.abspielen(
-            player.getParam(map, "titel"), params, player.getParam(map, "r"), "1");
-    logger.log(Level.FINE, antwort);
-    return antwort;
-  }
-
-  protected void deleteDirectory(Path start) throws IOException {
-    Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
-      @Override
-      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-              throws IOException {
-        Files.delete(file);
-        return FileVisitResult.CONTINUE;
-      }
-
-      @Override
-      public FileVisitResult postVisitDirectory(Path dir, IOException e)
-              throws IOException {
-        if (e == null) {
-          Files.delete(dir);
-          return FileVisitResult.CONTINUE;
-        } else {
-          // directory iteration failed
-          throw e;
-        }
-      }
-    });
-  }
-
-}
diff --git a/src/de/uhilger/calypso/handler/PlayOnHandler.java b/src/de/uhilger/calypso/handler/PlayOnHandler.java
deleted file mode 100644
index 957677e..0000000
--- a/src/de/uhilger/calypso/handler/PlayOnHandler.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import de.uhilger.calypso.OMXLogLeser;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * z.B.
- * http://rpi4-az:9090/avd/playon?th=1&ti=240&o=local&log=true&titel=http://amd-srv:9090/srv/Filme/C/casino_royale.m4v
- *
- * @author ulrich
- */
-public class PlayOnHandler extends PlayHandler {
-
-  private static final Logger logger = Logger.getLogger(PlayOnHandler.class.getName());
-  
-  public static final String LOG_DIR = "omx-logs";
-  public static final String LOG_EXT = "log";
-  public static final String DASH = "-";
-  public static final String DOT = ".";
-
-  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
-
-  public PlayOnHandler(String cmd) {
-    super(cmd);
-  }
-
-  /*
-    1. buildParams
-    2. process
-   */
-  @Override
-  protected StringBuilder buildParams(HttpExchange t) {
-    File logDir = logSichern();
-    StringBuilder params = super.buildParams(t);
-    params.append(" --pos ");
-    try {
-      params.append(dauerBestimmen(logDir));
-    } catch (IOException | ParseException ex) {
-      logger.log(Level.SEVERE, null, ex);
-    }
-    return params;
-  }
-  
-  private File logSichern() {
-    String wd = System.getProperty(App.OMX_WD);
-    File zielOrdner = new File(wd, LOG_DIR);
-    try {
-      // omxplayer.log umbenennen
-      FileSystem fs = FileSystems.getDefault();
-      Path logDatei = fs.getPath(wd, OMXPlayer.NAME + DOT + LOG_EXT);
-      Date now = new Date();
-      String neuerName = OMXPlayer.NAME + DASH + sdf.format(now) + DOT + LOG_EXT;
-      Files.move(logDatei, logDatei.resolveSibling(neuerName));
-
-      // Unterverzeichnis ggf. erzeugen
-      zielOrdner.mkdirs();
-
-      // omxplayer-datum.log verschieben
-      Path quellDatei = fs.getPath(wd, neuerName);
-      Path zielPfad = fs.getPath(wd, LOG_DIR);
-      Files.move(quellDatei, zielPfad.resolve(quellDatei.getFileName()), REPLACE_EXISTING);
-    } catch (IOException ex) {
-      logger.log(Level.SEVERE, null, ex);
-    }
-    return zielOrdner;
-  }
-
-  private String dauerBestimmen(File logDir) throws IOException, FileNotFoundException, ParseException {
-    OMXLogLeser leser = new OMXLogLeser();
-    return leser.logDirLesen(logDir);
-  }
-
-}
diff --git a/src/de/uhilger/calypso/handler/Player.java b/src/de/uhilger/calypso/handler/Player.java
deleted file mode 100644
index 9808bcb..0000000
--- a/src/de/uhilger/calypso/handler/Player.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.ProzessLauscher;
-import java.util.Map;
-
-/**
- *
- * @author ulrich
- */
-public interface Player extends ProzessLauscher {
-
-  /**
-   * Einen Prozess zum Abspielen mit dem omxplayer starten
-   * @param urlStr  URL der Quelle, die abgespielt werden soll
-   * @param token
-   * @return Antwort des Servers
-   */
-  /*
-  public String abspielen(String urlStr, String token) {
-  return abspielenMitParametern(urlStr, null, token);
-  }
-   */
-  /*
-  public String abspielenMitRueckmeldung(String urlStr, String meldeUrlStr, String token) {
-  return abspielenMitParameternUndRueckmeldung(urlStr, null, meldeUrlStr, token);
-  }
-   */
-  /**
-   * Einen Prozess zum Abspielen mit dem omxplayer starten
-   * und Parameter uebergeben.Moegliche Parameter fuer das Abspielen mit dem omxplayer
-  beschreibt die Seite
-  <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.
-   * App.OPT_LOCAL_AUDIO oder App.OPT_HDMI_AUDIO.
-  Mehrere Parameter werden mit App.BLANK getrennt.
-   * @param urlStr  der URL der Quelle, die abgespielt werden soll
-   * @param parameter  die Parameter, die vom omxplayer angewendet werden sollen
-   * @param token
-   * @return Antwort des Servers
-   */
-  /*
-  public String abspielenMitParametern(String urlStr, String parameter, String token) {
-  return abspielenMitParameternUndRueckmeldung(urlStr, parameter, null, token);
-  }
-   */
-  String abspielen(String urlStr, String parameter, String meldeUrlStr, String token);
-
-  /**
-   * Dem laufenden Abspielprozess ein Kommando uebermitteln
-   * @param k  das Kommando laut
-   * <a href="https://github.com/huceke/omxplayer/blob/master/README.md" target="_blank">Liste der Kommandos</a>
-   * @return die Antwort des Servers
-   */
-  String kommando(String k);
-  
-  StringBuilder buildParams(HttpExchange t, Map m);
-  
-  String getParam(Map map, String key);
-
-  /* ------ Implementierung ProzessLauscher ----------------- */
-  void prozessBeendet(String meldeUrlStr);
-
-  /**
-   * 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
-   */
-  String tilgen();
-  
-}
diff --git a/src/de/uhilger/calypso/handler/SeekHandler.java b/src/de/uhilger/calypso/handler/SeekHandler.java
deleted file mode 100644
index 9d3c255..0000000
--- a/src/de/uhilger/calypso/handler/SeekHandler.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class SeekHandler extends PlayHandler  {
-  
-  private static final Logger logger = Logger.getLogger(SeekHandler.class.getName());
-
-  public SeekHandler(String cmd) {
-    super(cmd);
-  }
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-    Player player = App.getPlayer();
-    String antwort = player.abspielen( 
-            player.getParam(map, "titel"), params, player.getParam(map, "r"), "1");    
-    logger.log(Level.FINE, antwort);
-    return antwort;
-  }
-
-  /*
-    start "C:Program FilesVLCvlc.exe" rel="nofollow" "D:MoviesThe Italian Job.avi" --start-time 12 --stop-time 20
-
-    You simply have to use the command line as given above, with the file paths and the time changed as needed. 
-    The numbers 12 and 20 in the command line indicate 12 seconds and 20 seconds respectively.
-  
-  
-    --global-key-play-pause=<string> 
-                                 Play/Pause
-          Select the hotkey to use to swap paused state.  
-  */
-  protected StringBuilder buildParams(HttpExchange t) {
-    Player player = App.getPlayer();
-    StringBuilder params = super.buildParams(t);
-    if(player instanceof OMXPlayer) {
-      params.append(" --pos ");
-      params.append(player.getParam(map, "pos"));
-    }
-    return params;
-  }  
-  
-}
diff --git a/src/de/uhilger/calypso/handler/SocketHandler.java b/src/de/uhilger/calypso/handler/SocketHandler.java
deleted file mode 100644
index 8fce603..0000000
--- a/src/de/uhilger/calypso/handler/SocketHandler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Hier muss noch die Implementierung mit Unix Domain Sockets folgen,
- * sobald Java 16 fuer 64-bit Raspberry Pi 4 erhaeltlich ist.
- * 
- * Bis dahin wird hier (dirty trick) ein Shell Skript aufgerufen, 
- * das mit Hilfe des Tools socat das Kommando ausfuehrt. socat muss 
- * dafuer auf dem Raspberry Pi installiert sein.
- * 
- * Kommandos
- * 
- * pause: echo '{"command": ["cycle", "pause"]}' | socat - /tmp/mpvsocket
- * seek: echo '{"command": ["seek", '30']}' | socat - /tmp/mpvsocket
- * 
- * @author Ulrich Hilger
- */
-public class SocketHandler extends CmdHandler {
-  
-  private static final Logger logger = Logger.getLogger(SocketHandler.class.getName());
-
-  public SocketHandler(String cmd) {
-    super(cmd);
-  }
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-      String antwort;// = null;
-    try {
-      StringBuilder kommando = new StringBuilder();
-      kommando.append(MPVPlayer.SOCK_PREFIX);
-      kommando.append(cmd);
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      antwort = "Kommando ausgefuehrt: " + kommando;
-    } catch (IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-}
diff --git a/src/de/uhilger/calypso/handler/StopServerHandler.java b/src/de/uhilger/calypso/handler/StopServerHandler.java
deleted file mode 100644
index 1bf848b..0000000
--- a/src/de/uhilger/calypso/handler/StopServerHandler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    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 <https://www.gnu.org/licenses/>.
-*/
-
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import de.uhilger.calypso.App;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class StopServerHandler extends OMXPlayer implements HttpHandler {
-
-  @Override
-  public void handle(HttpExchange exchange) throws IOException {
-    Logger.getLogger(StopServerHandler.class.getName()).info(exchange.getRequestURI().toString());    
-    this.kommando(CMD_STOP);
-    String response = "Server stopped";
-    exchange.sendResponseHeaders(200, response.length());
-    OutputStream os = exchange.getResponseBody();
-    os.write(response.getBytes());
-    os.flush();
-    os.close();
-    Logger.getLogger(StopServerHandler.class.getName()).info("stopping app.");    
-    App.stop();
-    //exchange.getHttpContext().getServer().stop(5);
-  }
-  
-  
-}
diff --git a/src/de/uhilger/calypso/handler/VLCKillHandler.java b/src/de/uhilger/calypso/handler/VLCKillHandler.java
deleted file mode 100644
index 34325f1..0000000
--- a/src/de/uhilger/calypso/handler/VLCKillHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
- * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
- */
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-
-/**
- *
- * @author ulli
- */
-public class VLCKillHandler extends AbstractHandler {
-  
-  @Override
-  protected String process(HttpExchange t, String params) {
-      Process p = App.getPlayerProcess();
-      p.destroy();
-      App.setPlayerProcess(null);
-    String antwort = "Player-Prozess beendet.";
-    return antwort;
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/handler/VLCPlayer.java b/src/de/uhilger/calypso/handler/VLCPlayer.java
deleted file mode 100644
index c2c1aba..0000000
--- a/src/de/uhilger/calypso/handler/VLCPlayer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import de.uhilger.calypso.MeldeThread;
-import java.io.IOException;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author ulrich
- */
-public class VLCPlayer extends BasePlayer implements Player {
-  
-  private static final Logger logger = Logger.getLogger(VLCPlayer.class.getName());
-
-  public static final String CMD_STOP = "s";
-  public static final String DBUS_PREFIX = "dbus-send --type=method_call --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2   org.mpris.MediaPlayer2.Player.";
-  public static final String CMD_PAUSE_RESUME = "PlayPause";
-  public static final String CMD_SEEK = "Seek";
-  public static final String CMD_VOLUME = "Volume";
-
-  @Override
-  public String abspielen(String urlStr, String parameter, String meldeUrlStr, String token) {
-    String antwort;// = null;
-    try {
-      //Object o = t.getAttribute(App.PI_PLAYER);
-      Process o = App.getPlayerProcess();
-      if(o != null) {
-        tilgen();        
-      }
-      StringBuilder kommando = new StringBuilder("vlc --fullscreen ");
-      /*
-      if(parameter != null) {
-        kommando.append(parameter);
-        kommando.append(BLANK);
-      }
-      */
-      if(urlStr.startsWith("http")) {
-        kommando.append(urlStr.replace(" ", "%20"));
-        kommando.append("?t=");
-        kommando.append(token);
-      } else {
-        /*
-          //url z.B.: Filme/H/HEAT_D2.m4v
-        
-          hier muss noch der Pfad hinzugefuegt werden, unter 
-          dem auf dem raspi die Datenquelle via NFS eingebunden ist,
-          z.B. /media/mc/
-          dieser Teil des Pfades muss in pirc als Init-Parameter oder 
-          etwas aehnliches hinterlegt sein, weil es lokal zum jeweils 
-          verwendeten raspi gehoert
-  
-        */
-        
-        String pfad = App.getInitParameter("nfs-prefix");
-        kommando.append(pfad);
-        
-        kommando.append(urlStr);
-      }
-      kommando.append(" vlc://quit");
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      if(meldeUrlStr != null) {
-        MeldeThread mt = new MeldeThread();
-        mt.setProcess(player_process);
-        mt.lauscherHinzufuegen(this);
-        mt.setMeldeUrl(meldeUrlStr);
-        mt.start();
-      }
-      //servletContext.setAttribute(App.PI_PLAYER, player_process);
-      //t.setAttribute(App.PI_PLAYER, player_process);
-      App.setPlayerProcess(player_process);
-      //Runtime.getRuntime().exec("killall dbus-daemon");
-      antwort = "Abspielen gestartet, url: " + urlStr;
-    }
-    catch(IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-  
-  /*
-  public String kommando(String k) {
-    if(k.equalsIgnoreCase(VLCPlayer.CMD_STOP)) {
-      Process p = App.getPlayerProcess();
-      p.destroy();
-      App.setPlayerProcess(null);
-    }
-    String antwort = "Kommando '" + k + "' ausgefuehrt.";
-    return antwort;
-  }
-*/
-
-  @Override
-  public StringBuilder buildParams(HttpExchange t, Map m) {
-    return new StringBuilder();
-  }
-
-
-}
diff --git a/src/de/uhilger/calypso/handler/VLCSeekHandler.java b/src/de/uhilger/calypso/handler/VLCSeekHandler.java
deleted file mode 100644
index 8da3a3a..0000000
--- a/src/de/uhilger/calypso/handler/VLCSeekHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package de.uhilger.calypso.handler;
-
-import com.sun.net.httpserver.HttpExchange;
-import de.uhilger.calypso.App;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * dbus-send --type=method_call --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2
- * org.mpris.MediaPlayer2.Player.Seek int64:-5000000
- *
- * @author Ulrich Hilger
- */
-public class VLCSeekHandler extends CmdHandler {
-
-  private static final Logger logger = Logger.getLogger(VLCSeekHandler.class.getName());
-
-  public VLCSeekHandler(String cmd) {
-    super(cmd);
-  }
-
-  @Override
-  protected String process(HttpExchange t, String params) {
-    String antwort;// = null;
-    try {
-      StringBuilder kommando = new StringBuilder();
-      kommando.append(VLCPlayer.DBUS_PREFIX);
-      kommando.append(cmd);
-      kommando.append(params);
-      logger.log(Level.FINE, "kommando: {0}", kommando.toString());
-      Process player_process = Runtime.getRuntime().exec(kommando.toString());
-      antwort = "Kommando ausgefuehrt: " + kommando;
-    } catch (IOException ex) {
-      antwort = "Fehler: " + ex.getMessage();
-    }
-    return antwort;
-  }
-
-  @Override
-  protected StringBuilder buildParams(HttpExchange t) {
-    Player player = App.getPlayer();
-    StringBuilder params = super.buildParams(t);
-
-    if (player instanceof VLCPlayer) {
-      String pos = player.getParam(map, "pos");
-      if (!pos.isEmpty()) {
-        params.append(" ");
-        params.append("int64:");
-        params.append(pos);
-        params.append("000000"); // Mikrosekunden
-      }
-    }
-
-    logger.log(Level.FINER, "params: " + params.toString());
-    return params;
-  }
-}
diff --git a/src/de/uhilger/calypso/neu/App.java b/src/de/uhilger/calypso/neu/App.java
index 603f4ea..602707f 100644
--- a/src/de/uhilger/calypso/neu/App.java
+++ b/src/de/uhilger/calypso/neu/App.java
@@ -1,5 +1,24 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
 package de.uhilger.calypso.neu;
 
+import de.uhilger.calypso.neu.http.Server;
 import java.util.HashMap;
 
 /**
diff --git a/src/de/uhilger/calypso/neu/AppProperties.java b/src/de/uhilger/calypso/neu/AppProperties.java
index f80c4b8..aea7da8 100644
--- a/src/de/uhilger/calypso/neu/AppProperties.java
+++ b/src/de/uhilger/calypso/neu/AppProperties.java
@@ -59,20 +59,8 @@
     Logger.getLogger(AppProperties.class.getName()).log(Level.INFO, fName);
     InputStream in = null;
     try {
-      // Einstellungen aus Datei lesen
-      //AppProperties einst = new AppProperties();
       File einstellungenDatei = new File(fName);
       in = new FileInputStream(einstellungenDatei);
-     
-      //BufferedReader br = new BufferedReader(new InputStreamReader(in));
-      //String line = br.readLine();
-      //while(line != null) {
-      //  System.out.println(line);
-      //  line = br.readLine();
-      //}
-      //br.close();
-      
-      
       load(in);
       in.close();
     } catch (FileNotFoundException ex) {
@@ -86,8 +74,5 @@
         Logger.getLogger(AppProperties.class.getName()).log(Level.SEVERE, null, ex);
       }
     }
-      
-    
   }
-  
 }
diff --git a/src/de/uhilger/calypso/MeldeThread.java b/src/de/uhilger/calypso/neu/MeldeThread.java
similarity index 92%
rename from src/de/uhilger/calypso/MeldeThread.java
rename to src/de/uhilger/calypso/neu/MeldeThread.java
index 7d03fb5..a8ea023 100644
--- a/src/de/uhilger/calypso/MeldeThread.java
+++ b/src/de/uhilger/calypso/neu/MeldeThread.java
@@ -16,7 +16,7 @@
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-package de.uhilger.calypso;
+package de.uhilger.calypso.neu;
 
 import java.util.logging.Logger;
 import java.util.logging.Level;
@@ -45,11 +45,17 @@
     this.meldeUrlStr = meldeUrlStr;
   }
   
+  /**
+   * ausfuehren des Threads
+   */
+  @Override
   public void run() {
     try {
       exitValue = omxplayer.waitFor();
       prozessBeendetMelden();
-    } catch(Exception ex) {
+      lauscher.clear();
+      lauscher = null;
+    } catch(InterruptedException ex) {
       logger.log(Level.FINE, ex.getMessage(), ex);
     } finally {
       aufraeumen();
diff --git a/src/de/uhilger/calypso/ProzessLauscher.java b/src/de/uhilger/calypso/neu/ProzessLauscher.java
similarity index 96%
rename from src/de/uhilger/calypso/ProzessLauscher.java
rename to src/de/uhilger/calypso/neu/ProzessLauscher.java
index 0fdb5d2..6adff11 100644
--- a/src/de/uhilger/calypso/ProzessLauscher.java
+++ b/src/de/uhilger/calypso/neu/ProzessLauscher.java
@@ -16,8 +16,7 @@
     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
 
-package de.uhilger.calypso;
-
+package de.uhilger.calypso.neu;
 
 public interface ProzessLauscher {
   
diff --git a/src/de/uhilger/calypso/neu/Rueckmelder.java b/src/de/uhilger/calypso/neu/Rueckmelder.java
new file mode 100644
index 0000000..1680653
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/Rueckmelder.java
@@ -0,0 +1,46 @@
+package de.uhilger.calypso.neu;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Ulrich Hilger
+ */
+public class Rueckmelder implements ProzessLauscher {
+
+
+
+  @Override
+  public void prozessBeendet(String meldeUrlStr) {
+    Logger logger = Logger.getLogger(de.uhilger.calypso.neu.http.ApiHandler.class.getName());
+    logger.log(Level.INFO,
+            "Abspielen beendet, sende Meldung an {0}.",
+            new Object[]{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});
+      /*
+            fuer den Fall, dass ein Stopp-Signal den Player nicht erreicht 
+            oder dort nicht funktioniert, gibt es keine Moeglichkeit festzustellen,
+            dass der Player noch spielt. Damit in einem solchen Fall der Zeiger 
+            auf den Abspielprozess nicht verloren geht, wird  der Zeiger nicht 
+            auf null gesetzt.
+       */
+      //App.setPlayerProcess(null);
+    } catch (IOException ex) {
+      logger.log(Level.INFO, ex.getMessage(), ex);
+    }
+  }
+
+
+  
+}
diff --git a/src/de/uhilger/calypso/neu/Server.java b/src/de/uhilger/calypso/neu/Server.java
deleted file mode 100644
index db467ba..0000000
--- a/src/de/uhilger/calypso/neu/Server.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.uhilger.calypso.neu;
-
-import java.io.File;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author Ulrich Hilger
- */
-public class Server {
-  
-  private static final Logger logger = Logger.getLogger(de.uhilger.calypso.Server.class.getName());
-  
-  public static final String CONF = "conf";
-  public static final String PORT = "port";
-  public static final String SKRIPTE = "skripte";
-  
-  public static final String EQUAL = "=";
-  
-  private AppProperties einst; 
-  
-  public void start(AppProperties einst) {
-    logger.log(Level.INFO, "Server startet auf Port {0}", einst.getString(PORT));
-    this.einst = einst;
-    String skripte = einst.getString(SKRIPTE);
-    File playSkript = new File(skripte, "play");
-    if(playSkript.exists()) {
-      logger.log(Level.INFO, "Skripte gefunden in {0}", playSkript.getParentFile().getAbsolutePath());
-    } else {
-      logger.log(Level.INFO, "Skripte nicht gefunden, Ordner laut Einstellungen: {0}", skripte);
-    }
-  }
-  
-}
diff --git a/src/de/uhilger/calypso/neu/actor/PlayActor.java b/src/de/uhilger/calypso/neu/actor/PlayActor.java
new file mode 100644
index 0000000..d8a7a67
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/actor/PlayActor.java
@@ -0,0 +1,87 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
+package de.uhilger.calypso.neu.actor;
+
+import de.uhilger.calypso.neu.MeldeThread;
+import de.uhilger.calypso.neu.Rueckmelder;
+import de.uhilger.calypso.neu.http.Server;
+import java.io.IOException;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Der PlayActor loest das Abspielen eines Titels aus. 
+ * 
+ * Das koennte auch als Shell-Skript geschehen, aber abhaengig 
+ * vom verwendeten Abspielprogramm benoetigt man das Prozessobjekt 
+ * des laufenden Abspielprozesses im Verlauf des Abspielens noch, um 
+ * weitere Kommandos zu senden.
+ * 
+ * Beim Abspieler mpv werden Kommandos allerdings ueber Unix Domain 
+ * Sockets gesendet, hierfuer waere also das Objekt des laufenden 
+ * Abspielprozesses nicht noetig. Man benoetigt es aber auch um 
+ * festzustellen, ob der Abspielprozess beendet ist.
+ * 
+ * @author Ulrich Hilger
+ */
+public class PlayActor {
+
+  public Process run(Map parameter) {
+    String meldeUrlStr = null;
+    Object o = parameter.get("r");
+    if (o instanceof String) {
+      meldeUrlStr = (String) o;
+    }
+
+    StringBuilder kommando = new StringBuilder();
+    o = parameter.get("titel");
+    if (o instanceof String) {
+      String titel = (String) o;
+      if (titel.toLowerCase().endsWith(".mp3")) {
+        kommando.append("mpv --input-ipc-server=/tmp/mpvsocket --no-terminal --vo=null ");
+      } else {
+        kommando.append("mpv --input-ipc-server=/tmp/mpvsocket --no-terminal ");
+      }
+      kommando.append(Server.BLANK);
+      kommando.append(titel);
+      Logger.getLogger(PlayActor.class.getName()).log(Level.FINE, kommando.toString());
+      Process player_process;
+      try {
+        player_process = Runtime.getRuntime().exec(kommando.toString());
+        if (meldeUrlStr != null) {
+          MeldeThread mt = new MeldeThread();
+          mt.setProcess(player_process);
+          mt.lauscherHinzufuegen(new Rueckmelder());
+          mt.setMeldeUrl(meldeUrlStr);
+          mt.start();
+        }
+        return player_process;
+      } catch (IOException ex) {
+        Logger logger = Logger.getLogger(PlayActor.class.getName());
+        logger.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
+        ex.printStackTrace();
+        return null;
+      }
+    } else {
+      Logger.getLogger(PlayActor.class.getName()).log(Level.INFO, "Titel fehlt");
+      return null;
+    }
+  }
+}
diff --git a/src/de/uhilger/calypso/neu/actor/ShellActor.java b/src/de/uhilger/calypso/neu/actor/ShellActor.java
new file mode 100644
index 0000000..c912c51
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/actor/ShellActor.java
@@ -0,0 +1,73 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
+package de.uhilger.calypso.neu.actor;
+
+import de.uhilger.calypso.neu.http.Server;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ *
+ * Der mpv Abspieler erhaelt Kommandos waehrend des Abspielens 
+ * ueber Unix Domain Sockets. Da diese erst mit Java 16 untersuetzt 
+ * werden und Java 16 fuer den Raspberry Pi noch nicht erhaeltlich 
+ * ist, werden diese Kommandos als Shell-Skript unter Verwendung 
+ * des Linux-Programms socat gesendet.
+ * 
+ * Der Shell Actor fuehrt Skripte aus. Wenn ein Kommando Parameter 
+ * erfordert, werden diese aus dem Query-Teil des HTTP-Aufrufes 
+ * entnommen.
+ * 
+ * 
+ * @author Ulrich Hilger
+ */
+public class ShellActor {
+  
+  /**
+   * Ein Skript auf der Kommandozeile ausfuehren
+   * 
+   * @param skriptDir das Verzeichnis, in dem das Skript liegt
+   * @param kommando der Name des Skript
+   * @throws IOException 
+   */
+  //public void run(String skriptDir, String kommando) throws IOException {
+  //  File skriptFile = new File(skriptDir, kommando);
+  //  Process p = Runtime.getRuntime().exec(skriptFile.getAbsolutePath());
+  //}
+  
+  /**
+   * 
+   * @param skriptDir das Verzeichnis, in dem das Skript liegt
+   * @param kommando der Name des Skript
+   * @param params die Parameter des Shell-Kommandos, null, wenn keine
+   * @throws IOException 
+   */
+  public void run(String skriptDir, String kommando, String... params) throws IOException {
+    StringBuilder sb = new StringBuilder();
+    File skriptFile = new File(skriptDir, kommando);
+    sb.append(skriptFile.getAbsolutePath());
+    if(params instanceof String[]) {
+      for (String param : params) {
+        sb.append(Server.BLANK);
+        sb.append(param);
+      }
+    }
+    Process p = Runtime.getRuntime().exec(sb.toString());    
+  }
+}
diff --git a/src/de/uhilger/calypso/neu/actor/StopServerActor.java b/src/de/uhilger/calypso/neu/actor/StopServerActor.java
new file mode 100644
index 0000000..c73c6c0
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/actor/StopServerActor.java
@@ -0,0 +1,53 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
+package de.uhilger.calypso.neu.actor;
+
+import com.sun.net.httpserver.HttpContext;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Logger;
+
+/**
+ * Ein HTTP-Handler zum Stoppen der Anwendung
+ *
+ * @author Ulrich Hilger
+ */
+public class StopServerActor {
+  
+  public void run(HttpContext thisContext) {
+    Logger.getLogger(StopServerActor.class.getName()).info("Server wird gestoppt..");
+    thisContext.getServer().stop(1); // diesen Server stoppen
+    Timer timer = new Timer();
+    timer.schedule(new AppStopper(), 1500); // die App auch beenden
+  }
+
+  /**
+   * Die Klasse AppStopper erm&ouml;glicht das asnychrone bzw. 
+   * zeitgesteuerte Stoppen der Anwendung.
+   */
+  class AppStopper extends TimerTask {
+
+    @Override
+    public void run() {
+      Logger.getLogger(StopServerActor.class.getName()).info("Calypso beendet.");
+      System.exit(0);
+    }
+  }
+
+}
diff --git a/src/de/uhilger/calypso/neu/http/ApiHandler.java b/src/de/uhilger/calypso/neu/http/ApiHandler.java
new file mode 100644
index 0000000..e803df6
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/http/ApiHandler.java
@@ -0,0 +1,146 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
+package de.uhilger.calypso.neu.http;
+
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import de.uhilger.calypso.neu.actor.PlayActor;
+import de.uhilger.calypso.neu.actor.ShellActor;
+import de.uhilger.calypso.neu.actor.StopServerActor;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Der ApiHandler ist die proprietaer fuer Calypso vorgesehene 
+ * Weise, HTTP-Anfragen zu verarbeiten.
+ *
+ * Der ApiHandler ist ein HttpHandler, der vom Server ueber die 
+ * gesamte Laufzeit des Programmes hinweg gehalten wird. Deswegen 
+ * beschraenkt sich der Programmcode des ApiHandlers auf die
+ * Verteilung der Kommandos auf Aktoren. Die Aktoren werden je nach 
+ * Bedarf instanziiert und enthalten zusammengenommen den Code 
+ * des Anwendungskerns.
+ *
+ * @author Ulrich Hilger
+ */
+public class ApiHandler extends HttpApi {
+
+  public static final int PLAYERCMD = 2;
+  public static final int SERVERCMD = 3;
+  public static final String PLAY = "play";
+  public static final String PAUSE = "pause";
+  public static final String SEEK = "seek";
+  public static final String STOP = "stop";
+  public static final String SERVER = "server";
+  public static final String PING = "ping";
+  
+  public static final String PLAYER = "player-proc";
+  
+  /**
+   * Die HTTP-Anfrage ausführen
+   * 
+   * WICHTIG: Die HTTP-Parameter aus dem Query-Teil muessen in 
+   * der Reihenfolge sein, die vom Shell-Skript erwartet wird. 
+   *
+   * @param elems die Elemente des URI-Pfads
+   * @param parameter die Parameter des Query-Teils der URI
+   * @param exchange das Objekt mit Infos zum HTTP-Aufruf
+   * @return die Antwort, die gesendet werden soll
+   */
+  @Override
+  protected String process(String[] elems, Map parameter, HttpExchange exchange) {
+    String antwort;
+    Object o;
+
+    switch (elems[PLAYERCMD]) {
+      case PLAY:
+        PlayActor a = new PlayActor();
+        o = a.run(parameter);
+        if (o instanceof Process) {
+          exchange.getHttpContext().getAttributes().put(PLAYER, o);
+          antwort = "Abspielprozess gestartet.";
+        } else {
+          // kein Prozess, es ist etwas schief gelaufen
+          antwort = "Abspielen konnte nicht gestartet werden.";
+        }
+        break;
+
+      case PAUSE:
+      case SEEK:
+        ShellActor pa = new ShellActor();      
+        try {
+          pa.run(getSkriptDir(exchange), elems[PLAYERCMD], toShellParams(parameter));
+          antwort = elems[PLAYERCMD] + " ausgefuehrt";
+        } catch (IOException ex) {
+          Logger.getLogger(ApiHandler.class.getName()).log(Level.SEVERE, null, ex);
+          antwort = "Fehler bei der Ausfuehrung von " + elems[PLAYERCMD];
+        }        
+        break;
+
+      case STOP:
+        o = exchange.getHttpContext().getAttributes().get(PLAYER);
+        if(o instanceof Process) {
+          Process p = (Process) o;
+          p.destroy();
+          antwort = "Player gestoppt.";
+        } else {
+          antwort = "Es wurde kein Player-Prozess zum Stoppen gefunden.";
+        }
+        break;
+        
+      case SERVER:
+        if(elems[SERVERCMD].equals(STOP)) {
+          new StopServerActor().run(exchange.getHttpContext());
+          antwort = "Calypso: Der Server wird angehalten und die App beendet.";
+        } else {
+          antwort = elems[SERVERCMD] + " ist ein unbekanntes Serverkommando";
+        }
+        break;
+        
+      case PING:
+        antwort = elems[PLAYERCMD];
+        break;
+        
+      default:
+        antwort = "Kommando " + elems[PLAYERCMD] + " unbekannt";
+        break;
+    }
+
+    return antwort;
+  }
+  
+  private String[] toShellParams(Map parameter) {
+    Collection<String> c = parameter.values();
+    return c.toArray(String[]::new);
+  }
+
+  private String getSkriptDir(HttpExchange exchange) {
+    HttpContext context = exchange.getHttpContext();
+    Object o = context.getAttributes().get(Server.SKRIPT_DIR);
+    if (o instanceof String) {
+      return (String) o;
+    } else {
+      // kein Skript-Dir
+      return "";
+    }
+  }
+}
diff --git a/src/de/uhilger/calypso/neu/http/HttpApi.java b/src/de/uhilger/calypso/neu/http/HttpApi.java
new file mode 100644
index 0000000..ed87d17
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/http/HttpApi.java
@@ -0,0 +1,97 @@
+package de.uhilger.calypso.neu.http;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Die Klasse HttpApi verwendet die von der Klasse HttpExchange 
+ * gelieferten Elemente einer HTTP-Anfrage und leitet sie an 
+ * die abstrakte Methode process, wo Subklassen das jeweilige 
+ * Kommando aus der HTTP-Anfrage ausfuehren können.
+ * 
+ * @author Ulrich Hilger
+ */
+public abstract class HttpApi implements HttpHandler {
+
+  public static final String AMP = "&";
+  public static final String SLASH = "/";
+
+  @Override
+  public void handle(HttpExchange exchange) throws IOException {
+    String path = exchange.getRequestURI().getPath();
+    String[] elems = path.split(SLASH);
+    Map params = getQueryMap(exchange);
+    String antwort = process(elems, params, exchange);
+    antwortSenden(exchange, params, path, antwort);
+  }
+  
+  /**
+   * Eine HTTP-Anfrage ausführen
+   * 
+   * @param elems die Elemente des URI-Pfads
+   * @param parameter die Parameter des Query-Teils der URI
+   * @return die Antwort, die gesendet werden soll
+   */
+  protected abstract String process(String[] elems, Map parameter, HttpExchange exchange);
+
+  /*
+    Den Query-Teil einer URL in die Parameter zerlegen
+  
+    Die Zerlegung erfolgt mit String.split nach 
+    &amp; und dann nach =
+  */
+  protected Map getQueryMap(HttpExchange t) {
+    HashMap map = new HashMap();
+    String query = t.getRequestURI().getQuery();
+    if(query != null && query.length() > 0) {
+      String qParts[] = query.split("&");
+      for(String qPart : qParts) {
+        Logger logger = Logger.getLogger(de.uhilger.calypso.neu.http.HttpApi.class.getName());
+        logger.log(Level.FINER, "qPart: {0}", qPart);
+        String pParts[] = qPart.split("=");
+        map.put(pParts[0], pParts[1]);
+        logger.log(Level.FINER, "pParts[0]: {0} pParts[1]: {1}", new Object[]{pParts[0], pParts[1]});
+      }
+    }
+    return map;
+  }
+  
+  protected void antwortSenden(HttpExchange exchange, Map params, String cmd, String antwort) throws IOException {
+    String httpResponseStr = getResponseString(params, cmd, antwort);
+    sendResponse(exchange, httpResponseStr);      
+  }
+  
+  protected String getResponseString(Map map, String cmd, String antwort) {
+    Set keys = map.keySet();
+    StringBuilder buf = new StringBuilder();
+    buf.append(cmd);
+    buf.append(System.lineSeparator());
+    keys.forEach((Object key) -> {
+      buf.append("key: ");
+      buf.append(key);
+      buf.append(System.lineSeparator());
+      buf.append("value: "); 
+      buf.append(map.get(key));
+      buf.append(System.lineSeparator());
+      //logger.log(Level.FINE, "key {0} value {1}", new Object[]{key, map.get(key)});
+    });
+    buf.append(antwort);
+    return buf.toString();
+  }    
+
+  protected void sendResponse(HttpExchange t, String response) throws IOException {
+    t.sendResponseHeaders(200, response.length());
+    OutputStream os = t.getResponseBody();
+    os.write(response.getBytes());
+    os.close();    
+  }
+  
+  
+}
diff --git a/src/de/uhilger/calypso/neu/http/Server.java b/src/de/uhilger/calypso/neu/http/Server.java
new file mode 100644
index 0000000..168d3c9
--- /dev/null
+++ b/src/de/uhilger/calypso/neu/http/Server.java
@@ -0,0 +1,69 @@
+/*
+    Calypso - Media Player Remote Control via HTTP for Raspberry Pi
+    Copyright (C) 2021-2023  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 <https://www.gnu.org/licenses/>.
+*/
+
+package de.uhilger.calypso.neu.http;
+
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpServer;
+import de.uhilger.calypso.neu.AppProperties;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Ulrich Hilger
+ */
+public class Server {
+  
+  //private static final Logger logger = Logger.getLogger(de.uhilger.calypso.Server.class.getName());
+  
+  public static final String CONF = "conf";
+  public static final String PORT = "port";
+  public static final String SKRIPTE = "skripte";
+  public static final String CTX = "ctx";
+  public static final String EQUAL = "=";
+  public static final String BLANK = " ";
+  public static final String SKRIPT_DIR = "skript-dir";
+  
+
+  public void start(AppProperties einst) {
+    Logger logger = Logger.getLogger(de.uhilger.calypso.neu.http.Server.class.getName());
+    logger.log(Level.INFO, "Server startet auf Port {0}", einst.getString(PORT));
+    String skripte = einst.getString(SKRIPTE);
+    File skript = new File(skripte, "pause");
+    if(skript.exists()) {
+      logger.log(Level.INFO, "Skripte gefunden in {0}", skript.getParentFile().getAbsolutePath());
+    } else {
+      logger.log(Level.INFO, "Skripte nicht gefunden, Ordner laut Einstellungen: {0}", skripte);
+    }
+    try {
+      HttpServer server = HttpServer.create(new InetSocketAddress(einst.getInt(PORT)), 0);
+      String ctx = einst.getString(CTX);
+      HttpContext context = server.createContext(ctx, new ApiHandler());
+      context.getAttributes().put(SKRIPT_DIR, einst.getString(SKRIPTE));
+      server.setExecutor(Executors.newFixedThreadPool(20));
+      server.start();
+    } catch (IOException ex) {
+      logger.log(Level.SEVERE, null, ex);
+    }    
+  }
+}
diff --git a/src/logging.properties b/src/logging.properties
deleted file mode 100644
index aa7cc61..0000000
--- a/src/logging.properties
+++ /dev/null
@@ -1,72 +0,0 @@
-############################################################
-#      Default Logging Configuration File
-#
-# You can use a different file by specifying a filename
-# with the java.util.logging.config.file system property.  
-# For example java -Djava.util.logging.config.file=myfile
-############################################################
-
-############################################################
-#  	Global properties
-############################################################
-
-# "handlers" specifies a comma separated list of log Handler 
-# classes.  These handlers will be installed during VM startup.
-# Note that these classes must be on the system classpath.
-# By default we only configure a ConsoleHandler, which will only
-# show messages at the INFO and above levels.
-# handlers= java.util.logging.ConsoleHandler
-
-# To also add the FileHandler, use the following line instead.
-# handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
-
-# Default global logging level.
-# This specifies which kinds of events are logged across
-# all loggers.  For any given facility this global level
-# can be overriden by a facility specific level
-# Note that the ConsoleHandler also has a separate level
-# setting to limit messages printed to the console.
-# .level= FINE
-.level = OFF
-
-############################################################
-# Handler specific properties.
-# Describes specific configuration info for Handlers.
-############################################################
-
-# default file output is in user's home directory.
-java.util.logging.FileHandler.pattern = %h/java%u.log
-# java.util.logging.FileHandler.pattern = /media/extmirror/tomcat747/logs/tv_%u.log
-# java.util.logging.FileHandler.pattern = ${catalina.base}/logs/file-cms_%u.log
-# java.util.logging.FileHandler.limit = 50000
-# java.util.logging.FileHandler.count = 1
-# java.util.logging.FileHandler.count = 2
-# java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
-java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
-# java.util.logging.FileHandler.level = FINER
-
-# Limit the message that are printed on the console to INFO and above.
-# java.util.logging.ConsoleHandler.level = INFO
-# java.util.logging.ConsoleHandler.level = FINER
-# java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
-
-# Example to customize the SimpleFormatter output format 
-# to print one-line log message like this:
-#     <level>: <log message> [<date/time>]
-#
-# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
-
-############################################################
-# Facility specific properties.
-# Provides extra control for each logger.
-############################################################
-
-# For example, set the com.xyz.foo logger to only log SEVERE
-# messages:
-# com.xyz.foo.level = SEVERE
-# de.uhilger.filecms.handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
-# de.uhilger.filecms.level = FINEST
-# de.uhilger.wbx.handlers = java.util.logging.ConsoleHandler
-# de.uhilger.wbx.level = FINEST
-de.uhilger.avdirektor.handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
-de.uhilger.avdirektor.level = FINEST
\ No newline at end of file

--
Gitblit v1.9.3