/* Aufzeichnungsplaner Copyright (C) 2020 Ulrich Hilger, https://uhilger.de 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 . */ function App() { var self = this; var wochentag; var mone; var channels; var outPath; var senderliste; /** * Den Aufnahmeplaner initialisieren */ this.init = function () { self.wochentag = ['Sonntag','Montag','Dienstag','Mittwoch', 'Donnerstag','Freitag','Samstag' ]; // Monatskuerzel in englisch fuer den 'at'-Befehl self.mone = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']; self.senderliste = new Array(); /* * die folgenden Konstanten koennten auch ueber eine Konfigurationsdatei * oder eine API vom Server bereitgestellt werden */ self.channels = "/media/extssd/mc/channels.conf"; self.outPath = "/opt/tv/"; self.channelsLesen(); // Bedienelemente an Programmlogik binden var elem = self.elementAnbinden("startdatum"); elem.valueAsDate = new Date(); self.elementAnbinden("bez"); self.elementAnbinden("startzeit"); self.elementAnbinden("dauer"); self.elementAnbinden("sender"); /* * initial die Einstellungen einsammeln und * an der Bedienoberflaeche zeigen */ //self.collectSettings(); }; /** * Ein Element aus dem Document Object Model (DOM) an das Eingabe-Ereignis * (oninput) binden um auf diese Weise dessen geaenderten Inhalt in die * Ausgabe des Infotextes zu uebernehmen * * @param {type} ename name des anzubindenden Elements * @returns {elem|Element} das angebundene Element */ this.elementAnbinden = function(ename) { elem = document.getElementById(ename); elem.oninput = self.collectSettings; return elem; }; /* * collectSettings nimmt die aktuellen Einstellungen aus den Eingabeelementen * und bildet eine Textausgabe aller aktuell eingegebenen Parameter * sowie das Kommando fuer gnutv und gibt diese in den Elementen * 'info' und 'cmd' aus. */ this.collectSettings = function() { // das Startdatum bestimmen und in den Infotext uebernehmen var start = self.getStart(); var infotext = "
Start: " + self.wochentag[start.getDay()] + ", " + self.datumZuDatumText(start) + ", " + self.zeitZuText(start, ":") + " Uhr"; // den Endezeitpunkt bestimmen und in den Infotext uebernehmen var ende = self.getEnde(); var endzeit = self.wochentag[ende.getDay()] + ", " + self.datumZuDatumText(ende) + ", " + self.zeitZuText(ende, ":"); infotext = infotext + "
Ende: " + endzeit + " Uhr"; // die Dauer in Sekunden sowie in Minuten bestimmen und dem Infotext anfuegen var dauerSekunden = document.getElementById("dauer").value; infotext = infotext + "
Dauer: " + dauerSekunden / 60 + " Minuten" + " (" + dauerSekunden + " Sekunden)"; /* * Die eingegebene Bezeichnung fuer die Aufnahme bestimmen und um * Startdatum, -zeit und Sender ergaenzen und das Ganze in den Infotext * uebernehmen * Es wird '.ts' fuer 'transport stream' angefuegt, wenn keine * Dateierweiterung in der Bezeichnung angegeben ist. Bei DVB wird der * Inhalt ueblicherweise als 'transport stream' bezeichnet. */ var bez = document.getElementById("bez").value; var dotpos = bez.indexOf("."); var fname = self.outPath; var senderElem = document.getElementById("sender"); var sender = senderElem.options[senderElem.selectedIndex].text; var streamData = self.senderliste[senderElem.selectedIndex]; var streamElems = streamData.split("|"); var streamFreq = streamElems[1]; if(dotpos > -1) { fname = fname + bez.substring(0, dotpos) + "-" + self.fts(start) + "-" + sender + bez.substring(dotpos); } else { fname = fname + bez + "-" + self.fts(start) + "-" + sender + ".mp4"; } infotext = infotext + "
" + fname; // den Infotext im DOM-Element 'info' anzeigen document.getElementById("info").innerHTML = infotext; /* * im DOM-Element 'cmd' wird der Befehl zusammengstellt und angezeigt * wie er fuer die Programmierung einer Aufzeichnung mit Hilfe von * gnutv und at benoetigt wird. * * Beispiel: * echo "gnutv -channels /media/extssd/mc/channels.conf * -out file /home/fred/work/test-2020-02-01-1050-arteHD.ts * -timeout 300 arteHD" | at 1050 feb 01 * * echo "ffmpeg -i https://artesimulcast.akamaized.net/hls/live/2030993/artelive_de/index.m3u8 * -t 10800 -acodec copy -vcodec copy * /home/ulli/tv/triangle-of-sadness-2024-11-17-2005-arte-HD.mp4" | at 2005 nov 17 * * */ /*document.getElementById("cmd").innerHTML = 'echo "gnutv -channels ' + self.channels + ' -out file ' + fname + ' -timeout ' + dauerSekunden + ' ' + sender + '" | at ' + self.zeitZuText(start) + ' ' + self.mone[start.getMonth()] + ' ' + start.getDate();*/ document.getElementById("cmd").innerHTML = 'echo "ffmpeg -i ' + streamFreq + ' -t ' + dauerSekunden + ' -acodec copy -vcodec copy ' + fname + '" | at ' + self.zeitZuText(start) + ' ' + self.mone[start.getMonth()] + ' ' + start.getDate(); /* + ' -out file ' + fname + ' -timeout ' + dauerSekunden + ' ' + sender + '" | at ' + self.zeitZuText(start) + ' ' + self.mone[start.getMonth()] + ' ' + start.getDate(); */ }; /* * getEnde fuegt dem Startzeitpunkt aus getStart() die Dauer hinzu * und bildet so den Endzeitpunkt, der als Datumsobjekt zurueckgegeben wird */ this.getEnde = function() { var endeZeitpunkt = self.getStart(); endeZeitpunkt.setMilliseconds(endeZeitpunkt.getMilliseconds() + (document.getElementById("dauer").value * 1000)); return endeZeitpunkt; }; /* * getStart setzt aus dem Datumseingabefeld und dem Schieberegler fuer die * Startzeit den Startzeitpunkt zusammen und gibt diesen als Datumsobjekt * zurueck * * Wenn das Datumseingabefeld kein Datum enthaelt, wird das heutige Datum * mit der Zeit des Schiebereglers kombiniert. */ this.getStart = function() { var startdatum = document.getElementById("startdatum").valueAsDate; startdatum.setHours(0); startdatum.setMilliseconds(startdatum.getMilliseconds() + (document.getElementById("startzeit").value * 1000)); return startdatum; }; /* * Die Sender aus der Datei channels.conf lesen und in eine * HTML-Auswahlliste ueberfuehren */ this.channelsLesen = function() { var url = 'channels.conf'; self.http_get(url, function (antwort) { var zeilen = antwort.split("\n"); zeilen.sort(); self.senderliste = zeilen; var senderAuswahl = document.getElementById("sender"); var sender; var zElems; for(var i = 0; i < zeilen.length; i++) { zElems = zeilen[i].split("|"); sender = document.createElement("option"); sender.textContent = zElems[0]; sender.value = zElems[1]; senderAuswahl.appendChild(sender); } }); }; /** * Die Funktion http_get ruft einen Inhalt ueber HTTP GET ab * * @param {type} url der aufzurufende URL * @param {type} process die Funktion, der die Antwort uebergeben * werden soll */ this.http_get = function (url, process) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { process(this.responseText); } }; xmlhttp.open("GET", url, true); xmlhttp.send(); }; /* ----------------------------------------------------------------------- * Nachfolgend einige Hilfsfunktionen zur Umwandlung von Datum-Objekten * zu Text. * * Solche Funktionen gibt es auch fertig in Bibliotheken wie * z.B. Moment.js. Hier werden allerdings nur wenige solche * Funktionen benoetigt so dass sich die zusaetzliche * Abhaengigkeit nicht lohnt, die mit der Verwendung der Bibliothek * entstuende. * ---------------------------------------------------------------------- */ /* * Aus einem Datums-Objekt einen Text im Format JJJJ-MM-TT machen */ this.datumZuText = function(datum) { var tag = self.textZweistellig(datum.getDate()); var monat = self.textZweistellig(datum.getMonth() + 1); var jahr = datum.getFullYear(); return jahr + "-" + monat + "-" + tag; }; /* * Aus einem Datums-Objekt einen Text im Format TT.MM.JJJJ machen */ this.datumZuDatumText = function(datum) { var tag = self.textZweistellig(datum.getDate()); var monat = self.textZweistellig(datum.getMonth() + 1); var jahr = datum.getFullYear(); return tag + "." + monat + "." + jahr; }; /* * Aus einem Datums-Objekt einen Text im Format SS:MM machen * * Das Trennzeichen, z.B. ":" kann im Parameter trennzeichen * uebergeben werden. trennzeichen darf auch leer bleiben. */ this.zeitZuText = function(datum, trennzeichen) { var std = self.textZweistellig(datum.getHours()); var min = self.textZweistellig(datum.getMinutes()); if(trennzeichen) { return std + trennzeichen + min; } else { return std + "" + min; } }; /* * Aus einer Zahl einen Text machen und dabei einstellige * Werte mit einer Null auffuellen */ this.textZweistellig = function(zahl) { if(zahl < 10) { return "0" + zahl; } else { return zahl; } }; /** * Aus einem Datum den Textausdruck JJJJ-MM-TT-hhmm machen * (fts: file name timestamp) * * @param {type} datum das Datumsobjekt aus dem der Text gemacht werden soll * @returns {String} der Text im Format JJJJ-MM-TT-hhmm */ this.fts = function(datum) { return self.datumZuText(datum) + "-" + self.zeitZuText(datum); }; }