/*
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);
};
}