diff --git a/.gitignore b/.gitignore
index 7fe0b0260..08aca6a64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,4 @@ src/rcsim.h
src/rcsim
src/gui/version.h
src/nhttpd/nhttpd.conf
+src/mdev_helper
diff --git a/configure.ac b/configure.ac
index b0a58dcd8..04832071d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,7 @@ TUXBOX_APPS_LIB_PKGCONFIG(PNG,libpng)
TUXBOX_APPS_LIB_PKGCONFIG(AVFORMAT,libavformat)
TUXBOX_APPS_LIB_PKGCONFIG(AVCODEC,libavcodec)
TUXBOX_APPS_LIB_PKGCONFIG(AVUTIL,libavutil)
+TUXBOX_APPS_LIB_PKGCONFIG(BLURAY,libbluray)
# either use dynamic lualib in package lua (openSUSE)
# ... or in package lua5.2 (debian-derivates)
@@ -253,6 +254,7 @@ AC_SUBST(STB_HAL_INC)
AC_SUBST(STB_HAL_LIB)
AC_SUBST(LUA_CFLAGS)
AC_SUBST(LUA_LIBS)
+AC_SUBST(BLURAY_LIBS)
AC_OUTPUT([
Makefile
diff --git a/data/Makefile.am b/data/Makefile.am
index 520c059e1..5f4751b23 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -5,9 +5,7 @@ SUBDIRS += lcd
endif
configdir = $(CONFIGDIR)
-config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml settingsupdate.conf
-
-config_DATA += terrestrial.xml
+config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml settingsupdate.conf terrestrial.xml
install-data-hook:
$(INSTALL) -d $(DESTDIR)/$(CONFIGDIR)/zapit
diff --git a/data/cables.xml b/data/cables.xml
index 610fa2fc8..3220eb5f9 100644
--- a/data/cables.xml
+++ b/data/cables.xml
@@ -247,17 +247,13 @@
-
-
-
-
-
+
diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
index 71ee57bb2..28076ef7d 100644
--- a/data/icons/Makefile.am
+++ b/data/icons/Makefile.am
@@ -57,6 +57,7 @@ install_DATA += \
ca.png \
ca2.png \
ca2_gray.png \
+ checkmark.png \
colors.png \
conax_green.png \
conax_white.png \
@@ -74,6 +75,7 @@ install_DATA += \
dummy.png \
dummy_small.png \
error.png \
+ epg.png \
features.png \
file.png \
folder.png \
diff --git a/data/icons/checkmark.png b/data/icons/checkmark.png
new file mode 100755
index 000000000..59495a665
Binary files /dev/null and b/data/icons/checkmark.png differ
diff --git a/data/icons/epg.png b/data/icons/epg.png
new file mode 100644
index 000000000..0dea572be
Binary files /dev/null and b/data/icons/epg.png differ
diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale
index cd0c60592..e43d94c1f 100644
--- a/data/locale/deutsch.locale
+++ b/data/locale/deutsch.locale
@@ -240,6 +240,7 @@ channellist.nonefound Es wurden keine Kanäle gefunden!\nFühren Sie bitte eine
channellist.numeric_adjust Numeric zap adjust
channellist.provs Anbieter
channellist.recording_not_possible Aufnahme nicht möglich!
+channellist.remember Zuletzt verwendete
channellist.reset_all Entferne Markierung "Neu" für alle Kanäle
channellist.reset_flags Entferne Kanal-Markierung "Neu"
channellist.sats Satelliten
@@ -316,6 +317,11 @@ date.Sun So
date.Thu Do
date.Tue Di
date.Wed Mi
+debug Debug Ausgabe
+debug.level Stufe
+debug.level_1 normal
+debug.level_2 informativ
+debug.level_3 ausführlich
epg.saving Speichere EPG
epgextended.actors Darsteller
epgextended.director Regie
@@ -390,7 +396,7 @@ extra.key_pic_size 4:3 Anzeigeverhalten
extra.key_pip_close Stop/Start PiP
extra.key_pip_setup PiP Konfiguration
extra.key_pip_swap Umschalten PiP/live
-extra.key_plugin One-touch-Plugin
+extra.key_plugin Schnellstart-Plugin
extra.key_screenshot Screenshot Taste
extra.key_timeshift Timeshift
extra.key_unlock Entsperrtaste
@@ -402,7 +408,8 @@ extra.lodirection Längengrad-Ausrichtung
extra.longitude Längengrad
extra.menu_left_exit "links" = Menü zurück
extra.north Norden
-extra.record_time Maximale Aufnahmezeit
+extra.record_time Maximale Aufnahmedauer
+extra.record_time_ts Maximale Timeshiftdauer
extra.rotor_swap Rotor dreht Ost/West
extra.rounded_corners Eckendarstellung
extra.rounded_corners_off eckig
@@ -617,18 +624,21 @@ hdd_check_format_bad Überprüfung von Datenträgern mit Format %s wird nicht un
hdd_extended_settings Erweiterte Festplatteneinstellungen
hdd_fast Schnell
hdd_format Formatiere Festplatte
-hdd_format_failed Formatierung fehlgeschlagen
-hdd_format_warn Formatierung wird gestartet
+hdd_format_failed Formatierung fehlgeschlagen! Stellen Sie sicher, dass der Datenträger nicht in Verwendung ist und versuchen Sie es erneut.
+hdd_format_warn Alle Daten auf dem Datenträger werden gelöscht! Formatierung starten?
hdd_fs Dateisystem zum formatieren
hdd_fs_unknown unbekannt
hdd_manage Laufwerke verwalten
hdd_middle Mittel
+hdd_mount Mount
+hdd_mount_umount Mount/Unmount
hdd_noise Akustikkontrolle (AAM)
hdd_not_found Keine Festplatte
hdd_removable_device Wechseldatenträger
hdd_settings Laufwerke
hdd_sleep Ausschalten nach...
hdd_slow Langsam
+hdd_umount Unmount
hdd_umount_warn Laufwerk aushängen
imageinfo.creator Ersteller:
imageinfo.date Datum:
@@ -675,6 +685,7 @@ keybindingmenu.channellist Kanalliste
keybindingmenu.channelup Kanal hoch
keybindingmenu.head Tasten-Belegungen bearbeiten
keybindingmenu.lastchannel Letzter Kanal
+keybindingmenu.longkeypress_duration Langer Tastendruck
keybindingmenu.misc Sonstige
keybindingmenu.mode_left_right_key_tv Funktion li/re Tasten im TV-Modus
keybindingmenu.mode_left_right_key_tv_infobar Infobar einblenden
@@ -738,6 +749,9 @@ ledcontroler.off LED1 & LED2 aus
ledcontroler.on.all LED1 & LED2 an
ledcontroler.on.led1 LED1 an
ledcontroler.on.led2 LED2 an
+lua.function_deprecated1 Achtung!
+lua.function_deprecated2 Die Funktion
+lua.function_deprecated3 ist veraltet,\n bitte nutzen Sie
mainmenu.audioplayer Audioplayer
mainmenu.channels Kanalliste
mainmenu.clearsectionsd Lösche EPG Cache
@@ -804,6 +818,7 @@ menu.hint_audioplayer_title Aktivieren Sie die Titelsuche (SMS-Stil) in der Play
menu.hint_auto_lang Wählen Sie, ob automatisch ihre bevorzugte Tonspur ausgewählt wird, wenn sie vorhanden ist
menu.hint_auto_subs Automatische Anzeige der Untertitel in Ihrer bevorzugten Sprache
menu.hint_back Zurück zum vorherigen Menü.\nDie Taste 'Menü' schließt alle Menüs
+menu.hint_back_brief Zurück zum vorherigen Menü.
menu.hint_backlight Konfigurieren Sie die Hintergrundbeleuchtung der Buttons
menu.hint_backup Sichern von Konfigurationen und Kanallisten
menu.hint_bedit Bearbeiten ihrer Favoriten und der Bouquets
@@ -818,6 +833,8 @@ menu.hint_channellist_epg_align Legen Sie fest, wie der Text für das EPG in der
menu.hint_channellist_extended Bei aktivierter Funktion wird vor dem Sendernamen ein Balken eingeblendet, der den Sendungsfortschritt anzeigt
menu.hint_channellist_fonts Ändern Sie die Schriftgrößen in der Kanalliste
menu.hint_channellist_foot Definiert, welche Informationen im unteren Sendungsfenster angezeigt werden sollen
+menu.hint_channellist_mode Wählen Sie die Start-Kanalliste im TV-Modus
+menu.hint_channellist_mode_radio Wählen Sie die Start-Kanalliste im Radio-Modus
menu.hint_channellist_setup Wählen Sie die Anzeigeoptionen für die Kanalliste
menu.hint_channellist_show_channellogo Zeigt Senderlogos in der Kanalliste.
menu.hint_channels Kanalliste öffnen
@@ -843,6 +860,7 @@ menu.hint_epg_old_events Veraltete EPG-Daten werden nach dieser Zeit (in Stunden
menu.hint_epg_save Speichert die EPG-Daten auf einem externen Datenträger und läd es von dort nach einen Neustart
menu.hint_epg_save_standby Speichert die EPG-Daten auch im Standby-Modus
menu.hint_epg_scan Aktivieren Sie den Hintergrundscan der EPG-Daten, wenn ein freier Tuner vorhanden ist, im aktuellen Bouquet oder in allen Favoriten
+menu.hint_epg_scan_mode Wählen Sie den Modus für den EPG Scan aus.
menu.hint_event_textcolor Ändern Sie die Farbe für farbige Events in der Kanalliste und der Infobar
menu.hint_eventlist_additional Definiert, ob zusätzliche Informationen im Hauptfenster angezeigt werden sollen
menu.hint_eventlist_fonts Ändern Sie die Schriftgröße in der Event-Liste
@@ -934,6 +952,7 @@ menu.hint_key_pic_size_active Die Taste für das 4:3 Anzeigeverhalten deaktivier
menu.hint_key_pip_close Tastenzuordnung für Stop PiP oder Start mit aktuellem Kanal
menu.hint_key_pip_setup Tastenzuordnung für PiP Konfiguration
menu.hint_key_pip_swap Tastenzuordnung zum Umschalten PiP und aktuellem Kanal
+menu.hint_key_plugin Wählen Sie eine Taste für das Schnellstart-Plugin
menu.hint_key_poweroff Wählen Sie eine Taste für den Standby und für das Verhalten für Standby und Deep-Standby
menu.hint_key_quickzap Konfigurieren Sie die Tastenbelegung für die Schnellumschaltung
menu.hint_key_repeatblock Die Verzögerung nach einem Tastendruck bis die Box reagieren soll
@@ -960,6 +979,7 @@ menu.hint_leds_record Definiert, ob die Power-LEDs blinken sollen, wenn eine Auf
menu.hint_leds_standby Definiert den Status der Power-LEDs im Standby
menu.hint_leds_tv Definiert den Status der Power-LEDs im TV-Modus
menu.hint_load Laden der Neutrino-HD-Einstellungen aus einer Datei
+menu.hint_longkeypress_duration Tasten, die länger als die angegebene Zeit betätigt werden, werden als "langer Tastendruck" behandelt.
menu.hint_lua Plugins ausführen
menu.hint_make_hdlist Bei aktiver Option wird ein Bouquet namens 'HD' erzeugt, in dem alle HD-Sender zusammengefasst sind
menu.hint_make_newlist Nach einer Kanalsuche wird ein Bouquet namens 'neue Kanäle' erzeugt
@@ -979,6 +999,7 @@ menu.hint_misc_filebrowser Dateisystem, Dateirechte anzeigen im Dateibrowser, St
menu.hint_misc_general Standby-, Teletext- und Rotor-Einstellungen, Pluginverzeichnis auf externem Datenträger
menu.hint_misc_zapit Verwaltung der Start-Kanäle für den TV/Radio-Modus
menu.hint_movie Wiedergabe von Filmen
+menu.hint_movieplayer_plugin Wählen Sie ein Plugin, das mit einer Schnellstart-Taste im Movieplayer-Modus gestartet wird
menu.hint_net_broadcast Ändern Sie die Broadcast-Adresse.\nWenn Sie unsicher sind, verwenden Sie zuletzt .255
menu.hint_net_dhcp Verwenden Sie einen DHCP-Server für die automatische Vergabe einer IP-Adresse im Netzwerk
menu.hint_net_djmount Mountet UPnP-Geräte als Dateisystem unter /media/00upnp
@@ -1014,6 +1035,9 @@ menu.hint_net_xupnpd Freigabe von Live Channels über UPNP
menu.hint_network IP-Adresse, Gateway, DNS, Zeit-Sync, Netzwerk-Freigaben, Dienste und mehr
menu.hint_new_zap_mode Aktiviert Quickzap in der Kanalliste. Nach Betätigen der Mute-Taste wird mit den Hoch/Runter-Tasten direkt umgeschalten
menu.hint_numeric_adjust Adjust channel list mode on numeric zap
+menu.hint_onekey_plugin Wählen Sie ein Plugin, das mit einer Schnellstart-Taste gestartet wird
+menu.hint_opkg Hier können Sie neue Software-Pakete installieren oder vorhandene aktualisieren
+menu.hint_opkg_upgrade Aktualisiert alle installierten Pakete auf die neueste verfügbare Version
menu.hint_osd Farben, Schriftarten, Anzeigegröße, Ansichtsoptionen der Menüs und mehr
menu.hint_osd_language Wählen Sie ihre Menü-Sprache
menu.hint_osd_preset Wählen Sie zwischen Röhren-TV (CRT) oder Flachbildschirm (LCD)
@@ -1050,10 +1074,12 @@ menu.hint_record_data_dvbsub Untertitel-Spur zu Aufnahme hinzufügen
menu.hint_record_data_vtxt Teletext-Spur zu Aufnahme hinzufügen
menu.hint_record_dir Wählen Sie das Aufnahmeverzeichnis
menu.hint_record_end Wählen Sie zwischen maximaler Aufnahmezeit oder einem Aufnahmeende anhand der EPG-Daten
+menu.hint_record_filename_template Vorlagemuster für den Dateinamen bearbeiten
menu.hint_record_slow_warn Zeige Warnung, wenn der Aufnahmepuffer zu überlaufen droht
menu.hint_record_startstop_msg Schaltet die Meldung bei Aufnahmestart/ende ein oder aus.
menu.hint_record_tdir Wählen Sie ein Verzeichnis für Ihre Timeshift-Aufnahmen im temporären Timeshift-Modus
-menu.hint_record_time Geben Sie eine maximale Aufnahmezeit in Stunden ein, wenn Sie die Aufnahme nicht vorzeitig stoppen
+menu.hint_record_time Aufzeichnungsdauer vor dem Stopp bei der Verwendung von Direktaufzeichnung mit Record-Taste.
+menu.hint_record_time_ts Timeshiftdauer vor dem Stopp, wenn temporäres Timeshift aktiviert.
menu.hint_record_timeafter Stellen Sie die Nachlaufzeit für Timer-Aufnahmen ein\nEin Wert von 2 beendet die Aufnahme 2 Minuten nach dem Sendungsende
menu.hint_record_timebefore Stellen Sie die Vorlaufzeit für Timer-Aufnahmen ein\nEin Wert von 2 startet die Aufnahme 2 Minuten vor dem Sendungsbeginn
menu.hint_record_timer Konfigurieren Sie Optionen für Timer-Aufnahmen
@@ -1085,8 +1111,10 @@ menu.hint_scan_diseqcorder Diseqc command order for cascaded switches
menu.hint_scan_diseqcrepeat DiSEqC-Wiederholungen für kaskadierte Schaltungen
menu.hint_scan_diseqctype Wählen Sie ihr DiSEqC-Protokoll\nMit 'Erweitert' können Sie ihre Anlage einbinden
menu.hint_scan_fast Schnell-Suchlauf eines ausgewählten Anbieters\nWARNUNG: DiSEqC-Einstellung wird überschrieben
+menu.hint_scan_fastdiseqc Start DiSEqC-Autokonfiguration
menu.hint_scan_fastprov Wählen Sie einen Anbieter (Provider) für den Suchlauf
menu.hint_scan_fasttype Wählen Sie das Sendeformat
+menu.hint_scan_fastupdate Aktivieren/Deaktivieren Fastscan Auto-Update
menu.hint_scan_fec Wählen Sie eine Transponder-FEC
menu.hint_scan_felink Select tuner to link tuner to
menu.hint_scan_femode Wählen Sie den Verbindungstyp für den zweiten Tuner
@@ -1106,6 +1134,7 @@ menu.hint_scan_logical_hd Wenn der Kanal in SD und in HD verfügbar ist, wird HD
menu.hint_scan_longitude Geben Sie ihren Längengrad ein
menu.hint_scan_manual Manueller Transponder-Suchlauf mit ausgewählten Parametern
menu.hint_scan_mod Wählen Sie eine Transponder-Modulation
+menu.hint_scan_motor Rotor Optionen, Satfinder
menu.hint_scan_motor_18v Benutze 18V für Motorbewegungen
menu.hint_scan_motor_speed Rotor-Bewegungsgeschwindigkeit in 1/10 Grad pro Sekunde
menu.hint_scan_motorpos Wählen Sie eine gespeicherten Positions-Nummer für diesen Satelliten,\nwird ignoriert, wenn USALS aktiv
@@ -1130,6 +1159,7 @@ menu.hint_scan_start Startet die Kanalsuche mit den angegebenen Parametern.\nMit
menu.hint_scan_test Testen Sie das Signal für diesen Transponder
menu.hint_scan_tpselect Wählen Sie einen einzelnen Transponder für den Suchlauf
menu.hint_scan_uncommited Wählen Sie nicht festgeschriebene Angaben für diesen Satelliten
+menu.hint_scan_usals USALS Optionen
menu.hint_scan_usals_repeat Geben Sie die USALS-Wiederholungen für den Rotor ein
menu.hint_scan_usalsall Verwenden Sie USALS für alle Satelliten an diesem Tuner
menu.hint_scan_useusals Verwenden Sie USALS für diesen Satelliten,\nwenn aktiv, wird Rotorposition ignoriert
@@ -1201,6 +1231,7 @@ menu.hint_video_modes Definiert, welche Videosysteme mit der VF-Taste der Fernbe
menu.hint_video_pip Bild in Bild Größe und Position
menu.hint_video_saturation Change picture saturation
menu.hint_video_scart_mode Wählen Sie den Modus des Ausgangssignals für den SCART-Anschluss
+menu.hint_video_sdosd Aktivieren/Deaktivieren der OSD Anzeige am Analogausgang (Scart, Cinch)
menu.hint_volume Wählen Sie die Anzeigeoptionen für die Lautstärke
menu.hint_volume_digits Zifferndarstellung der Lautstärkeanzeige ein- oder ausschalten
menu.hint_volume_pos Wählen Sie die Position der Lautstärkeanzeige aus
@@ -1241,8 +1272,12 @@ miscsettings.epg_old_events_hint2 Angabe in Stunden
miscsettings.epg_save EPG zwischenspeichern
miscsettings.epg_save_standby EPG speichern in Standby-Modus
miscsettings.epg_scan Hintergrundscan EPG
+miscsettings.epg_scan_always Immer
miscsettings.epg_scan_bq Aktuelles Bouquet
miscsettings.epg_scan_fav Alle Favoriten
+miscsettings.epg_scan_live Bei eingeschalteter Box
+miscsettings.epg_scan_sel Markierte Bouquets
+miscsettings.epg_scan_standby Im Standby Modus
miscsettings.general Allgemein
miscsettings.head Erweitert
miscsettings.infobar Infobar
@@ -1497,7 +1532,7 @@ mpkey.bookmark Speichere Lesezeichen
mpkey.forward Vorlauf
mpkey.pause Pause
mpkey.play Play
-mpkey.plugin Starte Plugin
+mpkey.plugin Movieplayer-Plugin
mpkey.rewind Rücklauf
mpkey.stop Stopp
mpkey.subtitle Untertitel
@@ -1564,6 +1599,19 @@ nvod.starting (Beginn in %d min)
nvodselector.directormode Bildregie-Modus
nvodselector.head Anfangszeit auswählen
nvodselector.subservice Perspektiven
+opkg.button.expert_off Standard-Modus
+opkg.button.expert_on Experten-Modus
+opkg.button.info Paket-Informationen
+opkg.button.install Paket installieren
+opkg.button.uninstall Paket entfernen
+opkg.failure.install Installation fehlgeschlagen (%d)
+opkg.failure.update Update fehlgeschlagen (%d)
+opkg.failure.upgrade Upgrade fehlgeschlagen (%d)
+opkg.messagebox.reinstall %s erneut installieren?
+opkg.messagebox.remove %s entfernen?
+opkg.success.install Installation erfolgreich, Neustart von Neutrino kann erforderlich sein.
+opkg.title Paketverwaltung
+opkg.upgrade Installierte Pakete aktualisieren
options.default Voreinstellungen benutzen
options.fb framebuffer
options.ntp_off DVB
@@ -1691,6 +1739,9 @@ recordingmenu.end_of_recording_epg EPG aktuelles Event
recordingmenu.end_of_recording_max max. Aufnahmezeit
recordingmenu.end_of_recording_name Ende der Sofortaufnahme
recordingmenu.file Direkt (Datei)
+recordingmenu.filename_template Vorlage für Dateiname
+recordingmenu.filename_template_hint Platzhalter werden durch folgende Werte ersetzt:
+recordingmenu.filename_template_hint2 %C = Kanal, %T = Titel, %I = Info, %d = Datum, %t = Zeit
recordingmenu.help Aufnahmegeräte:\n-----------------------\nServer:\nauf PC mit Hilfe eines Streaming-Programmes\n\n(analoger) Videorekorder:\nüber VCR-Ausgang\n\nDirekt (Datei):\nauf ein per NFS gemountetes Verzeichnis\noder eine interne Festplatte\nTS: SPTS-Mode Treiber laden(dbox2)\nPES: SPTS-Mode Treiber nicht laden(dbox2)\n\n\nMaximale Dateigröße:\n----------------------\nNFS V2: 2 GB (2048 MB)\nNFS V3: fast unendlich (0 MB)\nFAT: 2 GB (2048 MB)\nFAT32: 4 GB (4096 MB)
recordingmenu.multimenu.ask_stop_all Wirklich alle %d Aufnahmen beenden?
recordingmenu.multimenu.info_stop_all %d von %d Aufnahmen werden beendet.
@@ -1734,14 +1785,24 @@ satsetup.diseqcrepeat DiSEqC-Wiederholungen
satsetup.extended DiSEqC-Einstellungen
satsetup.extended_motor Motor-Einstellungen
satsetup.fastscan_all SD und HD
+satsetup.fastscan_auto_diseqc Start automatische Diseqc Konfiguration
+satsetup.fastscan_auto_diseqc_wait Automatische Diseqc Konfiguration wird durchgeführt
satsetup.fastscan_hd nur HD
-satsetup.fastscan_head Schnellscan (Astra 1, 19.2E, 12.515Mhz)
+satsetup.fastscan_head Schnellscan
satsetup.fastscan_prov Anbieter:
-satsetup.fastscan_prov_cd CanalDigitaal
-satsetup.fastscan_prov_telesat TéléSAT
-satsetup.fastscan_prov_tvv TV Vlaanderen
+satsetup.fastscan_prov_cd_hd CanalDigitaal (HD)
+satsetup.fastscan_prov_cd_sd CanalDigitaal (SD)
+satsetup.fastscan_prov_hda HD Austria
+satsetup.fastscan_prov_hello Hello
+satsetup.fastscan_prov_skylink_c Skylink Czech
+satsetup.fastscan_prov_skylink_s Skylink Slovak
+satsetup.fastscan_prov_telesat_b TéléSAT Belgium
+satsetup.fastscan_prov_telesat_l TéléSAT Luxemburg
+satsetup.fastscan_prov_tvv_hd TV Vlaanderen (HD)
+satsetup.fastscan_prov_tvv_sd TV Vlaanderen (SD)
satsetup.fastscan_sd nur SD
satsetup.fastscan_type Scantyp
+satsetup.fastscan_update Auto-Update
satsetup.fe_mode Tuner Modus
satsetup.fe_mode_independent Independent
satsetup.fe_mode_link_loop Loop
@@ -1875,9 +1936,11 @@ streaming.slow System oder Datenträger zu langsam! Bitte ggf. einige Aufnahmen
streaming.write_error Die Aufnahme wurde leider abgebrochen,\nda ein Fehler beim Schreiben der Daten auftrat.
stringinput.caps Groß-/Kleinbuchstaben
stringinput.clear Alles löschen
+subtitles.charset Zeichensatz
subtitles.head Untertitel
subtitles.stop Untertitel aus
-terrestrialsetup.provider DVB-T Region
+terrestrialsetup.area Region
+terrestrialsetup.provider DVB-T Versorgungsbereich
timer.eventrecord.msg Die Sendung wurde zur Aufnahme vorgemerkt.
timer.eventrecord.title Aufnahme vormerken
timer.eventtimed.msg Die Sendung wurde vorgemerkt.
@@ -2031,6 +2094,7 @@ videomenu.pip_error PiP Startfehler
videomenu.saturation Sättigung
videomenu.scart Scart
videomenu.screensetup Bildbereich
+videomenu.sdosd SD OSD
videomenu.sharpness Schärfe
videomenu.tv-scart TV Scart
videomenu.vcrsignal VCR-Ausgang Signalart
@@ -2057,8 +2121,10 @@ zapit.scantype.all Alle Services
zapit.scantype.radio Nur Radio
zapit.scantype.tv Nur TV
zapit.scantype.tvradio Nur TV & Radio
+zapitsetup.channelmode Start-Kanalliste für TV
+zapitsetup.channelmode_radio Start-Kanalliste für Radio
zapitsetup.head Startkanal-Verwaltung
-zapitsetup.info Start Kanal
+zapitsetup.info Startkanal
zapitsetup.last_radio Radio Kanal
zapitsetup.last_tv TV Kanal
zapitsetup.last_use Kanal beim Runterfahren speichern
diff --git a/data/locale/english.locale b/data/locale/english.locale
index 3efafb348..77695ab3b 100644
--- a/data/locale/english.locale
+++ b/data/locale/english.locale
@@ -240,6 +240,7 @@ channellist.nonefound No channels were found!\nPlease execute a scan\n(MENU-key
channellist.numeric_adjust Numeric zap adjust
channellist.provs Providers
channellist.recording_not_possible Recording not possible!
+channellist.remember Last used
channellist.reset_all Reset 'new' flag for all channels
channellist.reset_flags Reset 'new' channel flag
channellist.sats Satellites
@@ -316,6 +317,11 @@ date.Sun Sun
date.Thu Thu
date.Tue Tue
date.Wed Wed
+debug Debug Output
+debug.level Level
+debug.level_1 normal
+debug.level_2 informative
+debug.level_3 verbose
epg.saving Saving EPG
epgextended.actors Actors
epgextended.director Director
@@ -402,7 +408,8 @@ extra.lodirection LoDirection
extra.longitude Longitude
extra.menu_left_exit "Left" = menu back
extra.north North
-extra.record_time Maximal recording time
+extra.record_time Maximal recording duration
+extra.record_time_ts Maximal timeshift duration
extra.rotor_swap Swap rotor east/west
extra.rounded_corners Shape of corners
extra.rounded_corners_off angular
@@ -617,18 +624,24 @@ hdd_check_format_bad Checking of disks with format %s is not supported.
hdd_extended_settings Extended HDD-Settings
hdd_fast Fast
hdd_format Formating drive...
-hdd_format_failed Formating failed!
-hdd_format_warn Start format...
+hdd_format_failed Formating failed! Make sure device not in use, reboot and try again
+hdd_format_warn All data on device will be lost ! Continue with format ?
hdd_fs Filesystem used to format
hdd_fs_unknown unknown
hdd_manage Manage drives
hdd_middle Mid
+hdd_mount Mount
+hdd_mount_ok Device ready to use.
+hdd_mount_failed Failed to mount, check HDD settings menu.
+hdd_mount_umount Mount/Unmount
hdd_noise Acoustic-control (AAM)
hdd_not_found No HDD found
hdd_removable_device Removable device
hdd_settings Hard Disk Drive/USB
hdd_sleep Switch off after...
hdd_slow Slow
+hdd_umount Unmount
+hdd_umounted Device removed
hdd_umount_warn unmount device
imageinfo.creator Creator:
imageinfo.date Date:
@@ -675,6 +688,7 @@ keybindingmenu.channellist Channellist
keybindingmenu.channelup channel up
keybindingmenu.head Edit Keybindings
keybindingmenu.lastchannel Quick Zap
+keybindingmenu.longkeypress_duration Long key-press
keybindingmenu.misc Misc
keybindingmenu.mode_left_right_key_tv Left/Right Key Behavior in TV-Mode
keybindingmenu.mode_left_right_key_tv_infobar Show Infobar
@@ -738,6 +752,9 @@ ledcontroler.off Led1 & Led2 off
ledcontroler.on.all Led1 & Led2 on
ledcontroler.on.led1 Led1 on
ledcontroler.on.led2 Led2 on
+lua.function_deprecated1 Attention!
+lua.function_deprecated2 Function
+lua.function_deprecated3 is deprecated,\n please use
mainmenu.audioplayer Audioplayer
mainmenu.channels Channels
mainmenu.clearsectionsd Clear EPG Cache
@@ -804,6 +821,7 @@ menu.hint_audioplayer_title Enable SMS-style title search in playlist
menu.hint_auto_lang Auto-switch audio to preferred language
menu.hint_auto_subs Auto-start subtitles for preferred language
menu.hint_back Return to previous menu\nPress menu key to close all menus
+menu.hint_back_brief Return to previous menu
menu.hint_backlight Configure buttons backlight
menu.hint_backup Backup configs and channels to selected dir
menu.hint_bedit Edit favorites and bouquets
@@ -818,6 +836,8 @@ menu.hint_channellist_epg_align EPG event align
menu.hint_channellist_extended Show current event progress bar
menu.hint_channellist_fonts Change channel list font sizes
menu.hint_channellist_foot Show additional information\nin bottom box
+menu.hint_channellist_mode Use the selected channel list mode on startup if last mode is TV
+menu.hint_channellist_mode_radio Use the selected channel list mode on startup if last mode is Radio
menu.hint_channellist_setup Configure channel list GUI options
menu.hint_channellist_show_channellogo Show channellogos in channel list
menu.hint_channels Open channel list
@@ -843,6 +863,7 @@ menu.hint_epg_old_events Hours after event end time to consider\nevent old and r
menu.hint_epg_save Save cached EPG to harddisk or usb flash\nand load it after boot
menu.hint_epg_save_standby Save EPG on soft standby mode
menu.hint_epg_scan Enable background epg scan using free tuner,\ncurrent bouquet or all favorites
+menu.hint_epg_scan_mode Select box state to run epg scan
menu.hint_event_textcolor Change event color for colored-event options\nin channel list and infobar
menu.hint_eventlist_additional Show additional informations\nin main box
menu.hint_eventlist_fonts Change event list font sizes
@@ -934,6 +955,7 @@ menu.hint_key_pic_size_active Disable/enable key for the 4:3 display behavior
menu.hint_key_pip_close Assign button to stop PiP\nor start it for current channel
menu.hint_key_pip_setup Assign button to configure PiP
menu.hint_key_pip_swap Assign button to swap PiP and live channel
+menu.hint_key_plugin Assign button to execute the one touch plugin
menu.hint_key_poweroff Assign button to switch power state\n (standby/deepstandby <-> running)
menu.hint_key_quickzap Configure keybingdings for quick\nchannel switch
menu.hint_key_repeatblock Delay after button press and before\nfirst key repeat
@@ -960,6 +982,7 @@ menu.hint_leds_record LEDs state when box recording
menu.hint_leds_standby LEDs state in soft-standby mode
menu.hint_leds_tv Working LEDs state
menu.hint_load Load Neutrino-HD GUI settings from file
+menu.hint_longkeypress_duration A key press will be considered as "long key press" if it's pressed longer than the specified time.
menu.hint_lua Run Plugins
menu.hint_make_hdlist Auto-create HD channel list based on\nchannel type and name
menu.hint_make_newlist Create list of recently added channels
@@ -979,6 +1002,7 @@ menu.hint_misc_filebrowser Filesystem encoding, file rights\ndeny directory leav
menu.hint_misc_general Start to standby, cache teletext, swp rotor\nplugin hdd dir
menu.hint_misc_zapit Initial TV/Radio channels
menu.hint_movie Play movies
+menu.hint_movieplayer_plugin Choose a plugin that's executed with the one touch key in movieplayer mode
menu.hint_net_broadcast Enter broadcast address\nif unsure, use IP address with last .255
menu.hint_net_dhcp Use DHCP server to auto-configure
menu.hint_net_djmount Mount UPnP devices as filesystem\nunder /media/00upnp
@@ -1014,6 +1038,9 @@ menu.hint_net_xupnpd Share live channels over UPNP
menu.hint_network IP address, gateway, DNS, Time sync\nNetwork shares and services
menu.hint_new_zap_mode Allow channel switch while browsing\n(toggle mode with 'mute' in channel list)
menu.hint_numeric_adjust Adjust channel list mode on numeric zap
+menu.hint_onekey_plugin Choose a plugin that's executed with the one touch key
+menu.hint_opkg Install or update software packages
+menu.hint_opkg_upgrade Updates all installed packages to the most recent version available
menu.hint_osd Colors, fonts, screen size\nGUI look and feel options
menu.hint_osd_language Select OSD language
menu.hint_osd_preset Pre-configured screen margins for CRT and LCD TV
@@ -1044,16 +1071,19 @@ menu.hint_record_apid_alt Record alternative non-AC3 audio pids
menu.hint_record_apid_std Record first audio pid
menu.hint_record_apids Configure audio pids to record
menu.hint_record_apply Apply record options
+menu.hint_record_auto_cover Auto-create movie thumbnail for movie browser on record playback
menu.hint_record_chandir Create directory with name of channel\nto store recording
menu.hint_record_data Record (VideoText, subtitles) data streams
menu.hint_record_data_dvbsub subtitle stream
menu.hint_record_data_vtxt VideoText stream
menu.hint_record_dir Select directory to store recordings
menu.hint_record_end Stop direct record after maximal time or after current event end time
+menu.hint_record_filename_template edit filename template
menu.hint_record_slow_warn Show warning, when record buffer is close to overflow
menu.hint_record_startstop_msg Turns the message when recording start/end on or off.
menu.hint_record_tdir Select directory to save timeshift recordings\nin temporary timeshift mode
-menu.hint_record_time Record time before stop when\nusing direct record with record button
+menu.hint_record_time Record duration before stop when\nusing direct record with record button
+menu.hint_record_time_ts Timeshift duration before stop when\ntemporary timeshift enabled
menu.hint_record_timeafter Stop record after event end\nin minutes
menu.hint_record_timebefore Start record before event start\nin minutes
menu.hint_record_timer Configure record by timer options
@@ -1085,8 +1115,10 @@ menu.hint_scan_diseqcorder Diseqc command order for cascaded switches
menu.hint_scan_diseqcrepeat Diseqc repeat for cascaded switches
menu.hint_scan_diseqctype Select your diseqc switch protocol\nwith 'advanced' you can use uncommited switches
menu.hint_scan_fast CanalDigitaal/TéléSAT/TV Vlaanderen provider scan\nWARNING: diseqc config will be overwritten
+menu.hint_scan_fastdiseqc Start diseqc auto-configuration
menu.hint_scan_fastprov Select provider to scan
menu.hint_scan_fasttype Select fast scan type
+menu.hint_scan_fastupdate Enable/disable fast scan auto-update
menu.hint_scan_fec Select transponder FEC
menu.hint_scan_felink Select tuner to link tuner to
menu.hint_scan_femode Select tuner connection type
@@ -1106,6 +1138,7 @@ menu.hint_scan_logical_hd If both SD and HD channel versions present\nput HD to
menu.hint_scan_longitude Enter your longtitude
menu.hint_scan_manual Manual transponder scan using\nselected parameters
menu.hint_scan_mod Select transponder modulation
+menu.hint_scan_motor Rotor options, satellite finder
menu.hint_scan_motor_18v Use 18V when moving rotor
menu.hint_scan_motor_speed Rotor moving speed in 1/10 degree\nper second
menu.hint_scan_motorpos Select stored position number for this satellite,\nignored, if USALS enabled
@@ -1130,6 +1163,7 @@ menu.hint_scan_start Start scan. You can use 'exit' button to stop
menu.hint_scan_test Test signal for this transponder
menu.hint_scan_tpselect Select transponder to scan
menu.hint_scan_uncommited Select uncommited input for\nthis satellite
+menu.hint_scan_usals USALS options
menu.hint_scan_usals_repeat Repeat usals move rotor commands\nif you expirience unstable rotor move
menu.hint_scan_usalsall Use USALS for all satellites on this frontend
menu.hint_scan_useusals Use USALS for this satellite,\nif ON, rotor position ignored
@@ -1201,6 +1235,7 @@ menu.hint_video_modes VF key will cycle between enabled modes
menu.hint_video_pip Picture in picture size and position
menu.hint_video_saturation Change picture saturation
menu.hint_video_scart_mode Select analog output mode for SCART connectors
+menu.hint_video_sdosd Enable/disable OSD display on SD output (scart, cinch)
menu.hint_volume Configure Volume GUI options
menu.hint_volume_digits Numeric display of the volumebar on/off
menu.hint_volume_pos Select volume indicator position
@@ -1241,8 +1276,12 @@ miscsettings.epg_old_events_hint2 Set in hours
miscsettings.epg_save Save/Restore epg on reboot
miscsettings.epg_save_standby Save epg on soft standby
miscsettings.epg_scan EPG scan
+miscsettings.epg_scan_always Always
miscsettings.epg_scan_bq bouquet
miscsettings.epg_scan_fav favorites
+miscsettings.epg_scan_live Live
+miscsettings.epg_scan_sel Selected
+miscsettings.epg_scan_standby Standby
miscsettings.general General
miscsettings.head Extended settings
miscsettings.infobar Infobar
@@ -1497,7 +1536,7 @@ mpkey.bookmark save bookmark
mpkey.forward Forward
mpkey.pause Pause
mpkey.play Play
-mpkey.plugin Run plugin
+mpkey.plugin Movieplayer plugin
mpkey.rewind Rewind
mpkey.stop Stop
mpkey.subtitle Subtitles
@@ -1564,6 +1603,19 @@ nvod.starting (starting in %d min)
nvodselector.directormode Direct-Mode
nvodselector.head Select starting-time
nvodselector.subservice Select Subservice
+opkg.button.expert_off Standard mode
+opkg.button.expert_on Expert mode
+opkg.button.info Package information
+opkg.button.install Install package
+opkg.button.uninstall Uninstall package
+opkg.failure.install Install failed (%d)
+opkg.failure.update Update failed (%d)
+opkg.failure.upgrade Upgrade failed (%d)
+opkg.messagebox.reinstall Re-install %s?
+opkg.messagebox.remove Remove %s?
+opkg.success.install Install successful, restart of Neutrino might be required.
+opkg.title Package Management
+opkg.upgrade Upgrade installed packages
options.default Reset to defaults
options.fb framebuffer
options.ntp_off DVB
@@ -1684,6 +1736,7 @@ recordingmenu.apids Audio streams
recordingmenu.apids_ac3 record AC3 streams
recordingmenu.apids_alt record alternative streams
recordingmenu.apids_std record standard stream
+recordingmenu.auto_cover Auto-thumbnail
recordingmenu.data_pids Data streams
recordingmenu.defdir Recording directory
recordingmenu.dvbsub_pids record dvbsub stream
@@ -1691,6 +1744,9 @@ recordingmenu.end_of_recording_epg EPG act. Event
recordingmenu.end_of_recording_max max. Recordingtime
recordingmenu.end_of_recording_name Endtime of Recording
recordingmenu.file direct (file)
+recordingmenu.filename_template filename template
+recordingmenu.filename_template_hint wildcards will be replaced
+recordingmenu.filename_template_hint2 %C = channel, %T = title, %I = info, %d = date, %t = time
recordingmenu.help Recording devices:\n--------------------------\nserver:\nusing streaming software on a PC\n\n(analog) vcr:\nusing the vcr outlet\n\ndirect (file):\ndirectly into an NFS mounted directory\nor onto an internal hard drive\nTS: use spts mode(dbox2)\nPES: do not use spts mode(dbox2)\n\n\nMax. file size:\n---------------------\nNFS V2: 2 GB (2048 MB)\nNFS V3: almost unlimited (0 MB)\nFAT: 2 GB (2048 MB)\nFAT32: 4 GB (4096 MB)
recordingmenu.multimenu.ask_stop_all really stop all %d recordings?
recordingmenu.multimenu.info_stop_all %d of %d recordings will be stopped.
@@ -1734,14 +1790,24 @@ satsetup.diseqcrepeat DiSEqC-repeats
satsetup.extended DiSEqC-Settings
satsetup.extended_motor Motor-Settings
satsetup.fastscan_all SD and HD
+satsetup.fastscan_auto_diseqc Start auto-diseqc configuration
+satsetup.fastscan_auto_diseqc_wait Auto-diseqc configuration in progress
satsetup.fastscan_hd HD only
-satsetup.fastscan_head Fast scan (Astra 1, 19.2E, 12.515Mhz)
+satsetup.fastscan_head Fast scan
satsetup.fastscan_prov Provider
-satsetup.fastscan_prov_cd CanalDigitaal
-satsetup.fastscan_prov_telesat TéléSAT
-satsetup.fastscan_prov_tvv TV Vlaanderen
+satsetup.fastscan_prov_cd_hd CanalDigitaal (HD)
+satsetup.fastscan_prov_cd_sd CanalDigitaal (SD)
+satsetup.fastscan_prov_hda HD Austria
+satsetup.fastscan_prov_hello Hello
+satsetup.fastscan_prov_skylink_c Skylink Czech
+satsetup.fastscan_prov_skylink_s Skylink Slovak
+satsetup.fastscan_prov_telesat_b TéléSAT Belgium
+satsetup.fastscan_prov_telesat_l TéléSAT Luxemburg
+satsetup.fastscan_prov_tvv_hd TV Vlaanderen (HD)
+satsetup.fastscan_prov_tvv_sd TV Vlaanderen (SD)
satsetup.fastscan_sd SD only
satsetup.fastscan_type Scan type
+satsetup.fastscan_update Auto update
satsetup.fe_mode Tuner mode
satsetup.fe_mode_independent Independent
satsetup.fe_mode_link_loop Loop
@@ -1794,7 +1860,7 @@ scants.channel Channel:
scants.failed Transponderscan failed!
scants.finished Transponderscan finished successfully!
scants.freqdata Frequency:
-scants.head Scan transponder
+scants.head Service scan
scants.numberofdataservices Data
scants.numberofradioservices Radio
scants.numberoftotalservices Total
@@ -1875,8 +1941,10 @@ streaming.slow System/hdd too slow, consider to stop some records
streaming.write_error The recording was aborted,\nsince an error occured during the writing process.
stringinput.caps caps / no caps
stringinput.clear clear all
+subtitles.charset Charset
subtitles.head Subtitles
subtitles.stop Stop subtitles
+terrestrialsetup.area Area
terrestrialsetup.provider Terrestrial Provider
timer.eventrecord.msg The event is scheduled for recording.\nTo edit the schedule open the timer list.
timer.eventrecord.title Schedule Record
@@ -2031,6 +2099,7 @@ videomenu.pip_error PiP start failed
videomenu.saturation Saturation
videomenu.scart Scart
videomenu.screensetup Screen Setup
+videomenu.sdosd SD OSD
videomenu.sharpness Sharpness
videomenu.tv-scart Video
videomenu.vcrsignal VCR Output Signal Type
@@ -2057,6 +2126,8 @@ zapit.scantype.all all services
zapit.scantype.radio only radio
zapit.scantype.tv only tv
zapit.scantype.tvradio tv & radio
+zapitsetup.channelmode Initial TV channel list
+zapitsetup.channelmode_radio Initial Radio channel list
zapitsetup.head Start Channel Settings
zapitsetup.info Start Channel
zapitsetup.last_radio Radio Channel
diff --git a/data/locale/nederlands.locale b/data/locale/nederlands.locale
index 5f4d0e229..6688ca37b 100644
--- a/data/locale/nederlands.locale
+++ b/data/locale/nederlands.locale
@@ -314,6 +314,11 @@ date.Sun Zo
date.Thu Do
date.Tue Di
date.Wed Wo
+debug Debug Output
+debug.level Level
+debug.level_1 normaal
+debug.level_2 informatieve
+debug.level_3 verbose
epg.saving Opslaan EPG
epgextended.actors Acteurs
epgextended.director Regisseur
@@ -1713,8 +1718,8 @@ settings.backup_failed Backup maken mislukt
settings.help Help
settings.menu_hints Menu hints weergeven
settings.menu_pos Menu positie
-settings.missingoptionsconffile De instellingen zijn geupdate. \nNieuwe opties zijn standaard ingesteld.
-settings.noconffile Geen Neutrino-HD instellingen gevonden.\n Gebruikt standaard instellingen.
+settings.missingoptionsconffile De instellingen zijn geupdate.\nNieuwe opties zijn standaard ingesteld.
+settings.noconffile Geen Neutrino-HD instellingen gevonden.\nGebruikt standaard instellingen.
settings.pos_bottom_left Links onder
settings.pos_bottom_right Rechts onder
settings.pos_default_center Gecentreerd boven
@@ -1724,8 +1729,8 @@ settings.pos_top_right Rechts boven
settings.restore Instellingen herstellen
settings.restore_warn Alle instellingen zullen vervangen worden.\nDe ontvanger zal opnieuw opstarten\nWilt u verder gaan?
shutdown.recoding_query Wilt u de opname stoppen?
-shutdowntimer.announce De ontvanger zal binnen 1 minuut uitschakelen./nWilt u het uitschakelen annuleren?
-sleeptimerbox.announce De ontvanger zal binnen 1 minunut in standby schakelen./nlWilt u dit annuleren?
+shutdowntimer.announce De ontvanger zal binnen 1 minuut uitschakelen.\nWilt u het uitschakelen annuleren?
+sleeptimerbox.announce De ontvanger zal binnen 1 minuut in standby schakelen.\nWilt u dit annuleren?
sleeptimerbox.hint1 Afsluit tijd in minuten (000=uit)
sleeptimerbox.hint2 De ontvanger schakelt zichzelf uit na deze periode in standby.
sleeptimerbox.hint3 De ontvanger zal automatisch uitschakelen indien u de afstandsbediening niet gebruikt.
diff --git a/data/locale/slovak.locale b/data/locale/slovak.locale
index de11ee7c4..51b9187d9 100644
--- a/data/locale/slovak.locale
+++ b/data/locale/slovak.locale
@@ -316,6 +316,11 @@ date.Sun Ne
date.Thu Št
date.Tue Ut
date.Wed St
+debug Debug Output
+debug.level Rovina
+debug.level_1 normálne
+debug.level_2 informatívny
+debug.level_3 detail
epg.saving Uloženie EPG
epgextended.actors Herci
epgextended.director Režisér
@@ -1726,7 +1731,7 @@ satsetup.extended Nastavenia DiSEqC
satsetup.extended_motor Nastavenia motora
satsetup.fastscan_all SD a HD
satsetup.fastscan_hd len HD
-satsetup.fastscan_head Rýchle prehľadanie (Astra 1 - 12515 MHz)
+satsetup.fastscan_head Rýchle prehľadanie
satsetup.fastscan_prov Poskytovateľ
satsetup.fastscan_prov_cd CanalDigitaal
satsetup.fastscan_prov_telesat TéléSAT
diff --git a/data/satellites.xml b/data/satellites.xml
index 6496837e3..d28eb8946 100644
--- a/data/satellites.xml
+++ b/data/satellites.xml
@@ -1428,11 +1428,11 @@
-
+
-
+
@@ -1440,10 +1440,11 @@
+
+
-
-
+
@@ -1454,7 +1455,6 @@
-
@@ -1474,30 +1474,20 @@
-
+
-
+
-
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
@@ -1505,19 +1495,18 @@
-
-
-
-
+
+
-
+
+
@@ -1525,18 +1514,20 @@
-
-
+
+
+
+
-
-
+
+
+
-
-
+
diff --git a/lib/libcoolstream2/dmx_cs.h b/lib/libcoolstream2/dmx_cs.h
index 2e7630508..df105dcff 100644
--- a/lib/libcoolstream2/dmx_cs.h
+++ b/lib/libcoolstream2/dmx_cs.h
@@ -23,7 +23,12 @@
#endif
#define DMX_FILTER_SIZE MAX_FILTER_LENGTH
-#define MAX_DMX_UNITS 5
+#define MAX_DMX_UNITS cDemux::GetCount(DMX_TS)
+
+typedef enum {
+ DMX_TS = 0,
+ DMX_DMA,
+} DMX_TYPE;
typedef enum {
DMX_VIDEO_CHANNEL = 1,
@@ -81,5 +86,6 @@ public:
int GetSource();
static bool SetSource(int unit, int source);
static int GetSource(int unit);
+ static u32 GetCount(DMX_TYPE Type = DMX_TS);
};
#endif //__DMX_CS_H_
diff --git a/lib/libcoolstream2/video_cs.h b/lib/libcoolstream2/video_cs.h
index 07310e313..9f15eb8fc 100644
--- a/lib/libcoolstream2/video_cs.h
+++ b/lib/libcoolstream2/video_cs.h
@@ -130,6 +130,8 @@ typedef enum {
VIDEO_STD_1080P25,
VIDEO_STD_1080P50,
VIDEO_STD_1080P60,
+ VIDEO_STD_1080P2397,
+ VIDEO_STD_1080P2997,
VIDEO_STD_AUTO,
VIDEO_STD_MAX = VIDEO_STD_AUTO
} VIDEO_STD;
diff --git a/src/Makefile.am b/src/Makefile.am
index 2bb2ad126..93478530f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,12 +33,10 @@ else
VORBISLIBS = -lvorbisfile -lvorbis -logg
endif
-bin_PROGRAMS = neutrino rcsim
+bin_PROGRAMS = neutrino
neutrino_SOURCES = neutrino_menue.cpp neutrino.cpp
-rcsim_SOURCES = rcsim.c rcsim.h
-
if ENABLE_FLAC
FLACLIBS = -lFLAC
else
@@ -101,6 +99,7 @@ neutrino_LDADD = \
@CURL_LIBS@ \
@FREETYPE_LIBS@ \
@PNG_LIBS@ \
+ @BLURAY_LIBS@ \
@LIBCS_LIBS@ \
@AVFORMAT_LIBS@ \
@AVUTIL_LIBS@ \
@@ -136,11 +135,19 @@ neutrino_LDADD += -lnxp
endif
endif
+if BOXMODEL_APOLLO
+neutrino_LDADD += -liconv
+endif
+
bin_PROGRAMS += drivertool
drivertool_SOURCES = drivertool.c
bin_PROGRAMS += dt
dt_SOURCES = dt.c
endif
+bin_PROGRAMS += rcsim
+rcsim_SOURCES = rcsim.c rcsim.h
+bin_PROGRAMS += mdev_helper
+mdev_helper_SOURCES = mdev_helper.cpp
if USE_STB_HAL
neutrino_LDADD += \
diff --git a/src/daemonc/remotecontrol.cpp b/src/daemonc/remotecontrol.cpp
index 57364ee1e..37109315c 100644
--- a/src/daemonc/remotecontrol.cpp
+++ b/src/daemonc/remotecontrol.cpp
@@ -443,7 +443,7 @@ void CRemoteControl::processAPIDnames()
const char *desc;
char lang[4];
- if(g_settings.auto_lang) {
+ if(g_settings.auto_lang && (current_PIDs.APIDs.size() > 1)) {
/* first we check prefs to find pid according to pref index */
for(int i = 0; i < 3; i++) {
for(int j = 0; j < (int) current_PIDs.APIDs.size(); j++) {
diff --git a/src/driver/file.cpp b/src/driver/file.cpp
index 8bbb099b5..aa3002c98 100644
--- a/src/driver/file.cpp
+++ b/src/driver/file.cpp
@@ -43,7 +43,7 @@
const char * const file_extension_list[] =
{
"aac", "asf", "avi", "bmp", "cdr", "crw",
- "dts", "flac", "gif", "imu", "jpeg", "jpg",
+ "dts", "flac", "gif", "imu", "iso", "jpeg", "jpg",
"m2a", "m3u", "m4a", "mkv", "mp2", "mp3",
"mpa", "ogg", "pls", "png", "sh",
"txt", "url", "wav", "xml"
@@ -53,7 +53,7 @@ const char * const file_extension_list[] =
const CFile::FileType file_type_list[] =
{
CFile::FILE_AAC , CFile::FILE_ASF , CFile::FILE_AVI , CFile::FILE_PICTURE , CFile::FILE_CDR , CFile::FILE_PICTURE ,
- CFile::FILE_WAV , CFile::FILE_FLAC , CFile::FILE_PICTURE , CFile::STREAM_PICTURE, CFile::FILE_PICTURE , CFile::FILE_PICTURE ,
+ CFile::FILE_WAV , CFile::FILE_FLAC , CFile::FILE_PICTURE , CFile::STREAM_PICTURE, CFile::FILE_ISO , CFile::FILE_PICTURE , CFile::FILE_PICTURE ,
CFile::FILE_MP3 , CFile::FILE_PLAYLIST , CFile::FILE_AAC , CFile::FILE_MKV , CFile::FILE_MP3 , CFile::FILE_MP3 ,
CFile::FILE_MP3 , CFile::FILE_OGG , CFile::FILE_PLAYLIST, CFile::FILE_PICTURE , CFile::FILE_TEXT ,
CFile::FILE_TEXT , CFile::STREAM_AUDIO , CFile::FILE_WAV , CFile::FILE_XML
diff --git a/src/driver/file.h b/src/driver/file.h
index c807d1bae..1b578ca51 100644
--- a/src/driver/file.h
+++ b/src/driver/file.h
@@ -60,6 +60,7 @@ public:
FILE_AVI,
FILE_ASF,
FILE_DIR,
+ FILE_ISO,
FILE_TEXT,
FILE_CDR,
FILE_MP3,
diff --git a/src/driver/pictureviewer/pictureviewer.cpp b/src/driver/pictureviewer/pictureviewer.cpp
index d42b6f606..809523849 100644
--- a/src/driver/pictureviewer/pictureviewer.cpp
+++ b/src/driver/pictureviewer/pictureviewer.cpp
@@ -102,6 +102,29 @@ CPictureViewer::CFormathandler * CPictureViewer::fh_getsize (const char *name, i
}
return (NULL);
}
+std::string CPictureViewer::DownloadImage(std::string url)
+{
+ if (strstr(url.c_str(), "://")) {
+ std::string tmpname = "/tmp/pictureviewer" + url.substr(url.find_last_of("."));
+ FILE *tmpFile = fopen(tmpname.c_str(), "wb");
+ if (tmpFile) {
+ CURL *ch = curl_easy_init();
+ curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
+ curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
+ curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
+ curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, NULL);
+ curl_easy_setopt(ch, CURLOPT_WRITEDATA, tmpFile);
+ curl_easy_setopt(ch, CURLOPT_FAILONERROR, 1L);
+ curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
+ curl_easy_perform(ch);
+ curl_easy_cleanup(ch);
+ fclose(tmpFile);
+ url = true;
+ }
+ url = tmpname;
+ }
+ return url;
+}
bool CPictureViewer::DecodeImage (const std::string & _name, bool showBusySign, bool unscaled)
{
@@ -121,29 +144,9 @@ bool CPictureViewer::DecodeImage (const std::string & _name, bool showBusySign,
if (showBusySign)
showBusy (m_startx + 3, m_starty + 3, 10, 0xff, 00, 00);
- std::string name = _name;
bool url = false;
- if (strstr(name.c_str(), "://")) {
- std::string tmpname;
- tmpname = "/tmp/pictureviewer" + name.substr(name.find_last_of("."));
- FILE *tmpFile = fopen(tmpname.c_str(), "wb");
- if (tmpFile) {
- CURL *ch = curl_easy_init();
- curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
- curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
- curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, NULL);
- curl_easy_setopt(ch, CURLOPT_WRITEDATA, tmpFile);
- curl_easy_setopt(ch, CURLOPT_FAILONERROR, 1L);
- curl_easy_setopt(ch, CURLOPT_URL, name.c_str());
- curl_easy_perform(ch);
- curl_easy_cleanup(ch);
- fclose(tmpFile);
- url = true;
- }
- name = tmpname;
- }
+ std::string name = DownloadImage(_name);
CFormathandler *fh;
if (unscaled)
@@ -499,6 +502,7 @@ void CPictureViewer::getSize(const char* name, int* width, int *height)
}
#define LOGO_FLASH_DIR DATADIR "/neutrino/icons/logo"
+#define LOGO_FLASH_DIR_VAR "/var/tuxbox/icons/logo"
bool CPictureViewer::GetLogoName(const uint64_t& channel_id, const std::string& ChannelName, std::string & name, int *width, int *height)
{
@@ -523,6 +527,16 @@ bool CPictureViewer::GetLogoName(const uint64_t& channel_id, const std::string&
id_tmp_path += strChnId + fileType[i];
v_path.push_back(id_tmp_path);
+ //create filename with channel name (LOGO_FLASH_DIR_VAR)
+ id_tmp_path = LOGO_FLASH_DIR_VAR "/";
+ id_tmp_path += ChannelName + fileType[i];
+ v_path.push_back(id_tmp_path);
+
+ //create filename with id (LOGO_FLASH_DIR_VAR)
+ id_tmp_path = LOGO_FLASH_DIR_VAR "/";
+ id_tmp_path += strChnId + fileType[i];
+ v_path.push_back(id_tmp_path);
+
//create filename with channel name (LOGO_FLASH_DIR)
id_tmp_path = LOGO_FLASH_DIR "/";
id_tmp_path += ChannelName + fileType[i];
diff --git a/src/driver/pictureviewer/pictureviewer.h b/src/driver/pictureviewer/pictureviewer.h
index 71d8d256f..4326c45d4 100644
--- a/src/driver/pictureviewer/pictureviewer.h
+++ b/src/driver/pictureviewer/pictureviewer.h
@@ -54,6 +54,7 @@ class CPictureViewer
bool ShowImage(const std::string & filename, bool unscaled=false);
bool DecodeImage(const std::string & name, bool showBusySign=false, bool unscaled=false);
bool DisplayNextImage();
+ std::string DownloadImage(std::string url);
void SetScaling(ScalingMode s){m_scaling=s;}
void SetAspectRatio(float aspect_ratio) {m_aspect=aspect_ratio;}
void showBusy(int sx, int sy, int width, char r, char g, char b);
diff --git a/src/driver/rcinput.cpp b/src/driver/rcinput.cpp
index 02353ef3f..c161b7c6f 100644
--- a/src/driver/rcinput.cpp
+++ b/src/driver/rcinput.cpp
@@ -5,6 +5,7 @@
2003 thegoodguy
Copyright (C) 2008-2012 Stefan Seyfried
+ Copyright (C) 2013-2014 martii
License: GPL
@@ -29,6 +30,7 @@
#include
#include
+#include
#include
#include
@@ -52,13 +54,14 @@
#include
#include
-#include
+//#include
+#include
#include
#include
+#include
#include
//#define RCDEBUG
-//#define USE_GETTIMEOFDAY
#define ENABLE_REPEAT_CHECK
@@ -88,6 +91,8 @@ static bool input_stopped = false;
CRCInput::CRCInput()
{
timerid= 1;
+ repeatkeys = NULL;
+ longPressAny = false;
// pipe for internal event-queue
// -----------------------------
@@ -119,7 +124,7 @@ CRCInput::CRCInput()
int clilen;
memset(&servaddr, 0, sizeof(struct sockaddr_un));
servaddr.sun_family = AF_UNIX;
- strcpy(servaddr.sun_path, NEUTRINO_UDS_NAME);
+ cstrncpy(servaddr.sun_path, NEUTRINO_UDS_NAME, sizeof(servaddr.sun_path));
clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
unlink(NEUTRINO_UDS_NAME);
@@ -150,7 +155,7 @@ CRCInput::CRCInput()
repeat_block = repeat_block_generic = 0;
open();
rc_last_key = KEY_MAX;
- firstKey = true;
+ longPressEnd = 0;
//select and setup remote control hardware
set_rc_hw();
@@ -176,6 +181,8 @@ void CRCInput::open(int dev)
//+++++++++++++++++++++++++++++++++++++++
#ifdef KEYBOARD_INSTEAD_OF_REMOTE_CONTROL
fd_keyb = STDIN_FILENO;
+ if (fd_rc[0] < 0)
+ fd_rc[0] = fd_keyb;
#else
fd_keyb = 0;
#endif /* KEYBOARD_INSTEAD_OF_REMOTE_CONTROL */
@@ -352,13 +359,7 @@ int CRCInput::messageLoop( bool anyKeyCancels, int timeout )
int CRCInput::addTimer(uint64_t Interval, bool oneshot, bool correct_time )
{
-#ifdef USE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday( &tv, NULL );
- uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t timeNow = time_monotonic_us();
-#endif
timer _newtimer;
if (!oneshot)
@@ -390,19 +391,6 @@ int CRCInput::addTimer(uint64_t Interval, bool oneshot, bool correct_time )
return _newtimer.id;
}
-#ifdef USE_GETTIMEOFDAY
-int CRCInput::addTimer(struct timeval Timeout)
-{
- uint64_t timesout = (uint64_t) Timeout.tv_usec + (uint64_t)((uint64_t) Timeout.tv_sec * (uint64_t) 1000000);
- return addTimer( timesout, true, false );
-}
-
-int CRCInput::addTimer(const time_t *Timeout)
-{
- return addTimer( (uint64_t)*Timeout* (uint64_t) 1000000, true, false );
-}
-#endif
-
void CRCInput::killTimer(uint32_t &id)
{
//printf("killing timer %d\n", id);
@@ -422,13 +410,7 @@ void CRCInput::killTimer(uint32_t &id)
int CRCInput::checkTimers()
{
int _id = 0;
-#ifdef USE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday( &tv, NULL );
- uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t timeNow = time_monotonic_us();
-#endif
std::vector::iterator e;
for ( e= timers.begin(); e!= timers.end(); ++e )
if ( e->times_out< timeNow+ 2000 )
@@ -468,36 +450,18 @@ int CRCInput::checkTimers()
int64_t CRCInput::calcTimeoutEnd(const int timeout_in_seconds)
{
-#ifdef USE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec + (uint64_t)timeout_in_seconds) * (uint64_t) 1000000;
-#else
return time_monotonic_us() + ((uint64_t)timeout_in_seconds * (uint64_t) 1000000);
-#endif
}
int64_t CRCInput::calcTimeoutEnd_MS(const int timeout_in_milliseconds)
{
-#ifdef USE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday(&tv, NULL);
- uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t timeNow = time_monotonic_us();
-#endif
return ( timeNow + timeout_in_milliseconds * 1000 );
}
void CRCInput::getMsgAbsoluteTimeout(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint64_t *TimeoutEnd, bool bAllowRepeatLR)
{
-#ifdef USE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday( &tv, NULL );
- uint64_t timeNow = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t timeNow = time_monotonic_us();
-#endif
uint64_t diff;
if ( *TimeoutEnd < timeNow+ 100 )
@@ -507,16 +471,6 @@ void CRCInput::getMsgAbsoluteTimeout(neutrino_msg_t * msg, neutrino_msg_data_t *
//printf("CRCInput::getMsgAbsoluteTimeout diff %llx TimeoutEnd %llx now %llx\n", diff, *TimeoutEnd, timeNow);
getMsg_us( msg, data, diff, bAllowRepeatLR );
-#ifdef USE_GETTIMEOFDAY
- if ( *msg == NeutrinoMessages::EVT_TIMESET )
- {
- // recalculate timeout....
- //uint64_t ta= *TimeoutEnd;
- *TimeoutEnd= *TimeoutEnd + *(int64_t*) *data;
-
- //printf("[getMsgAbsoluteTimeout]: EVT_TIMESET - recalculate timeout\n%llx/%llx - %llx/%llx\n", timeNow, *(int64_t*) *data, *TimeoutEnd, ta );
- }
-#endif
}
void CRCInput::getMsg(neutrino_msg_t * msg, neutrino_msg_data_t * data, int Timeout, bool bAllowRepeatLR)
@@ -529,6 +483,43 @@ void CRCInput::getMsg_ms(neutrino_msg_t * msg, neutrino_msg_data_t * data, int T
getMsg_us(msg, data, (uint64_t) Timeout * 1000, bAllowRepeatLR);
}
+uint32_t *CRCInput::setAllowRepeat(uint32_t *rk) {
+ uint32_t *r = repeatkeys;
+ repeatkeys = rk;
+ return r;
+}
+
+bool checkLongPress(uint32_t key); // keybind_setup.cpp
+
+bool CRCInput::mayLongPress(uint32_t key, bool bAllowRepeatLR)
+{
+ if (mayRepeat(key, bAllowRepeatLR))
+ return false;
+ if (longPressAny)
+ return true;
+ return checkLongPress(key);
+}
+
+bool CRCInput::mayRepeat(uint32_t key, bool bAllowRepeatLR)
+{
+ if((key == RC_up) || (key == RC_down)
+ || (key == RC_plus) || (key == RC_minus)
+ || (key == RC_page_down) || (key == RC_page_up)
+ || ((bAllowRepeatLR) && ((key == RC_left ) || (key == RC_right))))
+ return true;
+
+ if (repeatkeys) {
+ uint32_t *k = repeatkeys;
+ while (*k != RC_nokey) {
+ if (*k == key) {
+ return true;
+ }
+ k++;
+ }
+ }
+ return false;
+}
+
void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint64_t Timeout, bool bAllowRepeatLR)
{
static uint64_t last_keypress = 0ULL;
@@ -544,7 +535,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
int timer_id;
fd_set rfds;
- t_input_event ev;
*data = 0;
@@ -559,25 +549,13 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
}
// wiederholung reinmachen - dass wirklich die ganze zeit bis timeout gewartet wird!
-#ifdef USE_GETTIMEOFDAY
- gettimeofday( &tv, NULL );
- uint64_t getKeyBegin = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t getKeyBegin = time_monotonic_us();
-#endif
+
while(1) {
- /* we later check for ev.type = EV_SYN which is 0x00, so set something invalid here... */
- memset(&ev, 0, sizeof(ev));
- ev.type = EV_MAX;
timer_id = 0;
if ( !timers.empty() )
{
-#ifdef USE_GETTIMEOFDAY
- gettimeofday( &tv, NULL );
- uint64_t t_n= (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
-#else
uint64_t t_n = time_monotonic_us();
-#endif
if ( timers[0].times_out< t_n )
{
timer_id = checkTimers();
@@ -950,12 +928,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
if ((int64_t)last_keypress > *(int64_t*)p)
last_keypress += *(int64_t *)p;
-#ifdef USE_GETTIMEOFDAY
- // Timer anpassen
- for(std::vector::iterator e = timers.begin(); e != timers.end(); ++e)
- if (e->correct_time)
- e->times_out+= *(int64_t*) p;
-#endif
*msg = NeutrinoMessages::EVT_TIMESET;
*data = (neutrino_msg_data_t) p;
dont_delete_p = true;
@@ -1197,7 +1169,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
*data = (unsigned long) p;
dont_delete_p = true;
break;
-
default :
printf("[neutrino] event INITID_TIMERD - unknown eventID 0x%x\n", emsg.eventID );
@@ -1205,6 +1176,13 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
}
else if (emsg.initiatorID == CEventServer::INITID_NEUTRINO)
{
+ printf("CRCInput::getMsg_us: INITID_NEUTRINO: msg %x size %d data %x\n", (int) emsg.eventID, emsg.dataSize, (int) p);
+ if (emsg.eventID == NeutrinoMessages::EVT_HOTPLUG) {
+ printf("EVT_HOTPLUG: [%s]\n", (char *) p);
+ *msg = emsg.eventID;
+ *data = (neutrino_msg_data_t) p;
+ dont_delete_p = true;
+ }
#if 0
if ((emsg.eventID == NeutrinoMessages::EVT_RECORDING_ENDED) &&
(read_bytes == sizeof(stream2file_status2_t)))
@@ -1225,10 +1203,21 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
}
else
printf("[neutrino] event - unknown initiatorID 0x%x\n", emsg.initiatorID);
- if ( !dont_delete_p )
- {
- delete[] p;//new [] delete []
- p= NULL;
+
+ switch (emsg.eventID) {
+ case NeutrinoMessages::EVT_CURRENTEPG:
+ case NeutrinoMessages::EVT_NEXTEPG:
+ {
+ CSectionsdClient::CurrentNextInfo *cn = (CSectionsdClient::CurrentNextInfo *) p;
+ delete cn;
+ p = NULL;
+ break;
+ }
+ default:
+ if (!dont_delete_p) {
+ delete[] p;
+ p = NULL;
+ }
}
}
}
@@ -1249,8 +1238,11 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
for (int i = 0; i < NUMBER_OF_EVENT_DEVICES; i++) {
if ((fd_rc[i] != -1) && (FD_ISSET(fd_rc[i], &rfds))) {
- int ret;
- ret = read(fd_rc[i], &ev, sizeof(t_input_event));
+ t_input_event ev;
+ memset(&ev, 0, sizeof(ev));
+ /* we later check for ev.type = EV_SYN = 0x00, so set something invalid here... */
+ ev.type = EV_MAX;
+ int ret = read(fd_rc[i], &ev, sizeof(t_input_event));
if (ret != sizeof(t_input_event)) {
if (errno == ENODEV) {
/* hot-unplugged? */
@@ -1262,19 +1254,44 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
if (ev.type == EV_SYN)
continue; /* ignore... */
SHTDCNT::getInstance()->resetSleepTimer();
- if (firstKey) {
- firstKey = false;
- CTimerManager::getInstance()->cancelShutdownOnWakeup();
- }
uint32_t trkey = translate(ev.code);
#ifdef _DEBUG
printf("key: %04x value %d, translate: %04x -%s-\n", ev.code, ev.value, trkey, getKeyName(trkey).c_str());
#endif
if (trkey == RC_nokey)
continue;
+
+ if (g_settings.longkeypress_duration > LONGKEYPRESS_OFF) {
+ uint64_t longPressNow = time_monotonic_us();
+ if (ev.value == 0 && longPressEnd) {
+ if (longPressNow < longPressEnd) {
+ // Key was a potential long press, but wasn't pressed long enough
+ longPressEnd = 0;
+ ev.value = 1;
+ } else {
+ // Long-press, key released after time limit
+ longPressEnd = 0;
+ continue;
+ }
+ } else if (ev.value == 1 && mayLongPress(trkey, bAllowRepeatLR)) {
+ // A long-press may start here.
+ longPressEnd = longPressNow + 1000 * g_settings.longkeypress_duration;
+ rc_last_key = KEY_MAX;
+ continue;
+ } else if (ev.value == 2 && longPressEnd) {
+ if (longPressEnd < longPressNow) {
+ // Key was pressed long enough.
+ ev.value = 1;
+ trkey |= RC_Repeat;
+ } else {
+ // Long-press, but key still not released. Skip.
+ continue;
+ }
+ }
+ }
+
if (ev.value) {
#ifdef RCDEBUG
- printf("got keydown native key: %04x %04x, translate: %04x -%s-\n", ev.code, ev.code&0x1f, translate(ev.code, 0), getKeyName(translate(ev.code, 0)).c_str());
printf("rc_last_key %04x rc_last_repeat_key %04x\n\n", rc_last_key, rc_last_repeat_key);
#endif
uint64_t now_pressed;
@@ -1282,21 +1299,17 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
tv = ev.time;
now_pressed = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
- if (ev.code == rc_last_key) {
+ if (trkey == rc_last_key) {
/* only allow selected keys to be repeated */
- /* (why?) */
- if( (trkey == RC_up) || (trkey == RC_down ) ||
- (trkey == RC_plus ) || (trkey == RC_minus ) ||
- (trkey == RC_page_down ) || (trkey == RC_page_up ) ||
- ((bAllowRepeatLR) && ((trkey == RC_left ) || (trkey == RC_right))) ||
- (g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown))))
+ if (mayRepeat(trkey, bAllowRepeatLR) ||
+ (g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown))))
{
#ifdef ENABLE_REPEAT_CHECK
- if (rc_last_repeat_key != ev.code) {
+ if (rc_last_repeat_key != trkey) {
if ((now_pressed > last_keypress + repeat_block) ||
/* accept all keys after time discontinuity: */
(now_pressed < last_keypress))
- rc_last_repeat_key = ev.code;
+ rc_last_repeat_key = trkey;
else
keyok = false;
}
@@ -1308,7 +1321,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
else
rc_last_repeat_key = KEY_MAX;
- rc_last_key = ev.code;
+ rc_last_key = trkey;
if (keyok) {
#ifdef ENABLE_REPEAT_CHECK
@@ -1329,9 +1342,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
} /* if (ev.value) */
else {
// clear rc_last_key on keyup event
-#ifdef RCDEBUG
- printf("got keyup native key: %04x %04x, translate: %04x -%s-\n", ev.code, ev.code&0x1f, translate(ev.code, 0), getKeyName(translate(ev.code, 0)).c_str() );
-#endif
rc_last_key = KEY_MAX;
if (trkey == RC_standby) {
*msg = RC_standby;
@@ -1341,8 +1351,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
}
}/* if FDSET */
} /* for NUMBER_OF_EVENT_DEVICES */
- if (ev.type == EV_SYN)
- continue; /* ignore... */
if(FD_ISSET(fd_pipe_low_priority[0], &rfds))
{
@@ -1368,12 +1376,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6
else
{
//timeout neu kalkulieren
-#ifdef USE_GETTIMEOFDAY
- gettimeofday( &tv, NULL );
- int64_t getKeyNow = (int64_t) tv.tv_usec + (int64_t)((int64_t) tv.tv_sec * (int64_t) 1000000);
-#else
int64_t getKeyNow = time_monotonic_us();
-#endif
int64_t diff = (getKeyNow - getKeyBegin);
if( Timeout <= (uint64_t) diff )
{
@@ -1447,21 +1450,21 @@ unsigned int CRCInput::convertDigitToKey(const unsigned int digit)
}
/**************************************************************************
-* getUnicodeValue - return unicode value of the key or -1
+* getUnicodeValue - return unicode value of the key or \0
*
**************************************************************************/
#define UNICODE_VALUE_SIZE 58
-static const int unicode_value[UNICODE_VALUE_SIZE] = {-1 , -1 , '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', -1 , -1 ,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', -1 , -1 , 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', -1 /* FIXME */, -1 /* FIXME */, -1 , '\\', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', ',', '.', '/', -1, -1, -1, ' '};
+static const char unicode_value[UNICODE_VALUE_SIZE * 2] =
+ "\0\0" "\0\0" "1\0" "2\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" "0\0" "-\0" "=\0" "\0\0" "\0\0"
+ "Q\0" "W\0" "E\0" "R\0" "T\0" "Y\0" "U\0" "I\0" "O\0" "P\0" "{\0" "}\0" "\0\0" "\0\0" "A\0" "S\0"
+ "D\0" "F\0" "G\0" "H\0" "J\0" "K\0" "L\0" ";\0" "'\0" "\140\0" "\0\0" "\\\0" "Z\0" "X\0" "C\0" "V\0"
+ "B\0" "N\0" "M\0" "\0\0" ".\0" "/\0" "\0\0" "\0\0" "\0\0" " ";
-int CRCInput::getUnicodeValue(const neutrino_msg_t key)
+const char *CRCInput::getUnicodeValue(const neutrino_msg_t key)
{
if (key < UNICODE_VALUE_SIZE)
- return unicode_value[key];
- else
- return -1;
+ return unicode_value + key * 2;
+ return "";
}
/**************************************************************************
@@ -1524,20 +1527,6 @@ const char * CRCInput::getSpecialKeyName(const unsigned int key)
return "radio";
case RC_text:
return "text";
-#if 0
- case RC_shift_red:
- return "shift-red";
- case RC_shift_green:
- return "shift-green";
- case RC_shift_yellow:
- return "shift-yellow";
- case RC_shift_blue:
- return "shift-blue";
- case RC_shift_tv:
- return "shift-tv";
- case RC_shift_radio:
- return "shift-radio";
-#endif
case RC_epg:
return "epg";
case RC_recall:
@@ -1606,21 +1595,18 @@ const char * CRCInput::getSpecialKeyName(const unsigned int key)
std::string CRCInput::getKeyName(const unsigned int key)
{
- return (std::string)getKeyNameC(key);
+ std::string res(getKeyNameC(key & ~RC_Repeat));
+ if ((key & RC_Repeat) && res != "unknown")
+ res += " (long)";
+ return res;
}
const char *CRCInput::getKeyNameC(const unsigned int key)
{
- int lunicode_value = getUnicodeValue(key);
- if (lunicode_value == -1)
- return getSpecialKeyName(key);
- else
- {
- static char tmp[2];
- tmp[0] = lunicode_value;
- tmp[1] = 0;
- return tmp;
- }
+ const char *lunicode_value = getUnicodeValue(key);
+ if (*lunicode_value)
+ return lunicode_value;
+ return getSpecialKeyName(key);
}
/**************************************************************************
@@ -1631,9 +1617,9 @@ int CRCInput::translate(int code)
{
switch(code)
{
- case 0x100:
+ case 0x100: // FIXME -- needed?
return RC_up;
- case 0x101:
+ case 0x101: // FIXME -- needed?
return RC_down;
#ifdef HAVE_AZBOX_HARDWARE
case KEY_HOME:
diff --git a/src/driver/rcinput.h b/src/driver/rcinput.h
index b2015351f..99dc6f149 100644
--- a/src/driver/rcinput.h
+++ b/src/driver/rcinput.h
@@ -141,6 +141,9 @@ class CRCInput
uint32_t timerid;
std::vector timers;
+ uint32_t *repeatkeys;
+ uint64_t longPressEnd;
+ bool longPressAny;
int fd_pipe_high_priority[2];
int fd_pipe_low_priority[2];
int fd_gamerc;
@@ -155,7 +158,6 @@ class CRCInput
int fd_max;
int clickfd;
- bool firstKey;
__u16 rc_last_key;
void set_dsp();
@@ -164,6 +166,8 @@ class CRCInput
int translate(int code);
void calculateMaxFd(void);
int checkTimers();
+ bool mayRepeat(uint32_t key, bool bAllowRepeatLR = false);
+ bool mayLongPress(uint32_t key, bool bAllowRepeatLR = false);
#ifdef IOC_IR_SET_PRI_PROTOCOL
void set_rc_hw(ir_protocol_t ir_protocol, unsigned int ir_address);
#endif
@@ -290,7 +294,8 @@ class CRCInput
static bool isNumeric(const neutrino_msg_t key);
static int getNumericValue(const neutrino_msg_t key);
static unsigned int convertDigitToKey(const unsigned int digit);
- static int getUnicodeValue(const neutrino_msg_t key);
+ static const char *getUnicodeValue(const neutrino_msg_t key);
+ uint32_t *setAllowRepeat(uint32_t *);
static const char * getSpecialKeyName(const unsigned int key);
static const char *getKeyNameC(const unsigned int key);
@@ -317,6 +322,8 @@ class CRCInput
void close_click();
void play_click();
void reset_dsp(int rate);
+
+ void setLongPressAny(bool b) { longPressAny = b; };
};
diff --git a/src/driver/record.cpp b/src/driver/record.cpp
index 586545ee3..e91769897 100644
--- a/src/driver/record.cpp
+++ b/src/driver/record.cpp
@@ -97,7 +97,6 @@ CRecordInstance::CRecordInstance(const CTimerd::RecordingInfo * const eventinfo,
cMovieInfo = new CMovieInfo();
recMovieInfo = new MI_MOVIE_INFO();
record = NULL;
- tshift_mode = TSHIFT_MODE_OFF;
rec_stop_msg = g_Locale->getText(LOCALE_RECORDING_STOP);
}
@@ -260,6 +259,7 @@ bool CRecordInstance::Stop(bool remove_event)
hintBox.paint();
printf("%s: channel %" PRIx64 " recording_id %d\n", __func__, channel_id, recording_id);
+ printf("%s: file %s.ts\n", __FUNCTION__, filename);
SaveXml();
/* Stop do close fd - if started */
record->Stop();
@@ -450,15 +450,19 @@ record_error_msg_t CRecordInstance::Record()
//FIXME recording_id (timerd eventID) is 0 means its user recording, in this case timer always added ?
if(ret == RECORD_OK && recording_id == 0) {
time_t now = time(NULL);
- int record_end = now+g_settings.record_hours*60*60;
- if (g_settings.recording_epg_for_end)
- {
- int pre=0, post=0;
- CEPGData epgData;
- if (CEitManager::getInstance()->getActualEPGServiceKey(channel_id, &epgData )) {
- g_Timerd->getRecordingSafety(pre, post);
- if (epgData.epg_times.startzeit > 0)
- record_end = epgData.epg_times.startzeit + epgData.epg_times.dauer + post;
+ int record_end;
+ if (autoshift) {
+ record_end = now+g_settings.timeshift_hours*60*60;
+ } else {
+ record_end = now+g_settings.record_hours*60*60;
+ if (g_settings.recording_epg_for_end) {
+ int pre=0, post=0;
+ CEPGData epgData;
+ if (CEitManager::getInstance()->getActualEPGServiceKey(channel_id, &epgData )) {
+ g_Timerd->getRecordingSafety(pre, post);
+ if (epgData.epg_times.startzeit > 0)
+ record_end = epgData.epg_times.startzeit + epgData.epg_times.dauer + post;
+ }
}
}
recording_id = g_Timerd->addImmediateRecordTimerEvent(channel_id, now, record_end, epgid, epg_time, apidmode);
@@ -676,25 +680,13 @@ record_error_msg_t CRecordInstance::MakeFileName(CZapitChannel * channel)
strncat(filename, "_",FILENAMEBUFFERSIZE - strlen(filename)-1);
}
- pos = strlen(filename);
- if (g_settings.recording_epg_for_filename) {
- if(epgid != 0) {
- CShortEPGData epgdata;
- if(CEitManager::getInstance()->getEPGidShort(epgid, &epgdata)) {
- if (!(epgdata.title.empty())) {
- strcpy(&(filename[pos]), epgdata.title.c_str());
- ZapitTools::replace_char(&filename[pos]);
- }
- }
- } else if (!epgTitle.empty()) {
- strcpy(&(filename[pos]), epgTitle.c_str());
- ZapitTools::replace_char(&filename[pos]);
- }
- }
+ pos = strlen(filename) - ((!autoshift && g_settings.recording_save_in_channeldir) ? 0 : (ext_channel_name.length() /*remove last "_"*/ +1));
+
+ std::string ext_file_name = g_settings.recording_filename_template;
+ MakeExtFileName(channel, ext_file_name);
+ strcpy(&(filename[pos]), UTF8_TO_FILESYSTEM_ENCODING(ext_file_name.c_str()));
pos = strlen(filename);
- time_t t = time(NULL);
- pos += strftime(&(filename[pos]), sizeof(filename) - pos - 1, "%Y%m%d_%H%M%S", localtime(&t));
if(autoshift)
strncat(filename, "_temp",FILENAMEBUFFERSIZE - strlen(filename)-1);
@@ -702,6 +694,60 @@ record_error_msg_t CRecordInstance::MakeFileName(CZapitChannel * channel)
return RECORD_OK;
}
+void CRecordInstance::StringReplace(std::string &str, const std::string search, const std::string rstr)
+{
+ std::string::size_type ptr = 0;
+ std::string::size_type pos = 0;
+ while((ptr = str.find(search,pos)) != std::string::npos){
+ str.replace(ptr,search.length(),rstr);
+ pos = ptr + rstr.length();
+ }
+}
+
+void CRecordInstance::MakeExtFileName(CZapitChannel * channel, std::string &FilenameTemplate)
+{
+ char buf[256];
+
+ // %C == channel, %T == title, %I == info1, %d == date, %t == time_t
+ if (FilenameTemplate.empty())
+ FilenameTemplate = "%C_%T_%d_%t";
+
+ time_t t = time(NULL);
+ strftime(buf,sizeof(buf),"%Y%m%d",localtime(&t));
+ StringReplace(FilenameTemplate,"%d",buf);
+
+ strftime(buf,sizeof(buf),"%H%M%S",localtime(&t));
+ StringReplace(FilenameTemplate,"%t",buf);
+
+ std::string channel_name = channel->getName();
+ if (!(channel_name.empty())) {
+ strcpy(buf, UTF8_TO_FILESYSTEM_ENCODING(channel_name.c_str()));
+ ZapitTools::replace_char(buf);
+ StringReplace(FilenameTemplate,"%C",buf);
+ }
+ else
+ StringReplace(FilenameTemplate,"%C","no_channel");
+
+ CShortEPGData epgdata;
+ if(CEitManager::getInstance()->getEPGidShort(epgid, &epgdata)) {
+ if (!(epgdata.title.empty())) {
+ strcpy(buf, epgdata.title.c_str());
+ ZapitTools::replace_char(buf);
+ StringReplace(FilenameTemplate,"%T",buf);
+ }
+ else
+ StringReplace(FilenameTemplate,"%T","no_title");
+
+ if (!(epgdata.info1.empty())) {
+ strcpy(buf, epgdata.info1.c_str());
+ ZapitTools::replace_char(buf);
+ StringReplace(FilenameTemplate,"%I",buf);
+ }
+ else
+ StringReplace(FilenameTemplate,"%I","no_info");
+ }
+}
+
void CRecordInstance::GetRecordString(std::string &str, std::string &dur)
{
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id);
@@ -832,28 +878,6 @@ const std::string CRecordManager::GetFileName(t_channel_id channel_id, bool time
/* return record mode mask, for channel_id not 0, or global */
int CRecordManager::GetRecordMode(const t_channel_id channel_id)
{
-#if 0
- if (RecordingStatus(channel_id) || IsTimeshift(channel_id))
- {
- if (RecordingStatus(channel_id) && !IsTimeshift(channel_id))
- return RECMODE_REC;
- if (channel_id == 0)
- {
- int records = GetRecordCount();
- if (IsTimeshift(channel_id) && (records == 1))
- return RECMODE_TSHIFT;
- else if (IsTimeshift(channel_id) && (records > 1))
- return RECMODE_REC_TSHIFT;
- else
- return RECMODE_OFF;
- } else
- {
- if (IsTimeshift(channel_id))
- return RECMODE_TSHIFT;
- }
- }
- return RECMODE_OFF;
-#endif
int recmode = RECMODE_OFF;
mutex.lock();
if (channel_id == 0) {
@@ -913,10 +937,6 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
if (g_settings.recording_type == CNeutrinoApp::RECORDING_OFF)
return false;
-#if 0
- if(!CheckRecording(eventinfo))
- return false;
-#endif
#if 1 // FIXME test
StopSectionsd = false;
@@ -926,18 +946,6 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
RunStartScript();
mutex.lock();
-#if 0
- inst = FindInstance(eventinfo->channel_id);
- if(inst) {
- if(direct_record) {
- error_msg = RECORD_BUSY;
- } else {
- CTimerd::RecordingInfo * evt = new CTimerd::RecordingInfo(*eventinfo);
- printf("%s add %llx : %s to pending\n", __FUNCTION__, evt->channel_id, evt->epgTitle);
- nextmap.push_back((CTimerd::RecordingInfo *)evt);
- }
- } else
-#endif
if(recmap.size() < RECORD_MAX_COUNT) {
CFrontend * frontend = NULL;
if(CutBackNeutrino(eventinfo->channel_id, frontend)) {
@@ -1034,18 +1042,6 @@ bool CRecordManager::StopAutoRecord(bool lock)
return (inst != NULL);
}
-#if 0
-bool CRecordManager::CheckRecording(const CTimerd::RecordingInfo * const eventinfo)
-{
- t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
- /* FIXME check if frontend used for timeshift the same and will zap ?? */
- if(/*(eventinfo->channel_id == live_channel_id) ||*/ !SAME_TRANSPONDER(eventinfo->channel_id, live_channel_id))
- StopAutoRecord();
-
- return true;
-}
-#endif
-
void CRecordManager::StartNextRecording()
{
CTimerd::RecordingInfo * eventinfo = NULL;
@@ -1053,25 +1049,6 @@ void CRecordManager::StartNextRecording()
for(nextmap_iterator_t it = nextmap.begin(); it != nextmap.end(); it++) {
eventinfo = *it;
-#if 0
- bool tested = true;
- if( !recmap.empty() ) {
- CRecordInstance * inst = FindInstance(eventinfo->channel_id);
- /* same channel recording and not auto - skip */
- if(inst && !inst->Timeshift())
- tested = false;
- /* there is only auto-record which can be stopped */
- else if(recmap.size() == 1 && autoshift)
- tested = true;
- else {
- /* there are some recordings, test any (first) for now */
- recmap_iterator_t fit = recmap.begin();
- t_channel_id channel_id = fit->second->GetChannelId();
- tested = (SAME_TRANSPONDER(channel_id, eventinfo->channel_id));
- }
- }
- if(tested)
-#endif
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id);
if (channel && CFEManager::getInstance()->canTune(channel))
{
@@ -1140,11 +1117,6 @@ void CRecordManager::StopInstance(CRecordInstance * inst, bool remove_event)
if(inst->Timeshift())
autoshift = false;
-#if 0
- t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
- if(inst->GetChannelId() == live_channel_id)
- recordingstatus = 0;
-#endif
delete inst;
}
@@ -1278,47 +1250,6 @@ int CRecordManager::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data
return messages_return::unhandled;
}
-#if 0
-bool CRecordManager::IsTimeshift(t_channel_id channel_id)
-{
- bool ret = false;
- CRecordInstance * inst;
- mutex.lock();
- if (channel_id != 0)
- {
- inst = FindInstance(channel_id);
- if(inst && inst->tshift_mode)
- ret = true;
- else
- ret = false;
- } else
- {
- for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
- {
- if(it->second->tshift_mode)
- {
- mutex.unlock();
- return true;
- }
- }
- }
- mutex.unlock();
- return ret;
-}
-
-void CRecordManager::SetTimeshiftMode(CRecordInstance * inst, int mode)
-{
- mutex.lock();
- /* reset all instances mode ? */
- for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
- it->second->tshift_mode = TSHIFT_MODE_OFF;
-
- mutex.unlock();
- if (inst)
- inst->tshift_mode = mode;
-}
-#endif
-
void CRecordManager::StartTimeshift()
{
if(g_RemoteControl->is_video_started)
@@ -1326,26 +1257,6 @@ void CRecordManager::StartTimeshift()
std::string tmode = "ptimeshift"; // already recording, pause
bool res = true;
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
-#if 0
- if(RecordingStatus(live_channel_id))
- {
- tmode = "ptimeshift"; // already recording, pause
- if(GetRecordMode(live_channel_id) == RECMODE_TSHIFT)
- SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PAUSE);
- } else
- {
- if(g_settings.temp_timeshift)
- {
- res = StartAutoRecord();
- SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_TEMPORAER);
- } else
- {
- res = Record(live_channel_id);
- SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PERMANET);
- }
- tmode = "timeshift"; // record just started
- }
-#endif
/* start temporary timeshift if enabled and not running, but dont start second record */
if (g_settings.temp_timeshift) {
if (!FindTimeshift()) {
@@ -1427,10 +1338,6 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
return menu_return::RETURN_EXIT_ALL;
}
-#if 0
- else
- DisplayInfoMessage(g_Locale->getText(LOCALE_RECORDING_IS_RUNNING));
-#endif
} else if(actionKey == "Timeshift")
{
StartTimeshift();
@@ -1497,7 +1404,6 @@ bool CRecordManager::ShowMenu(void)
durations.push_back(duration);
const char* mode_icon = NEUTRINO_ICON_REC;
- //if (inst->tshift_mode)
if (inst->Timeshift())
mode_icon = NEUTRINO_ICON_AUTO_SHIFT;
@@ -1551,7 +1457,6 @@ bool CRecordManager::ShowMenu(void)
bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
{
- //int recording_id = 0;
std::string title, duration;
CRecordInstance * inst;
@@ -1562,7 +1467,6 @@ bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
inst = FindInstance(channel_id);
if(inst) {
- //recording_id = inst->GetRecordingId();
inst->GetRecordString(title, duration);
title += duration;
}
@@ -1572,9 +1476,6 @@ bool CRecordManager::AskToStop(const t_channel_id channel_id, const int recid)
if(ShowMsg(LOCALE_SHUTDOWN_RECODING_QUERY, title.c_str(),
CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbNo, NULL, 450, 30, false) == CMessageBox::mbrYes) {
-#if 0
- g_Timerd->stopTimerEvent(recording_id);
-#endif
mutex.lock();
if (recid)
inst = FindInstanceID(recid);
diff --git a/src/driver/record.h b/src/driver/record.h
index ca2c7b539..eb69837cf 100644
--- a/src/driver/record.h
+++ b/src/driver/record.h
@@ -82,6 +82,7 @@ class CRecordInstance
t_channel_id channel_id;
event_id_t epgid;
std::string epgTitle;
+ std::string epgInfo1;
unsigned char apidmode;
time_t epg_time;
time_t start_time;
@@ -110,7 +111,9 @@ class CRecordInstance
bool SaveXml();
record_error_msg_t Start(CZapitChannel * channel);
void WaitRecMsg(time_t StartTime, time_t WaitTime);
- public:
+ void MakeExtFileName(CZapitChannel * channel, std::string &FilenameTemplate);
+ void StringReplace(std::string &str, const std::string search, const std::string rstr);
+ public:
CRecordInstance(const CTimerd::RecordingInfo * const eventinfo, std::string &dir, bool timeshift = false, bool stream_vtxt_pid = false, bool stream_pmt_pid = false, bool stream_subtitle_pids = false);
~CRecordInstance();
@@ -166,14 +169,12 @@ class CRecordManager : public CMenuTarget /*, public CChangeObserver*/
bool CutBackNeutrino(const t_channel_id channel_id, CFrontend * &frontend);
void RestoreNeutrino(void);
- bool CheckRecording(const CTimerd::RecordingInfo * const eventinfo);
void StartNextRecording();
void StopPostProcess();
void StopInstance(CRecordInstance * inst, bool remove_event = true);
CRecordInstance * FindInstance(t_channel_id);
CRecordInstance * FindInstanceID(int recid);
CRecordInstance * FindTimeshift();
- //void SetTimeshiftMode(CRecordInstance * inst=NULL, int mode=TSHIFT_MODE_OFF);
public:
enum record_modes_t
@@ -228,7 +229,6 @@ class CRecordManager : public CMenuTarget /*, public CChangeObserver*/
CRecordInstance* getRecordInstance(std::string file);
// old code
#if 0
- bool IsTimeshift(t_channel_id channel_id=0);
bool MountDirectory(const char *recordingDir);
bool ChooseRecDir(std::string &dir);
int recordingstatus;
diff --git a/src/driver/scanepg.cpp b/src/driver/scanepg.cpp
index a2bd09bc6..db30ed3f1 100644
--- a/src/driver/scanepg.cpp
+++ b/src/driver/scanepg.cpp
@@ -37,11 +37,13 @@
#include
#include
+#include
#define EPG_RESCAN_TIME (24*60*60)
extern CBouquetList * bouquetList;
extern CBouquetList * TVfavList;
+extern CBouquetList * TVbouquetList;
CEpgScan::CEpgScan()
{
@@ -71,11 +73,12 @@ void CEpgScan::Clear()
current_bmode = -1;
next_chid = 0;
allfav_done = false;
+ selected_done = false;
}
bool CEpgScan::Running()
{
- return (g_settings.epg_scan && !scanmap.empty());
+ return (CheckMode() && !scanmap.empty());
}
void CEpgScan::AddBouquet(CChannelList * clist)
@@ -90,7 +93,7 @@ void CEpgScan::AddBouquet(CChannelList * clist)
bool CEpgScan::AddFavorites()
{
INFO("allfav_done: %d", allfav_done);
- if ((g_settings.epg_scan != 2) || allfav_done)
+ if ((g_settings.epg_scan != SCAN_FAV) || allfav_done)
return false;
allfav_done = true;
@@ -103,6 +106,30 @@ bool CEpgScan::AddFavorites()
return (old_size != scanmap.size());
}
+bool CEpgScan::AddSelected()
+{
+ INFO("selected_done: %d", selected_done);
+ if ((g_settings.epg_scan != SCAN_SEL) || selected_done)
+ return false;
+
+ selected_done = true;
+ unsigned old_size = scanmap.size();
+ for (unsigned j = 0; j < TVfavList->Bouquets.size(); ++j) {
+ if (TVfavList->Bouquets[j]->zapitBouquet && TVfavList->Bouquets[j]->zapitBouquet->bScanEpg) {
+ CChannelList * clist = TVfavList->Bouquets[j]->channelList;
+ AddBouquet(clist);
+ }
+ }
+ for (unsigned j = 0; j < TVbouquetList->Bouquets.size(); ++j) {
+ if (TVbouquetList->Bouquets[j]->zapitBouquet && TVbouquetList->Bouquets[j]->zapitBouquet->bScanEpg) {
+ CChannelList * clist = TVbouquetList->Bouquets[j]->channelList;
+ AddBouquet(clist);
+ }
+ }
+ INFO("scan map size: %d -> %d\n", old_size, scanmap.size());
+ return (old_size != scanmap.size());
+}
+
void CEpgScan::AddTransponders()
{
if(bouquetList->Bouquets.empty())
@@ -114,7 +141,25 @@ void CEpgScan::AddTransponders()
}
int mode = CNeutrinoApp::getInstance()->GetChannelMode();
- if ((g_settings.epg_scan == 1) || (mode == LIST_MODE_FAV)) {
+ if (g_settings.epg_scan == SCAN_SEL) {
+ if (current_bmode != mode) {
+ current_bmode = mode;
+ current_bnum = -1;
+ }
+ int bnum = bouquetList->getActiveBouquetNumber();
+ bool bscan = bouquetList->Bouquets[bnum]->zapitBouquet &&
+ bouquetList->Bouquets[bnum]->zapitBouquet->bScanEpg;
+
+ if ((current_bnum != bnum) && bscan) {
+ current_bnum = bnum;
+ AddBouquet(bouquetList->Bouquets[current_bnum]->channelList);
+ } else {
+ AddSelected();
+ }
+ return;
+ }
+
+ if ((g_settings.epg_scan == SCAN_CURRENT) || (mode == LIST_MODE_FAV)) {
/* current bouquet mode */
if (current_bmode != mode) {
current_bmode = mode;
@@ -132,17 +177,23 @@ void CEpgScan::AddTransponders()
}
}
+bool CEpgScan::CheckMode()
+{
+ if (!g_settings.epg_scan
+ || (standby && !(g_settings.epg_scan_mode & MODE_STANDBY))
+ || (!standby && !(g_settings.epg_scan_mode & MODE_LIVE))
+ || (!standby && (CFEManager::getInstance()->getEnabledCount() <= 1))) {
+ return false;
+ }
+ return true;
+
+}
+
void CEpgScan::Start(bool instandby)
{
- if (!g_settings.epg_scan)
- return;
- if (!instandby && (CFEManager::getInstance()->getEnabledCount() <= 1))
- return;
-
+ standby = instandby;
live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
AddTransponders();
- standby = instandby;
- //g_RCInput->killTimer(rescan_timer);
INFO("starting %s scan, scanning %d, scan map size: %d", standby ? "standby" : "live", scan_in_progress, scanmap.size());
if (standby || !scan_in_progress)
Next();
@@ -167,14 +218,16 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data)
scanned.clear();
Clear();
g_RCInput->killTimer(rescan_timer);
- if (standby || (CFEManager::getInstance()->getEnabledCount() > 1)) {
+ if (CheckMode()) {
if (standby)
- g_Zapit->setStandby(false);
+ CNeutrinoApp::getInstance()->wakeupFromStandby();
Start(standby);
+ } else {
+ AddTimer();
}
return messages_return::handled;
}
- if (!g_settings.epg_scan || (!standby && (CFEManager::getInstance()->getEnabledCount() <= 1))) {
+ if (!CheckMode()) {
int ret = messages_return::handled;
if (msg == NeutrinoMessages::EVT_EIT_COMPLETE)
scan_in_progress = false;
@@ -232,36 +285,44 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data)
return messages_return::unhandled;
}
-void CEpgScan::EnterStandby()
+void CEpgScan::AddTimer()
{
- if (standby) {
- CZapit::getInstance()->SetCurrentChannelID(live_channel_id);
- //CZapit::getInstance()->EnablePlayback(true);
- g_Zapit->setStandby(true);
- g_Sectionsd->setPauseScanning(true);
- }
- //g_RCInput->killTimer(rescan_timer);
if (rescan_timer == 0)
rescan_timer = g_RCInput->addTimer(EPG_RESCAN_TIME*1000ULL*1000ULL, true);
INFO("rescan timer id %d", rescan_timer);
}
+void CEpgScan::EnterStandby()
+{
+ AddTimer();
+ if (standby) {
+ CZapit::getInstance()->SetCurrentChannelID(live_channel_id);
+ CNeutrinoApp::getInstance()->standbyToStandby();
+ }
+}
+
void CEpgScan::Next()
{
bool locked = false;
next_chid = 0;
+#if 0
if (!g_settings.epg_scan)
return;
+ if (!CheckMode())
+ return;
+#endif
if (!standby && CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby)
return;
- if (CRecordManager::getInstance()->RecordingStatus())
+ if (CRecordManager::getInstance()->RecordingStatus() || CStreamManager::getInstance()->StreamStatus())
return;
- if (g_settings.epg_scan == 2 && scanmap.empty())
+ if (g_settings.epg_scan == SCAN_FAV && scanmap.empty())
AddFavorites();
+ if (g_settings.epg_scan == SCAN_SEL && scanmap.empty())
+ AddSelected();
- if (scanmap.empty()) {
+ if (!CheckMode() || scanmap.empty()) {
EnterStandby();
return;
}
@@ -299,7 +360,9 @@ _repeat:
INFO("skip [%s], cannot tune", newchan->getName().c_str());
++it;
}
- if (!next_chid && AddFavorites())
+ if (!next_chid && ((g_settings.epg_scan == SCAN_FAV) && AddFavorites()))
+ goto _repeat;
+ if (!next_chid && ((g_settings.epg_scan == SCAN_SEL) && AddSelected()))
goto _repeat;
if (locked) {
diff --git a/src/driver/scanepg.h b/src/driver/scanepg.h
index 07057494e..989e2a63b 100644
--- a/src/driver/scanepg.h
+++ b/src/driver/scanepg.h
@@ -28,11 +28,24 @@ typedef eit_scanmap_t::iterator eit_scanmap_iterator_t;
class CEpgScan
{
+ public:
+ enum {
+ SCAN_OFF,
+ SCAN_CURRENT,
+ SCAN_FAV,
+ SCAN_SEL
+ };
+ enum {
+ MODE_LIVE = 0x1,
+ MODE_STANDBY = 0x2,
+ MODE_ALWAYS = 0x3
+ };
private:
int current_bnum;
int current_mode;
int current_bmode;
bool allfav_done;
+ bool selected_done;
bool standby;
eit_scanmap_t scanmap;
t_channel_id next_chid;
@@ -43,8 +56,11 @@ class CEpgScan
void AddBouquet(CChannelList * clist);
bool AddFavorites();
+ bool AddSelected();
void AddTransponders();
void EnterStandby();
+ bool CheckMode();
+ void AddTimer();
CEpgScan();
public:
diff --git a/src/driver/streamts.cpp b/src/driver/streamts.cpp
index 857a4f4fc..4e66460a2 100644
--- a/src/driver/streamts.cpp
+++ b/src/driver/streamts.cpp
@@ -1,9 +1,7 @@
/*
Neutrino-GUI - DBoxII-Project
- Copyright (C) 2011-2012 CoolStream International Ltd
-
- Copyright (C) 2010-2012, 2014 Stefan Seyfried
+ Copyright (C) 2011-2014 CoolStream International Ltd
based on code which is
Copyright (C) 2002 Andreas Oberritter
@@ -58,17 +56,12 @@
#include
#include
#include
-#include
-
-/* defined in neutrino.cpp */
-extern cCpuFreqManager * cpuFreq;
/* experimental mode:
* stream not possible, if record running
* pids in url ignored, and added from channel, with fake PAT/PMT
- * different channels supported, only from the same transponder - no zap is done,
+ * different channels supported,
* with url like http://coolstream:31339/id=c32400030070283e (channel id)
- * TODO: multi-tuner support
*/
#define ENABLE_MULTI_CHANNEL
@@ -120,23 +113,28 @@ bool CStreamInstance::Stop()
bool CStreamInstance::Send(ssize_t r)
{
+ //OpenThreads::ScopedLock m_lock(mutex);
+ stream_fds_t cfds;
mutex.lock();
- for (stream_fds_t::iterator it = fds.begin(); it != fds.end(); ++it) {
- int ret, i = 10;
- do {
- ret = send(*it, buf, r, MSG_DONTWAIT);
-#if 0
- if (ret != r)
- usleep(100);
-#endif
- } while ((ret != r) && (i-- > 0));
- if (ret != r) {
- if (r < 0)
- perror("send");
- printf("send err, fd %d: (%d from %d)\n", *it, ret, (int)r);
- }
- }
+ cfds = fds;
mutex.unlock();
+ int flags = 0;
+ if (cfds.size() > 1)
+ flags = MSG_DONTWAIT;
+ for (stream_fds_t::iterator it = cfds.begin(); it != cfds.end(); ++it) {
+ int i = 10;
+ unsigned char *b = buf;
+ ssize_t count = r;
+ do {
+ int ret = send(*it, b, count, flags);
+ if (ret > 0) {
+ b += ret;
+ count -= ret;
+ }
+ } while ((count > 0) && (i-- > 0));
+ if (count)
+ printf("send err, fd %d: (%d from %d)\n", *it, r-count, r);
+ }
return true;
}
@@ -149,35 +147,23 @@ void CStreamInstance::Close()
void CStreamInstance::AddClient(int clientfd)
{
- mutex.lock();
+ OpenThreads::ScopedLock m_lock(mutex);
fds.insert(clientfd);
printf("CStreamInstance::AddClient: %d (count %d)\n", clientfd, (int)fds.size());
- mutex.unlock();
}
void CStreamInstance::RemoveClient(int clientfd)
{
- mutex.lock();
+ OpenThreads::ScopedLock m_lock(mutex);
fds.erase(clientfd);
close(clientfd);
printf("CStreamInstance::RemoveClient: %d (count %d)\n", clientfd, (int)fds.size());
- mutex.unlock();
}
void CStreamInstance::run()
{
printf("CStreamInstance::run: %" PRIx64 "\n", channel_id);
-#if 0
-// TODO: check if this works... #ifndef HAVE_COOL_HARDWARE
- /* right now, only one stream is possible anyway and it is not possible
- * to stream a different channel than the live channel AFAICT, so we can
- * as well use the live demux */
- dmx = new cDemux(0);
-#endif
-#if 0
- dmx = new cDemux(STREAM_DEMUX);//FIXME
-#endif
CZapitChannel * tmpchan = CServiceManager::getInstance()->FindChannel(channel_id);
if (!tmpchan)
return;
@@ -204,7 +190,7 @@ void CStreamInstance::run()
while (running) {
ssize_t r = dmx->Read(buf, IN_SIZE, 100);
- if(r > 0)
+ if (r > 0)
Send(r);
}
@@ -265,7 +251,10 @@ bool CStreamManager::Stop()
if (!running)
return false;
running = false;
- return (OpenThreads::Thread::join() == 0);
+ cancel();
+ bool ret = (OpenThreads::Thread::join() == 0);
+ StopAll();
+ return ret;
}
bool CStreamManager::SetPort(int newport)
@@ -286,13 +275,83 @@ bool CStreamManager::SetPort(int newport)
return ret;
}
-bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
+CFrontend * CStreamManager::FindFrontend(CZapitChannel * channel)
+{
+ std::set frontends;
+ CFrontend * frontend = NULL;
+
+ t_channel_id chid = channel->getChannelID();
+ if (CRecordManager::getInstance()->RecordingStatus(chid)) {
+ printf("CStreamManager::Parse: channel %llx recorded, aborting..\n", chid);
+ return frontend;
+ }
+
+ t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
+ CFrontend *live_fe = CZapit::getInstance()->GetLiveFrontend();
+
+ if (live_channel_id == chid)
+ return live_fe;
+
+ CFEManager::getInstance()->Lock();
+
+ bool unlock = true;
+ CFEManager::getInstance()->lockFrontend(live_fe);
+
+ OpenThreads::ScopedLock m_lock(mutex);
+ for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it)
+ frontends.insert(it->second->frontend);
+
+ for (std::set::iterator ft = frontends.begin(); ft != frontends.end(); ft++)
+ CFEManager::getInstance()->lockFrontend(*ft);
+
+ frontend = CFEManager::getInstance()->allocateFE(channel, true);
+
+ if (frontend == NULL) {
+ unlock = false;
+ CFEManager::getInstance()->unlockFrontend(live_fe);
+ frontend = CFEManager::getInstance()->allocateFE(channel, true);
+ }
+
+ CFEManager::getInstance()->Unlock();
+
+ if (frontend) {
+ bool found = (live_fe != frontend) || SAME_TRANSPONDER(live_channel_id, chid);
+ bool ret = false;
+ if (found)
+ ret = zapit.zapTo_record(chid) > 0;
+ else
+ ret = zapit.zapTo_serviceID(chid) > 0;
+
+ if (ret) {
+#ifdef ENABLE_PIP
+ /* FIXME until proper demux management */
+ t_channel_id pip_channel_id = CZapit::getInstance()->GetPipChannelID();
+ if ((pip_channel_id == chid) && (channel->getRecordDemux() == channel->getPipDemux()))
+ zapit.stopPip();
+#endif
+ } else {
+ frontend = NULL;
+ }
+ }
+
+ CFEManager::getInstance()->Lock();
+ for (std::set::iterator ft = frontends.begin(); ft != frontends.end(); ft++)
+ CFEManager::getInstance()->unlockFrontend(*ft);
+
+ if (unlock)
+ CFEManager::getInstance()->unlockFrontend(live_fe);
+
+ CFEManager::getInstance()->Unlock();
+ return frontend;
+}
+
+bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFrontend * &frontend)
{
char cbuf[512];
char *bp;
FILE * fp = fdopen(fd, "r+");
- if(fp == NULL) {
+ if (fp == NULL) {
perror("fdopen");
return false;
}
@@ -303,7 +362,7 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
while (bp - &cbuf[0] < (int) sizeof(cbuf)) {
unsigned char c;
int res = read(fd, &c, 1);
- if(res < 0) {
+ if (res < 0) {
perror("read");
return false;
}
@@ -326,74 +385,54 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
return false;
}
+ chid = CZapit::getInstance()->GetCurrentChannelID();
+ CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel();
+
#ifndef ENABLE_MULTI_CHANNEL
/* parse stdin / url path, start dmx filters */
do {
int pid;
int res = sscanf(bp, "%x", &pid);
- if(res == 1) {
- printf("New pid: 0x%x\n", pid);
+ if (res == 1) {
+ printf("CStreamManager::Parse: pid: 0x%x\n", pid);
pids.insert(pid);
}
+ } while ((bp = strchr(bp, ',')) && (bp++));
+#else
+ t_channel_id tmpid;
+ bp = &cbuf[5];
+ if (sscanf(bp, "id=%llx", &tmpid) == 1) {
+ channel = CServiceManager::getInstance()->FindChannel(tmpid);
+ chid = tmpid;
}
- while ((bp = strchr(bp, ',')) && (bp++));
#endif
+ if (!channel)
+ return false;
- chid = CZapit::getInstance()->GetCurrentChannelID();
- CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel();
+ printf("CStreamManager::Parse: channel_id %llx [%s]\n", chid, channel->getName().c_str());
- int mode = CNeutrinoApp::getInstance()->getMode();
- if (mode == NeutrinoMessages::mode_standby && streams.empty()) {
- printf("CStreamManager::Parse: wakeup zapit..\n");
- cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000);
- g_Zapit->setStandby(false);
- g_Zapit->getMode();
+ frontend = FindFrontend(channel);
+ if (!frontend) {
+ printf("CStreamManager::Parse: no free frontend\n");
+ return false;
}
- if(pids.empty()) {
-#ifdef ENABLE_MULTI_CHANNEL
- t_channel_id tmpid;
- bp = &cbuf[5];
- if (sscanf(bp, "id=%" SCNx64, &tmpid) == 1) {
- printf("############################# channel_id %" PRIx64 "\n", tmpid);
- CZapitChannel * tmpchan = CServiceManager::getInstance()->FindChannel(tmpid);
- /* we may switch channels if neutrino is in standby and we are not recording
- * the current channel TODO: check interaction with recording */
- bool may_switch =
- (CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby) &&
- !CRecordManager::getInstance()->RecordingStatus(chid);
- if (tmpchan && (tmpid != chid) && (may_switch || SAME_TRANSPONDER(tmpid, chid))) {
- printf("############################# channel_id %" PRIx64 " -> zap\n", tmpid);
- bool ret = g_Zapit->zapTo_record(tmpid) > 0;
- if (ret) {
- channel = tmpchan;
- chid = tmpid;
- }
- }
- }
- if(CRecordManager::getInstance()->RecordingStatus(chid)) {
- printf("CStreamManager::Parse: channel %" PRIx64 " recorded, aborting..\n", chid);
- return false;
- }
-#ifdef ENABLE_PIP
- t_channel_id pip_channel_id = CZapit::getInstance()->GetPipChannelID();
- if ((chid == pip_channel_id) && (channel->getRecordDemux() == channel->getPipDemux())) {
- printf("CStreamManager::Parse: channel %llx used for pip, aborting..\n", chid);
- return false;
- }
-#endif
-#endif
+ AddPids(fd, channel, pids);
- printf("CStreamManager::Parse: no pids in url, using channel %" PRIx64 " pids\n", chid);
- if(!channel)
- return false;
- //pids.insert(0);
- //pids.insert(channel->getPmtPid());
- pids.insert(channel->getVideoPid());
+ return !pids.empty();
+}
+
+void CStreamManager::AddPids(int fd, CZapitChannel *channel, stream_pids_t &pids)
+{
+ if (pids.empty()) {
+ printf("CStreamManager::AddPids: no pids in url, using channel %llx pids\n", channel->getChannelID());
+ if (channel->getVideoPid())
+ pids.insert(channel->getVideoPid());
for (int i = 0; i < channel->getAudioChannelCount(); i++)
pids.insert(channel->getAudioChannel(i)->pid);
}
+
CGenPsi psi;
for (stream_pids_t::iterator it = pids.begin(); it != pids.end(); ++it) {
if (*it == channel->getVideoPid()) {
@@ -404,9 +443,9 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
if (*it == channel->getAudioChannel(i)->pid) {
CZapitAudioChannel::ZapitAudioChannelType atype = channel->getAudioChannel(i)->audioChannelType;
printf("CStreamManager::Parse: genpsi apid %x (%d)\n", *it, atype);
- if(channel->getAudioChannel(i)->audioChannelType == CZapitAudioChannel::EAC3){
+ if (channel->getAudioChannel(i)->audioChannelType == CZapitAudioChannel::EAC3) {
psi.addPid(*it, EN_TYPE_AUDIO_EAC3, atype, channel->getAudioChannel(i)->description.c_str());
- }else{
+ } else {
psi.addPid(*it, EN_TYPE_AUDIO, atype, channel->getAudioChannel(i)->description.c_str());
}
}
@@ -414,43 +453,85 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid)
}
}
//add pcr pid
- if(channel->getPcrPid() != channel->getVideoPid()){
+ if (channel->getPcrPid() && (channel->getPcrPid() != channel->getVideoPid())) {
pids.insert(channel->getPcrPid());
psi.addPid(channel->getPcrPid(), EN_TYPE_PCR, 0);
}
//add teletext pid
- if (g_settings.recording_stream_vtxt_pid && channel->getTeletextPid() != 0){
+ if (g_settings.recording_stream_vtxt_pid && channel->getTeletextPid() != 0) {
pids.insert(channel->getTeletextPid());
psi.addPid(channel->getTeletextPid(), EN_TYPE_TELTEX, 0, channel->getTeletextLang());
}
//add dvb sub pid
- if (g_settings.recording_stream_subtitle_pids){
+ if (g_settings.recording_stream_subtitle_pids) {
for (int i = 0 ; i < (int)channel->getSubtitleCount() ; ++i) {
CZapitAbsSub* s = channel->getChannelSub(i);
if (s->thisSubType == CZapitAbsSub::DVB) {
- if(i>9)//max sub pids
+ if (i>9)//max sub pids
break;
CZapitDVBSub* sd = reinterpret_cast(s);
pids.insert(sd->pId);
- psi.addPid( sd->pId, EN_TYPE_DVBSUB, 0, sd->ISO639_language_code.c_str() );
+ psi.addPid(sd->pId, EN_TYPE_DVBSUB, 0, sd->ISO639_language_code.c_str());
}
}
-
}
psi.genpsi(fd);
+}
- return !pids.empty();
+bool CStreamManager::AddClient(int connfd)
+{
+ stream_pids_t pids;
+ t_channel_id channel_id;
+ CFrontend *frontend;
+
+ if (Parse(connfd, pids, channel_id, frontend)) {
+ OpenThreads::ScopedLock m_lock(mutex);
+ streammap_iterator_t it = streams.find(channel_id);
+ if (it != streams.end()) {
+ it->second->AddClient(connfd);
+ } else {
+ CStreamInstance * stream = new CStreamInstance(connfd, channel_id, pids);
+ stream->frontend = frontend;
+
+ int sendsize = 10*IN_SIZE;
+ unsigned int m = sizeof(sendsize);
+ setsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, m);
+ if (stream->Start())
+ streams.insert(streammap_pair_t(channel_id, stream));
+ else
+ delete stream;
+ }
+ return true;
+ }
+ return false;
+}
+
+void CStreamManager::RemoveClient(int fd)
+{
+ OpenThreads::ScopedLock m_lock(mutex);
+ for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it) {
+ if (it->second->HasFd(fd)) {
+ CStreamInstance *stream = it->second;
+ stream->RemoveClient(fd);
+ if (stream->GetFds().empty()) {
+ streams.erase(stream->GetChannelId());
+ delete stream;
+ }
+ break;
+ }
+ }
}
void CStreamManager::run()
{
struct sockaddr_in servaddr;
- int clilen = sizeof(servaddr);;
+ int clilen = sizeof(servaddr);
struct pollfd pfd[128];
int poll_cnt;
+ int poll_timeout = -1;
printf("Starting STREAM thread keeper, tid %ld\n", syscall(__NR_gettid));
@@ -471,67 +552,36 @@ void CStreamManager::run()
}
mutex.unlock();
//printf("polling, count= %d\n", poll_cnt);
- int pollres = poll (pfd, poll_cnt, 1000);
- if (pollres < 0) {
- perror("CStreamManager::run(): poll");
+ int pollres = poll (pfd, poll_cnt, poll_timeout);
+ if (pollres <= 0) {
+ if (pollres < 0)
+ perror("CStreamManager::run(): poll");
continue;
}
- if(pollres == 0)
- continue;
for (int i = poll_cnt - 1; i >= 0; i--) {
if (pfd[i].revents & (POLLIN | POLLPRI | POLLHUP | POLLRDHUP)) {
printf("fd %d has events %x\n", pfd[i].fd, pfd[i].revents);
if (pfd[i].fd == listenfd) {
- int connfd = accept (listenfd, (struct sockaddr *) &servaddr, (socklen_t *) & clilen);
+ int connfd = accept(listenfd, (struct sockaddr *) &servaddr, (socklen_t *) & clilen);
printf("CStreamManager::run(): connection, fd %d\n", connfd);
- if(connfd < 0) {
+ if (connfd < 0) {
perror("CStreamManager::run(): accept");
continue;
}
- stream_pids_t pids;
- t_channel_id channel_id;
- if (Parse(connfd, pids, channel_id)) {
- mutex.lock();
- streammap_iterator_t it = streams.find(channel_id);
- if (it != streams.end()) {
- it->second->AddClient(connfd);
- } else {
- CStreamInstance * stream = new CStreamInstance(connfd, channel_id, pids);
- if (stream->Start())
- streams.insert(streammap_pair_t(channel_id, stream));
- else
- delete stream;
- }
- mutex.unlock();
- } else {
+#if 0
+ if (!AddClient(connfd))
close(connfd);
- }
+#endif
+ g_RCInput->postMsg(NeutrinoMessages::EVT_STREAM_START, connfd);
+ poll_timeout = 1000;
} else {
if (pfd[i].revents & (POLLHUP | POLLRDHUP)) {
printf("CStreamManager::run(): POLLHUP, fd %d\n", pfd[i].fd);
- mutex.lock();
- for (streammap_iterator_t it = streams.begin(); it != streams.end(); ++it) {
- if (it->second->HasFd(pfd[i].fd)) {
- CStreamInstance *stream = it->second;
- stream->RemoveClient(pfd[i].fd);
- if (stream->GetFds().empty()) {
- streams.erase(stream->GetChannelId());
- delete stream;
- }
- break;
- }
+ RemoveClient(pfd[i].fd);
+ if (streams.empty()) {
+ poll_timeout = -1;
+ g_RCInput->postMsg(NeutrinoMessages::EVT_STREAM_STOP, 0);
}
- mutex.unlock();
- }
- }
- /* this is a cheap check */
- if (streams.empty() &&
- CNeutrinoApp::getInstance()->getMode() == NeutrinoMessages::mode_standby) {
- /* this check is more expensive (goes through the socket) */
- if (g_Zapit->getMode() != 0) {
- printf("CStreamManager::run: put zapit into standby...\n");
- g_Zapit->setStandby(true);
- cpuFreq->SetCpuFreq(g_settings.standby_cpufreq * 1000 * 1000);
}
}
}
@@ -588,8 +638,6 @@ bool CStreamManager::Listen()
{
struct sockaddr_in socketAddr;
int socketOptActive = 1;
- int sendsize = 10*IN_SIZE;
- unsigned int m = sizeof(sendsize);
if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf (stderr, "network port %u open: ", port);
@@ -619,12 +667,7 @@ bool CStreamManager::Listen()
goto _error;
}
-#if 1
- setsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, m);
- sendsize = 0;
- getsockopt(listenfd, SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, &m);
- printf("CStreamManager::Listen: on %d, fd %d (%d)\n", port, listenfd, sendsize);
-#endif
+ printf("CStreamManager::Listen: on %d, fd %d\n", port, listenfd);
return true;
_error:
close (listenfd);
diff --git a/src/driver/streamts.h b/src/driver/streamts.h
index 9b10ddeca..e1a6915a1 100644
--- a/src/driver/streamts.h
+++ b/src/driver/streamts.h
@@ -27,6 +27,7 @@
#include
#include
+#include
#include
#include