/*
* MediathekView
* Copyright (C) 2008 W. Xaver
* W.Xaver[at]googlemail.com
* http://zdfmediathk.sourceforge.net/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package mediathek.controller.starter;
import com.apple.eawt.Application;
import com.jidesoft.utils.SystemInfo;
import mSearch.daten.DatenFilm;
import mSearch.tool.Datum;
import mSearch.tool.Listener;
import mSearch.tool.Log;
import mSearch.tool.SysMsg;
import mediathek.config.Daten;
import mediathek.config.Konstanten;
import mediathek.config.MVConfig;
import mediathek.daten.DatenDownload;
import mediathek.daten.DatenPset;
import mediathek.mac.SpotlightCommentWriter;
import mediathek.tool.MVFilmSize;
import mediathek.tool.MVNotification;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public class StarterClass {
//Tags Filme
private final Daten daten;
private Starten starten = null;
private boolean pause = false;
//===================================
// Public
//===================================
public StarterClass(Daten daten) {
this.daten = daten;
starten = new Starten();
starten.start();
}
public synchronized void urlMitProgrammStarten(DatenPset pSet, DatenFilm ersterFilm, String aufloesung) {
// url mit dem Programm mit der Nr. starten (Button oder TabDownload "rechte Maustaste")
// Quelle "Button" ist immer ein vom User gestarteter Film, also Quelle_Button!!!!!!!!!!!
String url = ersterFilm.arr[DatenFilm.FILM_URL];
if (!url.isEmpty()) {
DatenDownload d = new DatenDownload(pSet, ersterFilm, DatenDownload.QUELLE_BUTTON, null, "", "", aufloesung);
d.start = new Start();
starten.startStarten(d);
// gestartete Filme (originalURL des Films) auch in die History eintragen
daten.history.zeileSchreiben(ersterFilm.arr[DatenFilm.FILM_THEMA], ersterFilm.arr[DatenFilm.FILM_TITEL], d.arr[DatenDownload.DOWNLOAD_HISTORY_URL]);
daten.getListeFilmeHistory().add(ersterFilm);
// und jetzt noch in die Downloadliste damit die Farbe im Tab Filme passt
daten.getListeDownloadsButton().addMitNummer(d);
}
}
public void pause() {
pause = true;
}
static boolean pruefen(Daten daten, DatenDownload datenDownload, Start start) {
//prüfen ob der Download geklappt hat und die Datei existiert und eine min. Größe hat
boolean ret = false;
if (start != null) {
if (start.percent > -1 && start.percent < 995) {
// Prozent werden berechnet und es wurde vor 99,5% abgebrochen
Log.errorLog(696510258, "Download fehlgeschlagen: 99,5% wurden nicht erreicht"
+ datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
return false;
}
}
File file = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
if (!file.exists()) {
Log.errorLog(550236231, "Download fehlgeschlagen: Datei existiert nicht" + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
} else if (file.length() < Konstanten.MIN_DATEI_GROESSE_FILM) {
Log.errorLog(795632500, "Download fehlgeschlagen: Datei zu klein" + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
} else {
if (datenDownload.istAbo()) {
daten.erledigteAbos.zeileSchreiben(datenDownload.arr[DatenDownload.DOWNLOAD_THEMA],
datenDownload.arr[DatenDownload.DOWNLOAD_TITEL],
datenDownload.arr[DatenDownload.DOWNLOAD_HISTORY_URL]);
}
ret = true;
}
return ret;
}
/**
* Delete the file if filesize is less that a constant value.
*
* @param file The file which is to be deleted.
*/
static void deleteIfEmpty(File file) {
try {
if (file.exists()) {
// zum Wiederstarten/Aufräumen die leer/zu kleine Datei löschen, alles auf Anfang
if (file.length() == 0) {
// zum Wiederstarten/Aufräumen die leer/zu kleine Datei löschen, alles auf Anfang
SysMsg.sysMsg(new String[]{"Restart/Aufräumen: leere Datei löschen", file.getAbsolutePath()});
if (!file.delete()) {
throw new Exception();
}
} else if (file.length() < Konstanten.MIN_DATEI_GROESSE_FILM) {
SysMsg.sysMsg(new String[]{"Restart/Aufräumen: Zu kleine Datei löschen", file.getAbsolutePath()});
if (!file.delete()) {
throw new Exception();
}
}
}
} catch (Exception ex) {
Log.errorLog(795632500, "Fehler beim löschen" + file.getAbsolutePath());
}
}
static void startmeldung(DatenDownload datenDownload, Start start) {
ArrayList<String> text = new ArrayList<>();
boolean abspielen = datenDownload.quelle == DatenDownload.QUELLE_BUTTON;
if (abspielen) {
text.add("Film abspielen");
} else {
if (start.startcounter > 1) {
text.add("Download starten - Restart (Summe Starts: " + start.startcounter + ')');
} else {
text.add("Download starten");
}
text.add("Programmset: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMMSET]);
text.add("Ziel: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
}
text.add("URL: " + datenDownload.arr[DatenDownload.DOWNLOAD_URL]);
text.add("Startzeit: " + new SimpleDateFormat("HH:mm:ss").format(start.startZeit));
if (datenDownload.art == DatenDownload.ART_DOWNLOAD) {
text.add(DatenDownload.ART_DOWNLOAD_TXT);
} else {
text.add("Programmaufruf: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF]);
text.add("Programmaufruf[]: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF_ARRAY]);
}
SysMsg.sysMsg(text.toArray(new String[text.size()]));
}
private void reStartmeldung(DatenDownload datenDownload) {
ArrayList<String> text = new ArrayList<>();
text.add("Fehlerhaften Download neu starten - Restart (Summe Starts: " + datenDownload.start.countRestarted + ')');
text.add("Ziel: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
text.add("URL: " + datenDownload.arr[DatenDownload.DOWNLOAD_URL]);
SysMsg.sysMsg(text.toArray(new String[text.size()]));
}
private static void fertigmeldung(final DatenDownload datenDownload, final Start start, boolean abgebrochen) {
if (Boolean.parseBoolean(MVConfig.get(MVConfig.Configs.SYSTEM_DOWNLOAD_BEEP))) {
try {
Toolkit.getDefaultToolkit().beep();
} catch (Exception ignored) {
}
}
ArrayList<String> text = new ArrayList<>();
if (abgebrochen) {
text.add("Download wurde abgebrochen");
} else if (datenDownload.quelle == DatenDownload.QUELLE_BUTTON) {
text.add("Film fertig");
} else {
if (start.stoppen) {
text.add("Download abgebrochen");
} else if (start.status == Start.STATUS_FERTIG) {
// dann ists gut
text.add("Download ist fertig und hat geklappt");
} else if (start.status == Start.STATUS_ERR) {
text.add("Download ist fertig und war fehlerhaft");
}
if (datenDownload.isDownloadManager()) {
text.add("Programm ist ein Downloadmanager");
}
text.add("Programmset: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMMSET]);
text.add("Ziel: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
}
text.add("Startzeit: " + new SimpleDateFormat("HH:mm:ss").format(start.startZeit));
text.add("Endzeit: " + new SimpleDateFormat("HH:mm:ss").format(new Datum().getTime()));
text.add("Restarts: " + start.countRestarted);
text.add("Dauer: " + start.startZeit.diffInSekunden() + " s");
long dauer = start.startZeit.diffInMinuten();
if (dauer == 0) {
text.add("Dauer: <1 Min.");
} else {
text.add("Dauer: " + start.startZeit.diffInMinuten() + " Min");
}
if (datenDownload.art == DatenDownload.ART_DOWNLOAD) {
if (start.mVInputStream != null) {
text.add("Bytes gelesen: " + MVFilmSize.humanReadableByteCount(start.mVInputStream.getSumByte(), true));
text.add("Bandbreite: " + DatenDownload.getTextBandbreite(start.mVInputStream.getSumBandwidth()));
}
}
text.add("URL: " + datenDownload.arr[DatenDownload.DOWNLOAD_URL]);
if (datenDownload.art == DatenDownload.ART_DOWNLOAD) {
text.add(DatenDownload.ART_DOWNLOAD_TXT);
} else {
text.add("Programmaufruf: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF]);
text.add("Programmaufruf[]: " + datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF_ARRAY]);
}
SysMsg.sysMsg(text.toArray(new String[text.size()]));
if (!start.stoppen && !abgebrochen) {
if (datenDownload.quelle != DatenDownload.QUELLE_BUTTON) {
SwingUtilities.invokeLater(() -> MVNotification.addNotification(datenDownload, start.status != Start.STATUS_ERR));
}
}
}
static void finalizeDownload(DatenDownload datenDownload, Start start /* wegen "datenDownload.start=null" beim stoppen */, DirectHttpDownload.HttpDownloadState state) {
deleteIfEmpty(new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]));
setFileSize(datenDownload);
if (SystemInfo.isMacOSX() && state != DirectHttpDownload.HttpDownloadState.CANCEL) {
//we don´t write comments if download was cancelled...
if (Boolean.parseBoolean(datenDownload.arr[DatenDownload.DOWNLOAD_SPOTLIGHT])) {
final SpotlightCommentWriter writer = new SpotlightCommentWriter();
writer.writeComment(datenDownload);
}
}
fertigmeldung(datenDownload, start, state == DirectHttpDownload.HttpDownloadState.CANCEL);
switch (state) {
case CANCEL:
datenDownload.resetDownload();
break;
default:
start.restSekunden = -1;
start.percent = Start.PROGRESS_FERTIG;
datenDownload.mVFilmSize.setAktSize(-1);
break;
}
notifyStartEvent(datenDownload);
if (SystemInfo.isMacOSX() && Daten.getInstance().getMediathekGui() != null) {
Application.getApplication().requestUserAttention(false);
}
}
/**
* tatsächliche Dateigröße eintragen
*
* @param datenDownload {@link DatenDownload} with the info of the file
*/
static void setFileSize(DatenDownload datenDownload) {
try {
final File testFile = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
if (testFile.exists()) {
final long length = testFile.length();
if (length > 0) {
datenDownload.mVFilmSize.setSize(length);
}
}
} catch (Exception ex) {
Log.errorLog(461204780, "Fehler beim Ermitteln der Dateigröße: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]);
}
}
static void notifyStartEvent(DatenDownload datenDownload) {
Listener.notify(Listener.EREIGNIS_START_EVENT, StarterClass.class.getSimpleName());
if (datenDownload != null) {
if (datenDownload.quelle == DatenDownload.QUELLE_BUTTON) {
Listener.notify(Listener.EREIGNIS_START_EVENT_BUTTON, StarterClass.class.getSimpleName());
}
}
}
// ********************************************
// Hier wird dann gestartet
// Ewige Schleife die die Downloads startet
// ********************************************
private class Starten extends Thread {
private DatenDownload datenDownload;
/**
* The only {@link java.util.Timer} used for all {@link mediathek.controller.MVInputStream.BandwidthCalculationTask}
* calculation tasks.
*/
private java.util.Timer bandwidthCalculationTimer;
public Starten() {
super();
setName("DownloadStarter Daemon Thread");
setDaemon(true);
bandwidthCalculationTimer = new java.util.Timer("BandwidthCalculationTimer");
}
@Override
public synchronized void run() {
while (!isInterrupted()) {
try {
while ((datenDownload = getNextStart()) != null) {
startStarten(datenDownload);
//alle 5 Sekunden einen Download starten
sleep(5 * 1000);
}
daten.getListeDownloadsButton().buttonStartsPutzen(); // Button Starts aus der Liste löschen
sleep(3 * 1000);
} catch (Exception ex) {
Log.errorLog(613822015, ex);
}
}
}
private synchronized DatenDownload getNextStart() throws InterruptedException {
// get: erstes passendes Element der Liste zurückgeben oder null
// und versuchen dass bei mehreren laufenden Downloads ein anderer Sender gesucht wird
if (pause) {
// beim Löschen der Downloads, kann das Starten etwas "pausiert" werden
// damit ein zu Löschender Download nicht noch schnell gestartet wird
sleep(5 * 1000);
pause = false;
}
DatenDownload download = daten.getListeDownloads().getNextStart();
if (download == null) {
// dann versuchen einen Fehlerhaften nochmal zu starten
download = daten.getListeDownloads().getRestartDownload();
if (download != null) {
reStartmeldung(download);
}
}
return download;
}
/**
* This will start the download process.
*
* @param datenDownload The {@link mediathek.daten.DatenDownload} info object for download.
*/
private void startStarten(DatenDownload datenDownload) {
datenDownload.start.startZeit = new Datum();
Listener.notify(Listener.EREIGNIS_ART_DOWNLOAD_PROZENT, StarterClass.class.getName());
Thread downloadThread;
switch (datenDownload.art) {
case DatenDownload.ART_PROGRAMM:
downloadThread = new ExternalProgramDownload(daten, datenDownload);
downloadThread.start();
break;
case DatenDownload.ART_DOWNLOAD:
downloadThread = new DirectHttpDownload(daten, datenDownload, bandwidthCalculationTimer);
downloadThread.start();
break;
default:
Log.errorLog(789356001, "StarterClass.Starten - Switch-default");
break;
}
}
}
}