diff --git a/.gitignore b/.gitignore index 1ab909897..16493bc12 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ INSTALL .libs .deps *.o +*.so *.lo *.a *.la diff --git a/Makefile.am b/Makefile.am index 1356a4690..3f904ffde 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,6 @@ AUTOMAKE_OPTIONS = gnu SUBDIRS = lib src data + +locale-update: + make -C $(top_builddir)/data/locale install-locals diff --git a/acinclude.m4 b/acinclude.m4 index 0e7958dfa..4eea0e04a 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -11,7 +11,7 @@ AC_ARG_WITH(target, AC_ARG_WITH(targetprefix, [ --with-targetprefix=PATH prefix relative to target root (only applicable in cdk mode)], - [TARGET_PREFIX="$withval"],[TARGET_PREFIX="NONE"]) + [TARGET_PREFIX="$withval"],[TARGET_PREFIX=""]) AC_ARG_WITH(debug, [ --without-debug disable debugging code], @@ -82,21 +82,33 @@ check_path () { ]) +dnl expand nested ${foo}/bar +AC_DEFUN([TUXBOX_EXPAND_VARIABLE],[__$1="$2" + for __CNT in false false false false true; do dnl max 5 levels of indirection + + $1=`eval echo "$__$1"` + echo ${$1} | grep -q '\$' || break # 'grep -q' is POSIX, exit if no $ in variable + __$1="${$1}" + done + $__CNT && AC_MSG_ERROR([can't expand variable $1=$2]) dnl bail out if we did not expand +]) + AC_DEFUN([TUXBOX_APPS_DIRECTORY_ONE],[ AC_ARG_WITH($1,[ $6$7 [[PREFIX$4$5]]],[ _$2=$withval if test "$TARGET" = "cdk"; then - $2=`eval echo "$TARGET_PREFIX$withval"` + $2=`eval echo "$TARGET_PREFIX$withval"` # no indirection possible IMNSHO else $2=$withval fi TARGET_$2=${$2} ],[ - $2="\${$3}$5" + # RFC 1925: "you can always add another level of indirection..." + TUXBOX_EXPAND_VARIABLE($2,"${$3}$5") if test "$TARGET" = "cdk"; then - _$2=`eval echo "${target$3}$5"` + TUXBOX_EXPAND_VARIABLE(_$2,"${target$3}$5") else - _$2=`eval echo "${$3}$5"` + _$2=${$2} fi TARGET_$2=$_$2 ]) @@ -120,6 +132,8 @@ if test "$TARGET" = "cdk"; then targetlocalstatedir="\${TARGET_PREFIX}/var" targetlibdir="\${TARGET_PREFIX}/lib" targetmntdir="\${TARGET_PREFIX}/mnt" +else + mntdir="/mnt" # hack fi TUXBOX_APPS_DIRECTORY_ONE(configdir,CONFIGDIR,localstatedir,/var,/tuxbox/config, @@ -146,17 +160,17 @@ TUXBOX_APPS_DIRECTORY_ONE(luaplugindir,LUAPLUGINDIR,libdir,/lib,/tuxbox/luaplugi TUXBOX_APPS_DIRECTORY_ONE(localedir,LOCALEDIR,datadir,/share, /tuxbox/neutrino/locale, [--with-localedir=PATH ],[where to find the locale]) -TUXBOX_APPS_DIRECTORY_ONE(themesdir,THEMESDIR,datadir,/share, /tuxbox/neutrino/themes, - [--with-themesdir=PATH ],[where to find the themes]) +TUXBOX_APPS_DIRECTORY_ONE(themesdir,THEMESDIR,datadir,/share,/tuxbox/neutrino/themes, + [--with-themesdir=PATH ],[where to find the themes]) -TUXBOX_APPS_DIRECTORY_ONE(iconsdir,ICONSDIR,datadir,/share, /tuxbox/neutrino/icons, - [--with-iconsdir=PATH ],[where to find the icons]) +TUXBOX_APPS_DIRECTORY_ONE(iconsdir,ICONSDIR,datadir,/share,/tuxbox/neutrino/icons, + [--with-iconsdir=PATH ],[where to find the icons]) TUXBOX_APPS_DIRECTORY_ONE(private_httpddir,PRIVATE_HTTPDDIR,datadir,/share,/tuxbox/neutrino/httpd, - [--with-private_httpddir=PATH ],[where to find the the private httpd files]) + [--with-private_httpddir=PATH ],[where to find the the private httpd files]) TUXBOX_APPS_DIRECTORY_ONE(public_httpddir,PUBLIC_HTTPDDIR,localstatedir,/var,/httpd, - [--with-public_httpddir=PATH ],[where to find the the public httpd files]) + [--with-public_httpddir=PATH ],[where to find the the public httpd files]) TUXBOX_APPS_DIRECTORY_ONE(hosted_httpddir,HOSTED_HTTPDDIR,mntdir,/mnt,/hosted, [--with-hosted_httpddir=PATH ],[where to find the the hosted files]) @@ -289,8 +303,13 @@ _TUXBOX_APPS_LIB_CONFIG($1,$2,WARN) ]) AC_DEFUN([TUXBOX_APPS_PKGCONFIG],[ -AC_PATH_PROG(PKG_CONFIG, pkg-config,no) -if test "$PKG_CONFIG" = "no" ; then +m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test x"$PKG_CONFIG" = x"" ; then AC_MSG_ERROR([could not find pkg-config]); fi ]) @@ -302,6 +321,7 @@ if $PKG_CONFIG --exists "$2" ; then AC_MSG_RESULT(yes) $1_CFLAGS=$($PKG_CONFIG --cflags "$2") $1_LIBS=$($PKG_CONFIG --libs "$2") + $1_EXISTS=yes else AC_MSG_RESULT(no) fi @@ -312,7 +332,7 @@ AC_SUBST($1_LIBS) AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG],[ _TUXBOX_APPS_LIB_PKGCONFIG($1,$2) -if test -z "$$1_CFLAGS" ; then +if test x"$$1_EXISTS" != xyes; then AC_MSG_ERROR([could not find package $2]); fi ]) @@ -426,9 +446,9 @@ AC_SUBST(CATALOGS) AC_DEFUN([TUXBOX_BOXTYPE],[ AC_ARG_WITH(boxtype, - [ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,generic], + [ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic], [case "${withval}" in - dbox2|dreambox|ipbox|tripledragon|coolstream|generic) + dbox2|dreambox|ipbox|tripledragon|coolstream|spark|azbox|generic) BOXTYPE="$withval" ;; dm*) @@ -465,6 +485,13 @@ AC_ARG_WITH(boxmodel, AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) fi ;; + raspi) + if test "$BOXTYPE" = "generic"; then + BOXMODEL="$withval" + else + AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE]) + fi + ;; *) AC_MSG_ERROR([unsupported value $withval for --with-boxmodel]) ;; @@ -476,11 +503,13 @@ AC_ARG_WITH(boxmodel, AC_SUBST(BOXTYPE) AC_SUBST(BOXMODEL) +AM_CONDITIONAL(BOXTYPE_AZBOX, test "$BOXTYPE" = "azbox") AM_CONDITIONAL(BOXTYPE_DBOX2, test "$BOXTYPE" = "dbox2") AM_CONDITIONAL(BOXTYPE_TRIPLE, test "$BOXTYPE" = "tripledragon") AM_CONDITIONAL(BOXTYPE_DREAMBOX, test "$BOXTYPE" = "dreambox") AM_CONDITIONAL(BOXTYPE_IPBOX, test "$BOXTYPE" = "ipbox") AM_CONDITIONAL(BOXTYPE_COOL, test "$BOXTYPE" = "coolstream") +AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark") AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic") AM_CONDITIONAL(BOXMODEL_NEVIS,test "$BOXMODEL" = "nevis") @@ -497,8 +526,12 @@ AM_CONDITIONAL(BOXMODEL_IP250,test "$BOXMODEL" = "ip250") AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350") AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400") +AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi") + if test "$BOXTYPE" = "dbox2"; then AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2]) +elif test "$BOXTYPE" = "azbox"; then + AC_DEFINE(HAVE_AZBOX_HARDWARE, 1, [building for an azbox]) elif test "$BOXTYPE" = "tripledragon"; then AC_DEFINE(HAVE_TRIPLEDRAGON, 1, [building for a tripledragon]) elif test "$BOXTYPE" = "dreambox"; then @@ -507,6 +540,8 @@ elif test "$BOXTYPE" = "ipbox"; then AC_DEFINE(HAVE_IPBOX_HARDWARE, 1, [building for an ipbox]) elif test "$BOXTYPE" = "coolstream"; then AC_DEFINE(HAVE_COOL_HARDWARE, 1, [building for a coolstream]) +elif test "$BOXTYPE" = "spark"; then + AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux]) elif test "$BOXTYPE" = "generic"; then AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC]) fi @@ -526,6 +561,8 @@ elif test "$BOXMODEL" = "ip350"; then AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350]) elif test "$BOXMODEL" = "ip400"; then AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400]) +elif test "$BOXMODEL" = "raspi"; then + AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi]) fi ]) diff --git a/configure.ac b/configure.ac index eb5e2f2a9..672f7f3ab 100644 --- a/configure.ac +++ b/configure.ac @@ -13,19 +13,27 @@ AC_PROG_CXX AC_DISABLE_STATIC AM_PROG_LIBTOOL -# Add build information to config.h -# --------------------------------- - -# Add host to config.h -AC_DEFINE_UNQUOTED(USED_BUILD, ["$build"], [Build system under which the program was compiled on.]) - -# Add used CXXFLAGS to config.h -AC_DEFINE_UNQUOTED(USED_CXXFLAGS, ["$CXXFLAGS"], [Define to the used CXXFLAGS to compile this package.]) - -# Get compiler (version) -AH_TEMPLATE(USED_COMPILER, [Define to name and version of used compiler]) +# Add build information to local_build_config.h.tmp +# ------------------------------------------------- +rm -f local_build_config.h.tmp +cat > local_build_config.h.tmp << EOF +/* Build system under which the program was compiled on. */ +#define USED_BUILD "$build" +/* Define to the used CXXFLAGS to compile this package. */ +#define USED_CXXFLAGS "$CXXFLAGS" +EOF if COMPILER=`$CC --version | head -n 1`; then - AC_DEFINE_UNQUOTED(USED_COMPILER, ["$COMPILER"]) + cat >> local_build_config.h.tmp <<-EOF + /* Define to name and version of used compiler */ + #define USED_COMPILER "$COMPILER" + EOF +fi +# only update header if it differs to avoid unnecessary rebuilds +if ! diff local_build_config.h.tmp local_build_config.h >/dev/null 2>&1; then + rm -f local_build_config.h + mv local_build_config.h.tmp local_build_config.h +else + rm -f local_build_config.h.tmp fi AC_ARG_ENABLE(ffmpegdec, @@ -89,14 +97,31 @@ fi AM_CONDITIONAL(USE_TREMOR, test "$TREMOR" = "yes") # TUXBOX_APPS_LIB_PKGCONFIG(OPENSSL,openssl) -TUXBOX_APPS_LIB_CONFIG(CURL,curl-config) -TUXBOX_APPS_LIB_CONFIG(FREETYPE,freetype-config) +TUXBOX_APPS_LIB_PKGCONFIG(CURL,libcurl) +TUXBOX_APPS_LIB_PKGCONFIG(FREETYPE,freetype2) +# fallback to curl-config (which is ugly for cross-compilation) +if test -z "$CURL_LIBS" -a -z "$CURL_CFLAGS"; then + TUXBOX_APPS_LIB_CONFIG(CURL,curl-config) +fi +# fallback to freetype-config (which is ugly for cross-compilation) +if test -z "$FREETYPE_LIBS" -a -z "$FREETYPE_CFLAGS"; then + TUXBOX_APPS_LIB_CONFIG(FREETYPE,freetype-config) +fi 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) +if test "$BOXTYPE" = "coolstream"; then + TUXBOX_APPS_LIB_PKGCONFIG(BLURAY,libbluray) +fi + +if test "$BOXTYPE" = "coolstream" || + test "$BOXTYPE" = "tripledragon" || + test "$BOXTYPE" = "spark"; then + AC_DEFINE(SCREENSHOT,1,[Define to 1 if the platform supports screenshots]) +fi + TUXBOX_APPS_LIB_PKGCONFIG(SIGC,sigc++-2.0) #TUXBOX_APPS_LIB_PKGCONFIG(CONFIGFILE,tuxbox-configfile) @@ -171,10 +196,35 @@ if test "$enable_upnp" = "yes"; then AC_DEFINE(ENABLE_UPNP,1,[include UPNP support - currently broken]) fi +AC_ARG_ENABLE(extupdate, + AS_HELP_STRING(--enable-extupdate,include extended update routine), + ,[enable_extupdate=no]) + +AM_CONDITIONAL(ENABLE_EXTUPDATE,test "$enable_extupdate" = "yes") +if test "$enable_extupdate" = "yes"; then + AC_DEFINE(ENABLE_EXTUPDATE,1,[include extended update routine]) +fi + +AC_ARG_WITH(stb-hal-includes, + [ --with-stb-hal-includes=PATH path for libstb-hal includes [[NONE]]], + [STB_HAL_INC="$withval"],[STB_HAL_INC=""]) +AC_ARG_WITH(stb-hal-build, + [ --with-stb-hal-build=PATH path where libstb-hal is built [[NONE]]], + [STB_HAL_LIB="-L$withval"],[STB_HAL_LIB=""]) + +AM_CONDITIONAL(USE_STB_HAL, test "$BOXTYPE" != "coolstream") +if test "$BOXTYPE" != coolstream; then + AC_DEFINE(USE_STB_HAL, 1,[use libstb-hal]) + if test "$STB_HAL_INC" = ""; then + AC_MSG_ERROR([need libstb-hal includes path with --with-stb-hal-includes=...]) + fi + HWLIB_CFLAGS="-I$STB_HAL_INC" +fi + # Lua - embeddable scripting language AC_ARG_ENABLE(lua, - AS_HELP_STRING(--enable-lua,include Lua support), - ,[enable_lua=no]) + AS_HELP_STRING(--disable-lua,disable Lua support), + ,[enable_lua=yes]) AM_CONDITIONAL(ENABLE_LUA,test "$enable_lua" = "yes") if test "$enable_lua" = "yes"; then @@ -212,9 +262,10 @@ if test "$BOXTYPE" = "coolstream"; then if test -e ${srcdir}/lib/libcoolstream/nevis_ir.h; then AC_DEFINE(HAVE_COOLSTREAM_NEVIS_IR_H,1,[Define to 1 if you have the header file.]) fi -HWLIB_CFLAGS='-I$(top_srcdir)/lib/libcoolstream' +HWLIB_CFLAGS='-I$(top_srcdir)/lib/libcoolstream -I$(top_srcdir)/src/zapit/include/private' if test "$BOXMODEL" = "apollo"; then +HWLIB_CFLAGS='-I$(top_srcdir)/lib/libcoolstream2' if test -e ${srcdir}/lib/libcoolstream2/cs_ir_generic.h; then AC_DEFINE(HAVE_COOLSTREAM_CS_IR_GENERIC_H,1,[Define to 1 if you have the header file.]) fi @@ -253,6 +304,8 @@ AC_SUBST(FREETYPE_CFLAGS) AC_SUBST(FREETYPE_LIBS) AC_SUBST(VORBISIDEC_CFLAGS) AC_SUBST(VORBISIDEC_LIBS) +AC_SUBST(STB_HAL_INC) +AC_SUBST(STB_HAL_LIB) AC_SUBST(LUA_CFLAGS) AC_SUBST(LUA_LIBS) AC_SUBST(BLURAY_LIBS) @@ -269,7 +322,8 @@ lib/xmltree/Makefile lib/jsoncpp/Makefile lib/sectionsdclient/Makefile lib/timerdclient/Makefile -lib/libtriple/Makefile +lib/libcoolstream/Makefile +lib/libcoolstream2/Makefile lib/libtuxtxt/Makefile lib/libdvbsub/Makefile lib/libupnpclient/Makefile diff --git a/data/locale/Makefile.am b/data/locale/Makefile.am index 356885ce2..99c024e94 100644 --- a/data/locale/Makefile.am +++ b/data/locale/Makefile.am @@ -21,7 +21,7 @@ locale_unmaintained = \ unmaintained/svenska.locale install_DATA = $(locale) -#install_DATA += $(locale_unmaintained) +# install_DATA += $(locale_unmaintained) if MAINTAINER_MODE @@ -38,12 +38,12 @@ sort-locals: work-locals: $(master.locale) for locale in $(locale); do \ - $(top_srcdir)/data/locale/helpers/create-locals-work $${locale}; \ + ( cd $(top_srcdir)/data/locale; helpers/create-locals-work $${locale}; ); \ done ordercheck: $(master.locale) - cut -d' ' -f1 $(master.locale) | LC_ALL=C sort | uniq > /tmp/log - cut -d' ' -f1 $(master.locale) | uniq | diff - /tmp/log || \ + cut -d' ' -f1 $(top_srcdir)/data/locale/$(master.locale) | LC_ALL=C sort | uniq > /tmp/log + cut -d' ' -f1 $(top_srcdir)/data/locale/$(master.locale) | uniq | diff - /tmp/log || \ (echo "ERROR: $(master.locale) not ordered or contains empty lines" && false) locals.h: ordercheck @@ -61,8 +61,8 @@ check: locals.h locals_intern.h install-locals: $(locale) locals.h locals_intern.h cp locals.h locals_intern.h $(top_srcdir)/src/system @echo "Consider committing src/system/[locals.h locals_intern.h]" - cp -f $(locale) $(top_srcdir)/data/locale - @echo "Consider committing data/locale/[$(locale)]" + ## ??? cp -f $(locale) $(top_srcdir)/data/locale + ## @echo "Consider committing data/locale/[$(locale)]" locals-clean: rm -f locals.h locals_intern.h $(locale) diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale index 835fc3bb2..6b9c890a5 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -346,7 +346,7 @@ colormenu.background Hintergrundfarbe colormenu.clock_textcolor Ziffernfarbe colormenu.contrast_fonts Schriftkontrast colormenu.fade Ein-/Ausblenden -colormenu.font Neutrino-HD Schriftart +colormenu.font Neutrino Schriftart colormenu.font_ttx Teletext Schriftart colormenu.hd_preset LCD colormenu.menucolors Farben @@ -494,7 +494,7 @@ extra.key_timeshift Timeshift extra.key_unlock Entsperrtaste extra.ladirection Breitengrad-Ausrichtung extra.latitude Breitengrad -extra.loadconfig Neutrino-HD Einstellungen: Laden von +extra.loadconfig Neutrino Einstellungen: Laden von extra.loadkeys Lade Tastenbelegung von extra.lodirection Längengrad-Ausrichtung extra.longitude Längengrad @@ -506,7 +506,7 @@ extra.rotor_swap Rotor dreht Ost/West extra.rounded_corners Eckendarstellung extra.rounded_corners_off eckig extra.rounded_corners_on abgerundet -extra.saveconfig Neutrino-HD Einstellungen: Sichern als +extra.saveconfig Neutrino Einstellungen: Sichern als extra.savekeys Speichere Tastenbelegung als extra.scrambled_message Verschlüsselung melden extra.show_mute_icon Mute-Icon bei Lautstärke 0 @@ -1303,7 +1303,7 @@ menu.hint_leds_deepstandby Definiert den Status der Power-LEDs im Deep-Standby menu.hint_leds_record Definiert, ob die Power-LEDs blinken sollen, wenn eine Aufnahme aktiv ist 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_load Laden der Neutrino 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 @@ -1459,7 +1459,7 @@ menu.hint_restore Wiederherstellen von vorher erstellten Sicherungen menu.hint_rotor_swap Tauschen der Rotordrehrichtung Ost/West in den Motor-Einstellungen menu.hint_rounded_corners Aktiviert die Darstellung abgerundeter Ecken für die Menüs menu.hint_save_settings Speichert ihre Einstellungen -menu.hint_saveas Speichern der Neutrino-HD-Einstellungen in eine Datei +menu.hint_saveas Speichern der Neutrino Einstellungen in eine Datei menu.hint_scan_auto Automatischer Suchlauf ausgewählter Anbieter menu.hint_scan_autoall Automatischer Suchlauf aller ausgewählten Anbieter menu.hint_scan_autoall_select Suchlauf nur in ausgewählten Satelliten @@ -1578,7 +1578,7 @@ menu.hint_standby Receiver in den Standby Modus versetzen menu.hint_start_tostandby Aktiviert den Standby-Modus direkt nach dem Starten der Box menu.hint_streaminfo Aktuelle Sender-Informationen über PIDs, SNR-Verhältnis, Bitrate und mehr menu.hint_subchannel_pos Wählen Sie die Anzeigeposition der Unterkanäle aus -menu.hint_sw_update Neutrino-HD aktualisieren, Image sichern und wiederherstellen +menu.hint_sw_update Neutrino aktualisieren, Image sichern und wiederherstellen menu.hint_theme Wählen Sie ein vordefiniertes Farbschema, speichern oder laden Sie ihre eigenen Farbschemata menu.hint_timeouts Gibt an, nach welcher Zeit in Sekunden die Menüs oder Infofenster sich automatisch schließen (0 deaktiviert) menu.hint_timers Hinzufügen, entfernen und bearbeiten geplanter Aufnahmen oder anderer Timer @@ -2257,6 +2257,7 @@ plugintype.script Skript plugintype.tool Werkzeug rclock.locked Gesperrt rclock.lockmsg Die Fernbedienung wird gesperrt.\nUm die Sperre aufzuheben, bitte\n[rot] gefolgt von [%s]\nauf der Fernbedienung drücken. +rclock.menueadd FB sperren rclock.title Fernbedienung sperren rclock.unlockmsg Fernbedienung reaktiviert recording.already_found %s\nwurde bereits gefunden. Trotzdem aufnehmen? diff --git a/data/locale/english.locale b/data/locale/english.locale index 93b133d0a..e52f6baa2 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -494,7 +494,7 @@ extra.key_timeshift Timeshift extra.key_unlock Unlock key extra.ladirection LaDirection extra.latitude Latitude -extra.loadconfig Neutrino-HD Settings: Load from +extra.loadconfig Neutrino Settings: Load from extra.loadkeys Load keys from extra.lodirection LoDirection extra.longitude Longitude @@ -506,7 +506,7 @@ extra.rotor_swap Swap rotor east/west extra.rounded_corners Shape of corners extra.rounded_corners_off angular extra.rounded_corners_on rounded -extra.saveconfig Neutrino-HD Settings: Save as +extra.saveconfig Neutrino Settings: Save as extra.savekeys Save keys as extra.scrambled_message Scrambled Message extra.show_mute_icon mute-icon at volume 0 @@ -1303,7 +1303,7 @@ menu.hint_leds_deepstandby LEDs state in deeps-standby mode 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_load Load Neutrino 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 Lua Plugins menu.hint_make_hdlist Auto-create HD channel list based on\nchannel type and name @@ -1391,7 +1391,7 @@ menu.hint_other_fonts Change other font sizes menu.hint_parentallock_changepin Change PIN code menu.hint_parentallock_lockage Select age allowed to watch menu.hint_parentallock_menu Lock menus with pin code -menu.hint_parentallock_prompt Configure when Neutrino-HD will ask you\nfor PIN code +menu.hint_parentallock_prompt Configure when Neutrino will ask you\nfor PIN code menu.hint_personalize Enable, disable or Protect menu items\nConfigure color-buttons user menus menu.hint_pictureviewer_defdir Default picture viewer directory menu.hint_pictureviewer_scaling Picture scaling algorithm @@ -1459,7 +1459,7 @@ menu.hint_restore Restore files from selected backup menu.hint_rotor_swap Swap rotor east/west directions\nin motor control menu.hint_rounded_corners Draw round or rectangular windows corners menu.hint_save_settings Save all settings to flash -menu.hint_saveas Save Neutrino-HD GUI settings to file +menu.hint_saveas Save Neutrino GUI settings to file menu.hint_scan_auto Auto-scan selected provider menu.hint_scan_autoall Scan several selected providers at once menu.hint_scan_autoall_select Add selected satellites to scan diff --git a/data/locale/helpers/create-locals-work b/data/locale/helpers/create-locals-work index 6e1479338..f9a54ee55 100755 --- a/data/locale/helpers/create-locals-work +++ b/data/locale/helpers/create-locals-work @@ -6,46 +6,56 @@ # to, after manual editing, replace the outdated locale file. # Written by Barf on 2005-12-10. +# reorganized by Stefan Seyfried 2016-01-03, following changes: +# * use strict, use warnings to find errors easier +# * make it work with the above pragmas +# * tolerance against empty locales in english.locale -$masterfilename = "english.locale"; +use warnings; +use strict; + +my $masterfilename = "english.locale"; $#ARGV == 0 || die("Usage: create-locals-work file.locale."); -$no_errors = 0; -$last_was_ok = 1; -$localefilename = @ARGV[0]; -$outfilename = $localefilename . "-work"; +my $no_errors = 0; +my $last_was_ok = 1; +my $localefilename = $ARGV[0]; +my $outfilename = $localefilename . "-work"; -open(masterfile, $masterfilename) || die("Could not open master file"); -open(localefile, $localefilename) || die("Could not open locale file"); -open(outfile, ">" . $outfilename) || die("Could not open output file"); +open(MASTER, $masterfilename) || die("Could not open master file $masterfilename"); +open(LOCALE, $localefilename) || die("Could not open locale file $localefilename"); +open(OUT, ">" . $outfilename) || die("Could not open output file $outfilename"); -%master = {}; -%locale = {}; +my %master; +my %locale; -while () { +my $line; +while ($line = ) { # master hash - $line = $_; - ($key) = /([^ ]+)/; - ($junk, $text) = /([^ ]+)[ ]+([^\n]+)/; - $master{$key} = $text; + chomp $line; + $line =~ s/^\s+//; # strip whitespace from start of line + my ($key, $text) = split /\s+/, $line, 2; + $master{$key} = $text ? $text : ""; } +close(MASTER); -while () { +while ($line = ) { # locale hash - $line = $_; - ($key) = /([^ ]+)/; - ($junk, $text) = /([^ ]+)[ ]+([^\n]+)/; - $locale{$key} = $text; + chomp $line; + $line =~ s/^\s+//; + my ($key, $text) = split /\s+/, $line, 2; + $locale{$key} = $text ? $text : ""; } +close(LOCALE); -foreach $term (sort keys %master) { +foreach my $term (sort keys %master) { if (exists $locale{$term}) { - print outfile $term, " ", $locale{$term}, "\n"; + print OUT $term." ".$locale{$term}."\n"; } else { # not found $no_errors++; - print outfile $term, " TRANSLATE ", $master{$term}, "\n"; + print OUT $term." TRANSLATE ".$master{$term}."\n"; } } diff --git a/data/locale/nederlands.locale b/data/locale/nederlands.locale index 68dbea5bc..ec6dd12e7 100644 --- a/data/locale/nederlands.locale +++ b/data/locale/nederlands.locale @@ -426,7 +426,7 @@ extra.key_timeshift Timeshift extra.key_unlock Ontgrendel toets extra.ladirection LA richting extra.latitude Breedtegraad (latitude) -extra.loadconfig Neutrino-HD Settings: Laden van +extra.loadconfig Neutrino Settings: Laden van extra.loadkeys Toetsen laden van extra.lodirection LO richting extra.longitude Lengtegraad (Longitude) @@ -438,7 +438,7 @@ extra.rotor_swap Schakelen rotor oost/west extra.rounded_corners Vorm van hoeken extra.rounded_corners_off Rechthoekig extra.rounded_corners_on Rond -extra.saveconfig Neutrino-HD Settings: Opslaan als... +extra.saveconfig Neutrino Settings: Opslaan als... extra.savekeys Toetsen opslaan extra.scrambled_message Gecodeerd bericht extra.show_mute_icon Weergave Mute icoon wanneer volume niveau 0 is @@ -1079,7 +1079,7 @@ menu.hint_leds_deepstandby LEDs status in deeps-standby mode menu.hint_leds_record LEDs status wanneer een opname gemaakt wordt menu.hint_leds_standby LEDs status in soft-standby mode menu.hint_leds_tv LEDs status indien de ontvanger in werking is -menu.hint_load Laad Neutrino-HD gebruikersinterface \ninstellingen van back-up bestand +menu.hint_load Laad Neutrino gebruikersinterface \ninstellingen van back-up bestand menu.hint_longkeypress_duration Een toets-indruk wordt gezien als "lange toets indruk" wanneer deze langer is ingedrukt dan de gespecificeerde tijd. menu.hint_lua Start Lua Plugins menu.hint_make_hdlist Automatisch HD kanalenlijst maken \ngebaseerd op kanaaltype en naam @@ -1297,7 +1297,7 @@ menu.hint_selected_back Wijzig achtergrond kleur van het geselecteerde item menu.hint_selected_text Wijzig test kleur van het geselecteerde item menu.hint_service Tuner instellingen, service scan,\nfavorietenlijst editor, software update menu.hint_service_scan Tuner instellingen, service scan -menu.hint_settings Configureer Neutrino-HD\nNetwerk, audio, video, OSD en meer +menu.hint_settings Configureer Neutrino\nNetwerk, audio, video, OSD en meer menu.hint_show_mute_icon Mute icoon weergeven wanneer volume op 0 staat. menu.hint_shutdown Schakel uw ontvanger in deep standby modus\n geen bevestiging menu.hint_shutdown_count Tijd voordat uw ontvanger in deepstand-by schakelt vanuit soft-standby modus @@ -1306,7 +1306,7 @@ menu.hint_shutdown_rcdelay Deep standby modus inschakelen wanneer de power toets menu.hint_shutdown_real Soft-standby inschakelen indien soft-standby is \nuitgeschakeld schakelt de ontvanger gelijk in deep standby menu.hint_sleeptimer Timer instellen om uw ontvanger in slaapstand te schakelen menu.hint_sleeptimer_min Standaard instelling voor sleeptimer -menu.hint_soft_restart Herstart Neutrino-HD zonder reboot +menu.hint_soft_restart Herstart Neutrino zonder reboot menu.hint_softupdate_check Controleer online voor updates, download en installeer deze. menu.hint_softupdate_check_local Selecteer en installeer firmware vanaf een lokaal bestand menu.hint_softupdate_createimage_menu Backup van huidige software, inclusief alle instellingen @@ -2069,7 +2069,7 @@ settings.menu_hints Menu hints weergeven settings.menu_pos Menu positie settings.menus Menus settings.missingoptionsconffile De instellingen zijn geupdate.\nNieuwe opties zijn standaard ingesteld. -settings.noconffile Geen Neutrino-HD instellingen gevonden.\nGebruikt standaard instellingen. +settings.noconffile Geen Neutrino instellingen gevonden.\nGebruikt standaard instellingen. settings.pos_bottom_center midden onder settings.pos_bottom_left Links onder settings.pos_bottom_right Rechts onder diff --git a/data/locale/unmaintained/czech.locale b/data/locale/unmaintained/czech.locale index 11e1e557d..f2c26b254 100644 --- a/data/locale/unmaintained/czech.locale +++ b/data/locale/unmaintained/czech.locale @@ -1151,7 +1151,7 @@ menu.hint_other_fonts Zmena velikosti další písma menu.hint_parentallock_changepin Změna PIN kódu menu.hint_parentallock_lockage Výběr povoleného věku pro sledování menu.hint_parentallock_menu Zamknutí nabídek s pin kódem -menu.hint_parentallock_prompt Konfigurace když se Neutrino-HD zeptá na PIN kód +menu.hint_parentallock_prompt Konfigurace když se Neutrino zeptá na PIN kód menu.hint_personalize Povolení / zakázání nebo Položky menu zabezpečení \nKonfigurace barevných tlačítek uživatelských nabídek menu.hint_pictureviewer_defdir Výchozí adresář prohlížeče obrázků menu.hint_pictureviewer_scaling Algoritmus měřítka obrázku @@ -1305,7 +1305,7 @@ menu.hint_selected_back Změna barvy podkladu označené položky menu.hint_selected_text Změna barvy textu označené položky menu.hint_service Nastavení tuneru, vyhledání služeb, \nÚprava buketů, aktualizace software menu.hint_service_scan Nastavení tuneru, vyhledání služeb -menu.hint_settings Konfigurace Neutrino-HD, síť, zvuk, obraz, OSD a jiné +menu.hint_settings Konfigurace Neutrino, síť, zvuk, obraz, OSD a jiné menu.hint_show_mute_icon Zobrazení ikony umlčení, pokud nastavení hlasitosti bude 0 menu.hint_shutdown Přepne váš příjmač do spánku \nBez potvrzování menu.hint_shutdown_count Čas přepnutí přijímače do spánku \nz režimu připravenosti @@ -1314,7 +1314,7 @@ menu.hint_shutdown_rcdelay Použije režim spánku, pokud tlačítko zapnutí \n menu.hint_shutdown_real Použije režim připravenosti \nPokud se nepoužije, tlačítko zapnutí přepne příjmač do spánku menu.hint_sleeptimer Nastavení časovače pro přechod vašeho příjmače \ndo režimu připravenosti menu.hint_sleeptimer_min Přednastavené nastavení pro časovač vypnutí -menu.hint_soft_restart Restartování Neutrino-HD bez rebootu +menu.hint_soft_restart Restartování Neutrino bez rebootu menu.hint_softupdate_check Kontrola dostupných aktualizací, stažení a naprogramování firmware menu.hint_softupdate_check_local Výběr a programování firmware z lokálního souboru menu.hint_softupdate_createimage_menu Zálohování aktuálního firmware včetně všech nastavení diff --git a/lib/Makefile.am b/lib/Makefile.am index ff4f206cb..0aacf022e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,7 +18,12 @@ SUBDIRS += \ libupnpclient endif -if BOXTYPE_TRIPLE +if BOXTYPE_COOL +if BOXMODEL_APOLLO SUBDIRS += \ - libtriple + libcoolstream2 +else +SUBDIRS += \ + libcoolstream +endif endif diff --git a/lib/libcoolstream/Makefile.am b/lib/libcoolstream/Makefile.am new file mode 100644 index 000000000..f1c497147 --- /dev/null +++ b/lib/libcoolstream/Makefile.am @@ -0,0 +1,16 @@ +noinst_LIBRARIES = libhwcaps.a + +AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing + +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/zapit/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/lib/libeventserver \ + -I$(top_srcdir)/lib/libconfigfile \ + -I$(top_srcdir)/lib/libcoolstream \ + @HWLIB_CFLAGS@ + +libhwcaps_a_SOURCES = \ + hardware_caps.cpp diff --git a/lib/libcoolstream/hardware_caps.cpp b/lib/libcoolstream/hardware_caps.cpp new file mode 100644 index 000000000..f488e046a --- /dev/null +++ b/lib/libcoolstream/hardware_caps.cpp @@ -0,0 +1,87 @@ +/* + * determine the capabilities of the hardware. + * part of libstb-hal + * + * (C) 2010-2012 Stefan Seyfried + * (C) 2016 M. Liebmann + * + * License: GPL v2 or later + */ + +#include +#include +#include +#include "hardware_caps.h" + +static int initialized = 0; +static bool frontend_check = false; +static hw_caps_t caps; + +hw_caps_t *get_hwcaps(void) +{ + + if (initialized && frontend_check) + return ∩︀ + + struct utsname u; + unsigned int system_rev = cs_get_revision(); + + CFEManager* fem = CFEManager::getInstance(); + int frontendCount = fem->getFrontendCount(); + frontend_check = frontendCount > 0; + + caps.has_fan = (system_rev < 8); + caps.has_HDMI = 1; + caps.has_SCART = (system_rev != 10); + caps.has_SCART_input = 0; + caps.has_YUV_cinch = 1; + caps.can_shutdown = (system_rev > 7); + caps.can_cec = 1; + caps.display_type = (system_rev != 10) ? HW_DISPLAY_LINE_TEXT : HW_DISPLAY_NONE; + caps.display_xres = 12; + caps.display_yres = 0; + caps.can_set_display_brightness = 1; + + + strcpy(caps.boxvendor, "CST"); + const char* boxname; + switch (system_rev) { + case 6: + boxname = "HD1"; + break; + case 7: + boxname = "BSE"; + break; + case 8: + boxname = "Neo"; + break; + case 10: + boxname = "Zee"; + break; + default: + char buffer[512]; + snprintf(buffer, sizeof(buffer)-1, "Unknown nr. %u\n", system_rev); + boxname = buffer; + break; + } + strcpy(caps.boxname, boxname); + + CFrontend *frontend = fem->getFE(0); + uint32_t mask = frontend->getSupportedDeliverySystems(); + std::string tuner = ""; + if (frontendCount > 1) + tuner += "Twin "; + tuner += ((mask & DVB_C) == DVB_C) ? g_Locale->getText(LOCALE_SATSETUP_FE_DELSYS_MODE_CABLE) : "Sat"; + strcpy(caps.frontend, tuner.c_str()); + + strcpy(caps.chipset, "Nevis"); + + if (! uname(&u)) + strncpy(caps.boxarch, u.machine, sizeof(caps.boxarch)); + else + fprintf(stderr, "%s: uname() failed: %m\n", __func__); + + initialized = 1; + return ∩︀ +} + diff --git a/lib/libcoolstream/hardware_caps.h b/lib/libcoolstream/hardware_caps.h new file mode 100644 index 000000000..c45c173dc --- /dev/null +++ b/lib/libcoolstream/hardware_caps.h @@ -0,0 +1,46 @@ +/* + * determine the capabilities of the hardware. + * part of libstb-hal + * + * (C) 2010-2012 Stefan Seyfried + * (C) 2016 M. Liebmann + * + * License: GPL v2 or later + */ +#ifndef __HARDWARE_CAPS_H__ +#define __HARDWARE_CAPS_H__ + +#include "cs_api.h" +#include +#include + +typedef enum { + HW_DISPLAY_NONE, + HW_DISPLAY_LED_NUM, /* simple 7 segment LED display */ + HW_DISPLAY_LINE_TEXT, /* 1 line text display */ + HW_DISPLAY_GFX +} display_type_t; + + +typedef struct hw_caps { + int has_fan; + int has_HDMI; + int has_SCART; + int has_SCART_input; + int has_YUV_cinch; + int can_shutdown; + int can_cec; + display_type_t display_type; + int display_xres; /* x resolution or chars per line */ + int display_yres; + int can_set_display_brightness; + char boxvendor[64]; + char boxname[64]; + char boxarch[64]; + char chipset[64]; + char frontend[64]; +} hw_caps_t; + +std::string getTuner(); +hw_caps_t *get_hwcaps(void); +#endif diff --git a/lib/libcoolstream2/Makefile.am b/lib/libcoolstream2/Makefile.am new file mode 100644 index 000000000..e96803f29 --- /dev/null +++ b/lib/libcoolstream2/Makefile.am @@ -0,0 +1,15 @@ +noinst_LIBRARIES = libhwcaps.a + +AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing + +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/zapit/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/lib/libeventserver \ + -I$(top_srcdir)/lib/libconfigfile \ + -I$(top_srcdir)/lib/libcoolstream2 + +libhwcaps_a_SOURCES = \ + hardware_caps.cpp diff --git a/lib/libcoolstream2/cs_frontpanel.h b/lib/libcoolstream2/cs_frontpanel.h index e6ca97137..df44af486 100644 --- a/lib/libcoolstream2/cs_frontpanel.h +++ b/lib/libcoolstream2/cs_frontpanel.h @@ -120,7 +120,11 @@ typedef struct { unsigned short xres, yres; unsigned int segment_count; fp_display_text_type_t text_support; +#ifdef __cplusplus bool number_support; +#else + int number_support; +#endif } fp_display_caps_t; #define IOC_FP_SET_BRIGHT _IOW(0xDE, 1, unsigned char) /* set the display brighness in 16 steps between 0 to 15 */ diff --git a/lib/libcoolstream2/hardware_caps.cpp b/lib/libcoolstream2/hardware_caps.cpp new file mode 100644 index 000000000..1e1c4a8c1 --- /dev/null +++ b/lib/libcoolstream2/hardware_caps.cpp @@ -0,0 +1,170 @@ +/* + * determine the capabilities of the hardware. + * part of libstb-hal + * + * (C) 2010-2012 Stefan Seyfried + * (C) 2016 M. Liebmann + * + * License: GPL v2 or later + */ + +#include +#include +#include +#include "hardware_caps.h" + +static int initialized = 0; +static bool frontend_check = false; +static hw_caps_t caps; + +std::string getTuner() +{ + std::string tuner; + char buff1[64]; + CFEManager* fem = CFEManager::getInstance(); + int frontendCount = fem->getFrontendCount(); + frontend_check = frontendCount > 0; + + int satCount = 0; + int cableCount = 0; + int dvbtCount = 0; + int dvbc_tCount = 0; + for (int i = 0; i < frontendCount; i++) { + bool has_dvb_s = false; + bool has_dvb_s2 = false; + bool has_dvb_c = false; + bool has_dvb_t = false; + bool has_dvb_t2 = false; +// bool has_dtmb = false; + + CFrontend *frontend = fem->getFE(i); + uint32_t mask = frontend->getSupportedDeliverySystems(); + + if ((mask & DVB_S) == DVB_S) has_dvb_s = true; + if ((mask & DVB_S2) == DVB_S2) has_dvb_s2 = true; + if ((mask & DVB_C) == DVB_C) has_dvb_c = true; + if ((mask & DVB_T) == DVB_T) has_dvb_t = true; + if ((mask & DVB_T2) == DVB_T2) has_dvb_t2 = true; +// if ((mask & DTMB) == DTMB) has_dtmb = true; + + if (has_dvb_s || has_dvb_s2) satCount++; + if (has_dvb_c && (has_dvb_t || has_dvb_t2)) + dvbc_tCount++; + else { + if (has_dvb_c) cableCount++; + if (has_dvb_t || has_dvb_t2) dvbtCount++; + } + } + + if (satCount > 0) { + memset(buff1, 0, sizeof(buff1)); + snprintf(buff1, sizeof(buff1)-1, "%dx Sat", satCount); + tuner += buff1; + } + if (cableCount > 0) { + if (satCount > 0) tuner += ", "; + memset(buff1, 0, sizeof(buff1)); + snprintf(buff1, sizeof(buff1)-1, "%dx %s", cableCount, g_Locale->getText(LOCALE_SATSETUP_FE_DELSYS_MODE_CABLE)); + tuner += buff1; + } + if (dvbtCount > 0) { + if ((satCount > 0) || (cableCount > 0)) tuner += ", "; + memset(buff1, 0, sizeof(buff1)); + snprintf(buff1, sizeof(buff1)-1, "%dx DVB-T", dvbtCount); + tuner += buff1; + } + if (dvbc_tCount > 0) { + if ((satCount > 0) || (cableCount > 0) || (dvbtCount > 0)) tuner += ", "; + memset(buff1, 0, sizeof(buff1)); + snprintf(buff1, sizeof(buff1)-1, "%dx %s/DVB-T", dvbc_tCount, g_Locale->getText(LOCALE_SATSETUP_FE_DELSYS_MODE_CABLE)); + tuner += buff1; + } + return tuner; +} + +hw_caps_t *get_hwcaps(void) +{ + if (!frontend_check) + strcpy(caps.frontend, getTuner().c_str()); + + if (initialized) + return ∩︀ + + struct utsname u; + unsigned int system_rev = cs_get_revision(); + + caps.has_fan = 0; + caps.has_HDMI = 1; + caps.has_SCART = (system_rev != 10); + caps.has_SCART_input = 0; + caps.has_YUV_cinch = 1; + caps.can_shutdown = 1; + caps.can_cec = 1; + switch (system_rev) { + case 9: /* Tank */ + case 12: /* Zee2 */ + caps.display_type = HW_DISPLAY_LINE_TEXT; + break; + case 11: /* Trinity */ + caps.display_type = HW_DISPLAY_NONE; + break; + case 13: /* Link */ + caps.display_type = HW_DISPLAY_LED_NUM; + break; + default: + caps.display_type = HW_DISPLAY_NONE; + break; + } + caps.display_xres = 12; + caps.display_yres = 0; + caps.can_set_display_brightness = 1; + + strcpy(caps.boxvendor, "CST"); + const char* boxname; + switch (system_rev) { + case 9: + boxname = "Tank"; + break; + case 11: + boxname = "Trinity"; + break; + case 12: + boxname = "Zee2"; + break; + case 13: + boxname = "Link"; + break; + default: + char buffer[512]; + snprintf(buffer, sizeof(buffer)-1, "Unknown nr. %u\n", system_rev); + boxname = buffer; + break; + } + strcpy(caps.boxname, boxname); + + const char* chipset; + switch (system_rev) { + case 9: + chipset = "Apollo"; + break; + case 11: + chipset = "Shiner"; + break; + case 12: + case 13: + chipset = "Kronos"; + break; + default: + chipset = ""; + break; + } + strcpy(caps.chipset, chipset); + + if (! uname(&u)) + strncpy(caps.boxarch, u.machine, sizeof(caps.boxarch)); + else + fprintf(stderr, "%s: uname() failed: %m\n", __func__); + + initialized = 1; + return ∩︀ +} diff --git a/lib/libcoolstream2/hardware_caps.h b/lib/libcoolstream2/hardware_caps.h new file mode 100644 index 000000000..c45c173dc --- /dev/null +++ b/lib/libcoolstream2/hardware_caps.h @@ -0,0 +1,46 @@ +/* + * determine the capabilities of the hardware. + * part of libstb-hal + * + * (C) 2010-2012 Stefan Seyfried + * (C) 2016 M. Liebmann + * + * License: GPL v2 or later + */ +#ifndef __HARDWARE_CAPS_H__ +#define __HARDWARE_CAPS_H__ + +#include "cs_api.h" +#include +#include + +typedef enum { + HW_DISPLAY_NONE, + HW_DISPLAY_LED_NUM, /* simple 7 segment LED display */ + HW_DISPLAY_LINE_TEXT, /* 1 line text display */ + HW_DISPLAY_GFX +} display_type_t; + + +typedef struct hw_caps { + int has_fan; + int has_HDMI; + int has_SCART; + int has_SCART_input; + int has_YUV_cinch; + int can_shutdown; + int can_cec; + display_type_t display_type; + int display_xres; /* x resolution or chars per line */ + int display_yres; + int can_set_display_brightness; + char boxvendor[64]; + char boxname[64]; + char boxarch[64]; + char chipset[64]; + char frontend[64]; +} hw_caps_t; + +std::string getTuner(); +hw_caps_t *get_hwcaps(void); +#endif diff --git a/lib/libdvbsub/dvbsub.cpp b/lib/libdvbsub/dvbsub.cpp index 3af6d17fe..396c68200 100644 --- a/lib/libdvbsub/dvbsub.cpp +++ b/lib/libdvbsub/dvbsub.cpp @@ -102,8 +102,8 @@ int dvbsub_start(int pid) pid_change_req = 1; } } -printf("[dvb-sub] ***************************************** start, stopped %d pid %x\n", dvbsub_stopped, dvbsub_pid); #if 0 +printf("[dvb-sub] ***************************************** start, stopped %d pid %x\n", dvbsub_stopped, dvbsub_pid); while(!dvbsub_stopped) usleep(10); #endif @@ -243,10 +243,14 @@ static void* reader_thread(void * /*arg*/) int len; uint16_t packlen; uint8_t* buf; + bool bad_startcode = false; dmx = new cDemux(0); +#if HAVE_TRIPLEDRAGON + dmx->Open(DMX_PES_CHANNEL, NULL, 16*1024); +#else dmx->Open(DMX_PES_CHANNEL, NULL, 64*1024); - +#endif while (reader_running) { if(dvbsub_stopped /*dvbsub_paused*/) { sub_debug.print(Debug::VERBOSE, "%s stopped\n", __FUNCTION__); @@ -281,9 +285,13 @@ static void* reader_thread(void * /*arg*/) continue; if(memcmp(tmp, "\x00\x00\x01\xbd", 4)) { - sub_debug.print(Debug::VERBOSE, "[subtitles] bad start code: %02x%02x%02x%02x\n", tmp[0], tmp[1], tmp[2], tmp[3]); + if (!bad_startcode) { + sub_debug.print(Debug::VERBOSE, "[subtitles] bad start code: %02x%02x%02x%02x\n", tmp[0], tmp[1], tmp[2], tmp[3]); + bad_startcode = true; + } continue; } + bad_startcode = false; count = 6; packlen = getbits(tmp, 4*8, 16) + 6; @@ -370,7 +378,7 @@ static void* dvbsub_thread(void* /*arg*/) if(packet_queue.size() == 0) { continue; } - sub_debug.print(Debug::VERBOSE, "PES: Wakeup, queue size %d\n\n", packet_queue.size()); + sub_debug.print(Debug::VERBOSE, "PES: Wakeup, queue size %d\n", packet_queue.size()); if(dvbsub_stopped /*dvbsub_paused*/) { clear_queue(); continue; diff --git a/lib/libdvbsub/dvbsubtitle.cpp b/lib/libdvbsub/dvbsubtitle.cpp index e2bd49e5b..dad97acaa 100644 --- a/lib/libdvbsub/dvbsubtitle.cpp +++ b/lib/libdvbsub/dvbsubtitle.cpp @@ -11,6 +11,10 @@ * dvbsubtitle for HD1 ported by Coolstream LTD */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "dvbsubtitle.h" extern "C" { @@ -32,7 +36,7 @@ extern "C" { #endif // Set these to 'true' for debug output: -static bool DebugConverter = false; //NI +static bool DebugConverter = false; #define dbgconverter(a...) if (DebugConverter) sub_debug.print(Debug::VERBOSE, a) @@ -62,7 +66,7 @@ cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t pPts) cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps() { - dbgconverter("cDvbSubtitleBitmaps::delete: PTS: %lld rects %d\n", pts, Count()); +// dbgconverter("cDvbSubtitleBitmaps::delete: PTS: %lld rects %d\n", pts, Count()); int i; if(sub.rects) { @@ -83,12 +87,16 @@ fb_pixel_t * simple_resize32(uint8_t * orgin, uint32_t * colors, int nb_colors, fb_pixel_t *cr,*l; int i,j,k,ip; +#ifndef HAVE_SPARK_HARDWARE cr = (fb_pixel_t *) malloc(dx*dy*sizeof(fb_pixel_t)); if(cr == NULL) { printf("Error: malloc\n"); return NULL; } +#else + cr = CFrameBuffer::getInstance()->getBackBufferPointer(); +#endif l = cr; for(j = 0; j < dy; j++, l += dx) @@ -107,26 +115,34 @@ fb_pixel_t * simple_resize32(uint8_t * orgin, uint32_t * colors, int nb_colors, void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) { int i; +#ifndef HAVE_SPARK_HARDWARE int stride = CFrameBuffer::getInstance()->getScreenWidth(true); +#if 0 int wd = CFrameBuffer::getInstance()->getScreenWidth(); int xstart = CFrameBuffer::getInstance()->getScreenX(); int yend = CFrameBuffer::getInstance()->getScreenY() + CFrameBuffer::getInstance()->getScreenHeight(); int ystart = CFrameBuffer::getInstance()->getScreenY(); +#endif uint32_t *sublfb = CFrameBuffer::getInstance()->getFrameBufferPointer(); +#endif - dbgconverter("cDvbSubtitleBitmaps::Draw: %d bitmaps, x= %d, width= %d yend=%d stride %d\n", Count(), xstart, wd, yend, stride); +// dbgconverter("cDvbSubtitleBitmaps::Draw: %d bitmaps, x= %d, width= %d yend=%d stride %d\n", Count(), xstart, wd, yend, stride); + int sw = CFrameBuffer::getInstance()->getScreenWidth(true); + int sh = CFrameBuffer::getInstance()->getScreenHeight(true); +#if 0 double xc = (double) CFrameBuffer::getInstance()->getScreenWidth(true)/(double) 720; double yc = (double) CFrameBuffer::getInstance()->getScreenHeight(true)/(double) 576; xc = yc; //FIXME should we scale also to full width ? int xf = int(xc * (double) 720); - +#endif for (i = 0; i < Count(); i++) { uint32_t * colors = (uint32_t *) sub.rects[i]->pict.data[1]; int width = sub.rects[i]->w; int height = sub.rects[i]->h; int xoff, yoff; +#if 0 int nw = int(width == 1280 ? ((double) width / xc) : ((double) width * xc)); int nh = int((double) height * yc); @@ -139,12 +155,22 @@ void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) if(yoff < ystart) yoff = ystart; } +#endif + int h2 = (width == 1280) ? 720 : 576; + xoff = sub.rects[i]->x * sw / width; + yoff = sub.rects[i]->y * sh / h2; + int nw = width * sw / width; + int nh = height * sh / h2; - dbgconverter("cDvbSubtitleBitmaps::Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, - sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, xoff, yoff, nw, nh); +// dbgconverter("cDvbSubtitleBitmaps::Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, +// sub.rects[i]->x, sub.rects[i]->y, sub.rects[i]->w, sub.rects[i]->h, sub.rects[i]->nb_colors, xoff, yoff, nw, nh); fb_pixel_t * newdata = simple_resize32 (sub.rects[i]->pict.data[0], colors, sub.rects[i]->nb_colors, width, height, nw, nh); +#ifdef HAVE_SPARK_HARDWARE + // CFrameBuffer::getInstance()->waitForIdle(); + CFrameBuffer::getInstance()->blit2FB(newdata, nw, nh, xoff, yoff, 0, 0); +#else fb_pixel_t * ptr = newdata; for (int y2 = 0; y2 < nh; y2++) { int y = (yoff + y2) * stride; @@ -152,6 +178,7 @@ void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) *(sublfb + xoff + x2 + y) = *ptr++; } free(newdata); +#endif if(min_x > xoff) min_x = xoff; @@ -162,11 +189,13 @@ void cDvbSubtitleBitmaps::Draw(int &min_x, int &min_y, int &max_x, int &max_y) if(max_y < (yoff + nh)) max_y = yoff + nh; } - if(Count()) - dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); - dbgconverter("\n"); + +// if(Count()) +// dbgconverter("cDvbSubtitleBitmaps::Draw: finish, min/max screen: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); +// dbgconverter("\n"); } +static int screen_w, screen_h, screen_x, screen_y; // --- cDvbSubtitleConverter ------------------------------------------------- cDvbSubtitleConverter::cDvbSubtitleConverter(void) @@ -197,10 +226,10 @@ cDvbSubtitleConverter::cDvbSubtitleConverter(void) //if(DebugConverter) // av_log_set_level(AV_LOG_INFO); - min_x = CFrameBuffer::getInstance()->getScreenWidth(); - min_y = CFrameBuffer::getInstance()->getScreenHeight(); - max_x = CFrameBuffer::getInstance()->getScreenX(); - max_y = CFrameBuffer::getInstance()->getScreenY(); + screen_w = min_x = CFrameBuffer::getInstance()->getScreenWidth(); + screen_h = min_y = CFrameBuffer::getInstance()->getScreenHeight(); + screen_x = max_x = CFrameBuffer::getInstance()->getScreenX(); + screen_y = max_y = CFrameBuffer::getInstance()->getScreenY(); Timeout.Set(0xFFFF*1000); } @@ -243,9 +272,14 @@ void cDvbSubtitleConverter::Pause(bool pause) void cDvbSubtitleConverter::Clear(void) { - dbgconverter("cDvbSubtitleConverter::Clear: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); +// dbgconverter("cDvbSubtitleConverter::Clear: x=% d y= %d, w= %d, h= %d\n", min_x, min_y, max_x-min_x, max_y-min_y); if(running && (max_x-min_x > 0) && (max_y-min_y > 0)) { CFrameBuffer::getInstance()->paintBackgroundBoxRel (min_x, min_y, max_x-min_x, max_y-min_y); + /* reset area to clear */ + min_x = screen_w; + min_y = screen_h; + max_x = screen_x; + max_y = screen_h; //CFrameBuffer::getInstance()->paintBackground(); } } @@ -279,18 +313,18 @@ int cDvbSubtitleConverter::Convert(const uchar *Data, int Length, int64_t pts) avpkt.data = (uint8_t*) Data; avpkt.size = Length; - dbgconverter("cDvbSubtitleConverter::Convert: sub %x pkt %x pts %lld\n", sub, &avpkt, pts); +// dbgconverter("cDvbSubtitleConverter::Convert: sub %x pkt %x pts %lld\n", sub, &avpkt, pts); //avctx->sub_id = (anc_page << 16) | comp_page; //FIXME not patched ffmpeg needs this ! avcodec_decode_subtitle2(avctx, sub, &got_subtitle, &avpkt); - dbgconverter("cDvbSubtitleConverter::Convert: pts %lld subs ? %s, %d bitmaps\n", pts, got_subtitle? "yes" : "no", sub->num_rects); +// dbgconverter("cDvbSubtitleConverter::Convert: pts %lld subs ? %s, %d bitmaps\n", pts, got_subtitle? "yes" : "no", sub->num_rects); if(got_subtitle) { if(DebugConverter) { unsigned int i; for(i = 0; i < sub->num_rects; i++) { - dbgconverter("cDvbSubtitleConverter::Convert: #%d at %d,%d size %d x %d colors %d\n", i+1, - sub->rects[i]->x, sub->rects[i]->y, sub->rects[i]->w, sub->rects[i]->h, sub->rects[i]->nb_colors); +// dbgconverter("cDvbSubtitleConverter::Convert: #%d at %d,%d size %d x %d colors %d\n", i+1, +// sub->rects[i]->x, sub->rects[i]->y, sub->rects[i]->w, sub->rects[i]->h, sub->rects[i]->nb_colors); } } bitmaps->Add(Bitmaps); @@ -311,7 +345,10 @@ void dvbsub_get_stc(int64_t * STC); int cDvbSubtitleConverter::Action(void) { int WaitMs = WAITMS; - +#if 0 + retry: + bool shown = false; +#endif if (!running) return 0; @@ -328,11 +365,12 @@ int cDvbSubtitleConverter::Action(void) Delta = LimitTo32Bit(sb->Pts()) - LimitTo32Bit(STC); Delta /= 90; // STC and PTS are in 1/90000s - dbgconverter("cDvbSubtitleConverter::Action: PTS: %016llx STC: %016llx (%lld) timeout: %d\n", sb->Pts(), STC, Delta, sb->Timeout()); +// dbgconverter("cDvbSubtitleConverter::Action: PTS: %016llx STC: %016llx (%lld) timeout: %d\n", sb->Pts(), STC, Delta, sb->Timeout()); if (Delta <= MAXDELTA) { if (Delta <= SHOW_DELTA) { - dbgconverter("cDvbSubtitleConverter::Action: Got %d bitmaps, showing #%d\n", bitmaps->Count(), sb->Index() + 1); +dbgconverter("cDvbSubtitleConverter::Action: PTS: %012llx STC: %012llx (%lld) timeout: %d bmp %d/%d\n", sb->Pts(), STC, Delta, sb->Timeout(), bitmaps->Count(), sb->Index() + 1); +// dbgconverter("cDvbSubtitleConverter::Action: Got %d bitmaps, showing #%d\n", bitmaps->Count(), sb->Index() + 1); if (running) { Clear(); sb->Draw(min_x, min_y, max_x, max_y); @@ -341,12 +379,16 @@ int cDvbSubtitleConverter::Action(void) if(sb->Count()) WaitMs = MIN_DISPLAY_TIME; bitmaps->Del(sb, true); +// shown = true; } else if (Delta < WaitMs) WaitMs = int((Delta > SHOW_DELTA) ? Delta - SHOW_DELTA : Delta); } else + { + dbgconverter("deleted because delta (%lld) > MAXDELTA (%d)\n", Delta, MAXDELTA); bitmaps->Del(sb, true); + } } else { if (Timeout.TimedOut()) { dbgconverter("cDvbSubtitleConverter::Action: timeout, elapsed %lld\n", Timeout.Elapsed()); @@ -355,6 +397,10 @@ int cDvbSubtitleConverter::Action(void) } } Unlock(); +#if 0 +if (shown) + goto retry; +#endif if(WaitMs != WAITMS) dbgconverter("cDvbSubtitleConverter::Action: finish, WaitMs %d\n", WaitMs); diff --git a/lib/libiw/iwscan.cpp b/lib/libiw/iwscan.cpp index 45efd2b4d..65ee3ff53 100644 --- a/lib/libiw/iwscan.cpp +++ b/lib/libiw/iwscan.cpp @@ -19,6 +19,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* something is fishy with ppc compilers: if vector gets included later from + * iwscan.h it blows up in the c++config.h libstdc++ header... + * probably caused by the redefinition of the "inline" keyword in iwlib.h. */ +#include + #include extern "C" { #include "iwlib.h" /* Header */ diff --git a/lib/libmd5sum/md5.c b/lib/libmd5sum/md5.c index e433782e8..3e7aa83ed 100644 --- a/lib/libmd5sum/md5.c +++ b/lib/libmd5sum/md5.c @@ -96,8 +96,8 @@ md5_finish_ctx (ctx, resbuf) { /* Take yet unprocessed bytes into account. */ md5_uint32 bytes = ctx->buflen; - md5_uint32 swap_bytes; size_t pad; + md5_uint32 *p; /* Now count remaining bytes. */ ctx->total[0] += bytes; @@ -107,13 +107,11 @@ md5_finish_ctx (ctx, resbuf) pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; memmove (&ctx->buffer[bytes], fillbuf, pad); - /* Put the 64-bit file length in *bits* at the end of the buffer. - Use memcpy to avoid aliasing problems. On most systems, this - will be optimized away to the same code. */ - swap_bytes = SWAP (ctx->total[0] << 3); - memcpy (&ctx->buffer[bytes + pad], &swap_bytes, sizeof (swap_bytes)); - swap_bytes = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - memcpy (&ctx->buffer[bytes + pad + 4], &swap_bytes, sizeof (swap_bytes)); + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + p = (md5_uint32 *)&ctx->buffer[bytes + pad]; + *p = SWAP (ctx->total[0] << 3); + p++; + *p = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); /* Process last bytes. */ md5_process_block (ctx->buffer, bytes + pad + 8, ctx); diff --git a/lib/libtriple/Makefile.am b/lib/libtriple/Makefile.am deleted file mode 100644 index 4ac1550ca..000000000 --- a/lib/libtriple/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/src \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/src/zapit/include \ - -I$(top_srcdir)/lib/connection \ - -I$(top_srcdir)/lib/libeventserver \ - @DIRECTFB_CFLAGS@ - -noinst_LIBRARIES = libtriple.a - -AM_CPPFLAGS += -fno-rtti -fno-exceptions - -libtriple_a_SOURCES = \ - dmx_td.cpp \ - video_td.cpp \ - audio_td.cpp \ - init_td.cpp \ - playback_td.cpp \ - pwrmngr.cpp \ - record_td.cpp - -#libtriple_a_LIBADD = $(top_builddir)/src/driver/libneutrino_driver.a diff --git a/lib/libtriple/cs_api.h b/lib/libtriple/cs_api.h deleted file mode 100644 index 5512b928d..000000000 --- a/lib/libtriple/cs_api.h +++ /dev/null @@ -1,66 +0,0 @@ -/* compatibility header for tripledragon. I'm lazy, so I just left it - as "cs_api.h" so that I don't need too many ifdefs in the code */ - -#ifndef __CS_API_H_ -#define __CS_API_H_ - -#include "init_td.h" -typedef void (*cs_messenger) (unsigned int msg, unsigned int data); - -#if 0 -enum CS_LOG_MODULE { - CS_LOG_CI = 0, - CS_LOG_HDMI_CEC, - CS_LOG_HDMI, - CS_LOG_VIDEO, - CS_LOG_VIDEO_DRM, - CS_LOG_AUDIO, - CS_LOG_DEMUX, - CS_LOG_DENC, - CS_LOG_PVR_RECORD, - CS_LOG_PVR_PLAY, - CS_LOG_POWER_CTRL, - CS_LOG_POWER_CLK, - CS_LOG_MEM, - CS_LOG_API, -}; -#endif - -inline void cs_api_init() -{ - init_td_api(); -}; - -inline void cs_api_exit() -{ - shutdown_td_api(); -}; - -#define cs_malloc_uncached malloc -#define cs_free_uncached free - -// Callback function helpers -static inline void cs_register_messenger(cs_messenger) { return; }; -static inline void cs_deregister_messenger(void) { return; }; -//cs_messenger cs_get_messenger(void); - -#if 0 -// Logging functions -void cs_log_enable(void); -void cs_log_disable(void); -void cs_log_message(const char *prefix, const char *fmt, ...); -void cs_log_module_enable(enum CS_LOG_MODULE module); -void cs_log_module_disable(enum CS_LOG_MODULE module); -void cs_log_module_message(enum CS_LOG_MODULE module, const char *fmt, ...); - -// TS Routing -unsigned int cs_get_ts_output(void); -int cs_set_ts_output(unsigned int port); - -// Serial nr and revision accessors -unsigned long long cs_get_serial(void); -#endif -/* compat... HD1 seems to be version 6. everything newer ist > 6... */ -static unsigned int cs_get_revision(void) { return 1; }; -extern int cnxt_debug; -#endif //__CS_API_H_ diff --git a/lib/libtriple/init_cs.h b/lib/libtriple/init_cs.h deleted file mode 100644 index 5894a14d0..000000000 --- a/lib/libtriple/init_cs.h +++ /dev/null @@ -1,2 +0,0 @@ -#warning using init_cs.h from libtriple -#include "init_td.h" diff --git a/lib/libtriple/init_td.cpp b/lib/libtriple/init_td.cpp deleted file mode 100644 index d56714bf3..000000000 --- a/lib/libtriple/init_td.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include - -#include "init_td.h" -#include -#include -#include -#include -#include -#include - -#include - -extern "C" { -#include -#include -#include -} - -static const char * FILENAME = "init_td.cpp"; - -static bool initialized = false; - -/* the super interface */ -static IDirectFB *dfb; -/* the primary surface */ -static IDirectFBSurface *primary; -static IDirectFBSurface *dest; -static IDirectFBDisplayLayer *layer; - -#define DFBCHECK(x...) \ - err = x; \ - if (err != DFB_OK) { \ - fprintf(stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ - DirectFBErrorFatal(#x, err ); \ - } - -static void dfb_init() -{ - int argc = 0; - DFBResult err; - DFBSurfaceDescription dsc; - DFBSurfacePixelFormat pixelformat; - int SW, SH; - - DFBCHECK(DirectFBInit(&argc, NULL)); - /* neutrino does its own VT handling */ - DirectFBSetOption("no-vt-switch", NULL); - DirectFBSetOption("no-vt", NULL); - /* signal handling seems to interfere with neutrino */ - DirectFBSetOption("no-sighandler", NULL); - /* if DirectFB grabs the remote, neutrino does not get events */ - DirectFBSetOption("disable-module", "tdremote"); - DirectFBSetOption("disable-module", "keyboard"); - DirectFBSetOption("disable-module", "linux_input"); - DFBCHECK(DirectFBCreate(&dfb)); - - err = dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN); - if (err) - DirectFBError("Failed to get exclusive access", err); - - dsc.flags = DSDESC_CAPS; - dsc.caps = DSCAPS_PRIMARY; - - DFBCHECK(dfb->CreateSurface( dfb, &dsc, &primary )); - /* set pixel alpha mode */ - dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer); - DFBCHECK(layer->SetCooperativeLevel(layer, DLSCL_EXCLUSIVE)); - DFBDisplayLayerConfig conf; - DFBCHECK(layer->GetConfiguration(layer, &conf)); - conf.flags = DLCONF_OPTIONS; - conf.options = (DFBDisplayLayerOptions)((conf.options & ~DLOP_OPACITY) | DLOP_ALPHACHANNEL); - DFBCHECK(layer->SetConfiguration(layer, &conf)); - - primary->GetPixelFormat(primary, &pixelformat); - primary->GetSize(primary, &SW, &SH); - primary->Clear(primary, 0, 0, 0, 0); - primary->GetSubSurface(primary, NULL, &dest); - dest->Clear(dest, 0, 0, 0, 0); -} - -static void dfb_deinit() -{ - dest->Release(dest); - primary->Release(primary); - layer->Release(layer); - dfb->Release(dfb); -} - -static void rc_init() -{ - /* set remote control address from bootloader config */ - int fd = open("/dev/stb/tdsystem", O_RDWR); - struct BIOS_CONFIG_AREA bca; - unsigned short rc_addr = 0xff; - if (ioctl(fd, IOC_AVS_GET_LOADERCONFIG, &bca) != 0) - fprintf(stderr, "%s: IOC_AVS_GET_LOADERCONFIG failed: %m\n", __FUNCTION__); - else - rc_addr = bca.ir_adrs; - close(fd); - fd = open("/dev/stb/tdremote", O_RDWR); - if (ioctl(fd, IOC_IR_SET_ADDRESS, rc_addr) < 0) - fprintf(stderr, "%s: IOC_IR_SET_ADDRESS %d failed: %m\n", __FUNCTION__, rc_addr); - /* short delay in the driver improves responsiveness and reduces spurious - "key up" events during zapping */ - //ioctl(fd, IOC_IR_SET_DELAY, 1); TODO: needs more work in rcinput - close(fd); - printf("%s: rc_addr=0x%02hx\n", __FUNCTION__, rc_addr); -} - -void init_td_api() -{ - fprintf(stderr, "%s:%s begin, initialized = %d\n", FILENAME, __FUNCTION__, (int)initialized); - if (!initialized) - { - /* DirectFB does setpgid(0,0), which disconnects us from controlling terminal - and thus disables e.g. ctrl-C. work around that. */ - pid_t pid = getpgid(0); - dfb_init(); - if (setpgid(0, pid)) - perror("setpgid"); - rc_init(); - } - initialized = true; - fprintf(stderr, "%s:%s end\n", FILENAME, __FUNCTION__); -} - -void shutdown_td_api() -{ - fprintf(stderr, "%s:%s, initialized = %d\n", FILENAME, __FUNCTION__, (int)initialized); - if (initialized) - dfb_deinit(); - initialized = false; -} diff --git a/lib/libtriple/init_td.h b/lib/libtriple/init_td.h deleted file mode 100644 index d9a6f0963..000000000 --- a/lib/libtriple/init_td.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __INIT_TD_H -#define __INIT_TD_H -void init_td_api(); -void shutdown_td_api(); -#endif diff --git a/lib/libtriple/playback.h b/lib/libtriple/playback.h deleted file mode 100644 index 6e6b4c5ae..000000000 --- a/lib/libtriple/playback.h +++ /dev/null @@ -1 +0,0 @@ -#include "playback_td.h" diff --git a/lib/libtriple/td-compat/td-audio-compat.h b/lib/libtriple/td-compat/td-audio-compat.h deleted file mode 100644 index 3e0b4a7ff..000000000 --- a/lib/libtriple/td-compat/td-audio-compat.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * compatibility stuff for Tripledragon audio API - * - * (C) 2009 Stefan Seyfried - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __td_audio_compat_h__ -#define __td_audio_compat_h__ - -#include -// types -typedef enum { - AUDIO_SOURCE_DEMUX = AUD_SOURCE_DEMUX, - AUDIO_SOURCE_MEMORY = AUD_SOURCE_MEMORY -} audio_stream_source_t; -#define audio_channel_select_t audChannel_t -// ioctls -#define AUDIO_CHANNEL_SELECT MPEG_AUD_SELECT_CHANNEL -#define AUDIO_SELECT_SOURCE MPEG_AUD_SELECT_SOURCE -#define AUDIO_PLAY MPEG_AUD_PLAY -#define AUDIO_STOP MPEG_AUD_STOP -#define AUDIO_SET_MUTE MPEG_AUD_SET_MUTE - -#endif /* __td_audio_compat_h__ */ diff --git a/lib/libtriple/td-compat/td-demux-compat.h b/lib/libtriple/td-compat/td-demux-compat.h deleted file mode 100644 index 8feacfed3..000000000 --- a/lib/libtriple/td-compat/td-demux-compat.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * compatibility stuff for Tripledragon demux API - * - * (C) 2009 Stefan Seyfried - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __td_demux_compat_h__ -#define __td_demux_compat_h__ - -#include -#include -// types -#define dmx_output_t OutDevice -#define dmx_pes_type_t PesType -#define dmx_sct_filter_params demux_filter_para -#define dmx_pes_filter_params demux_pes_para -#define pes_type pesType -// defines -#define DMX_FILTER_SIZE FILTER_LENGTH -#define DMX_ONESHOT XPDF_ONESHOT -#define DMX_CHECK_CRC 0 // TD checks CRC by default -#define DMX_IMMEDIATE_START XPDF_IMMEDIATE_START -#define DMX_OUT_DECODER OUT_DECODER -// ioctls -#define DMX_SET_FILTER DEMUX_FILTER_SET -#define DMX_SET_PES_FILTER DEMUX_FILTER_PES_SET -#define DMX_START DEMUX_START -#define DMX_STOP DEMUX_STOP -#define DMX_SET_BUFFER_SIZE DEMUX_SET_BUFFER_SIZE - -#endif /* __td_demux_compat_h__ */ diff --git a/lib/libtriple/td-compat/td-frontend-compat.h b/lib/libtriple/td-compat/td-frontend-compat.h deleted file mode 100644 index 46781ce89..000000000 --- a/lib/libtriple/td-compat/td-frontend-compat.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * compatibility stuff for Tripledragon frontend API - * - * (C) 2009 Stefan Seyfried - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __td_frontend_compat_h__ -#define __td_frontend_compat_h__ - -#ifdef __cplusplus -extern "C" { -#endif - #include -#ifdef __cplusplus -} -#endif - -/* I know that those are different. But functions that get a - dvb_frontend_parameters struct passed on dbox/dreambox will most likely - get a tunersetup struct on TD, so it keeps the differences in headers - and function prototypes small. Of course, the functions itself will have - #ifdef TRIPLEDRAGON or similar... */ -#define dvb_frontend_parameters tunersetup - -/* compat stuff for settings.cpp */ -enum { - INVERSION_OFF, - INVERSION_ON, - INVERSION_AUTO -}; -typedef enum fe_code_rate { - FEC_NONE = 0, - FEC_1_2, - FEC_2_3, - FEC_3_4, - FEC_4_5, - FEC_5_6, - FEC_6_7, - FEC_7_8, - FEC_8_9, - FEC_AUTO -} fe_code_rate_t; - -enum td_code_rate { - TD_FEC_AUTO = 0, - TD_FEC_1_2, - TD_FEC_2_3, - TD_FEC_3_4, - TD_FEC_5_6, - TD_FEC_7_8 -}; - -typedef enum fe_sec_tone_mode { - SEC_TONE_ON, - SEC_TONE_OFF -} fe_sec_tone_mode_t; - -typedef enum fe_sec_voltage { - SEC_VOLTAGE_13, - SEC_VOLTAGE_18, - SEC_VOLTAGE_OFF -} fe_sec_voltage_t; - -typedef enum fe_sec_mini_cmd { - SEC_MINI_A, - SEC_MINI_B -} fe_sec_mini_cmd_t; - -struct dvb_diseqc_master_cmd { - unsigned char msg [6]; /* { framing, address, command, data [3] } */ - unsigned char msg_len; /* valid values are 3...6 */ -}; - -typedef enum fe_type { - FE_QPSK, - FE_QAM, - FE_OFDM, - FE_ATSC -} fe_type_t; - -struct dvb_frontend_info { -// char name[128]; - fe_type_t type; -#if 0 - __u32 frequency_min; - __u32 frequency_max; - __u32 frequency_stepsize; - __u32 frequency_tolerance; - __u32 symbol_rate_min; - __u32 symbol_rate_max; - __u32 symbol_rate_tolerance; /* ppm */ - __u32 notifier_delay; /* DEPRECATED */ - fe_caps_t caps; -#endif -}; - -struct dvb_frontend_event { - fe_status_t status; - tunersetup parameters; -}; - -#ifdef _DVBFRONTEND_H_ -#error _DVBFRONTEND_H_ included -#endif - -#endif /* __td_frontend_compat_h__ */ diff --git a/lib/libtriple/td-compat/td-value-compat.h b/lib/libtriple/td-compat/td-value-compat.h deleted file mode 100644 index f7bb9523c..000000000 --- a/lib/libtriple/td-compat/td-value-compat.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * compatibility stuff for conversion of Tripledragon API values to DVB API - * and vice versa - * - * (C) 2009 Stefan Seyfried - * - * Released under the GPL V2. - */ - -#ifndef _td_value_compat_ -#define _td_value_compat_ - -#undef FE_GET_INFO -#undef FE_READ_BER -#undef FE_READ_SIGNAL_STRENGTH -#undef FE_READ_SNR -#undef FE_READ_UNCORRECTED_BLOCKS -#undef FE_GET_EVENT -#undef FE_READ_STATUS -#undef FE_SET_PROPERTY -#undef FE_GET_EVENT -#undef FE_GET_EVENT -#undef FE_SET_PROPERTY -#undef FE_SET_TONE -#undef FE_ENABLE_HIGH_LNB_VOLTAGE -#undef FE_SET_VOLTAGE -#undef FE_DISEQC_SEND_MASTER_CMD -#undef FE_DISEQC_SEND_BURST -/* hack, linux/dvb/frontend.h already defines fe_status */ -#define fe_status td_fe_status -#define fe_status_t td_fe_status_t -#define FE_HAS_SIGNAL TD_FE_HAS_SIGNAL -#define FE_HAS_CARRIER TD_FE_HAS_CARRIER -#define FE_HAS_VITERBI TD_FE_HAS_VITERBI -#define FE_HAS_SYNC TD_FE_HAS_SYNC -#define FE_HAS_LOCK TD_FE_HAS_LOCK -#define FE_TIMEDOUT TD_FE_TIMEDOUT -#define FE_REINIT TD_FE_REINIT -#include -#undef fe_status -#undef fe_status_t -#undef FE_HAS_SIGNAL -#undef FE_HAS_CARRIER -#undef FE_HAS_VITERBI -#undef FE_HAS_SYNC -#undef FE_HAS_LOCK -#undef FE_TIMEDOUT -#undef FE_REINIT -enum td_code_rate { - TD_FEC_AUTO = 0, - TD_FEC_1_2, - TD_FEC_2_3, - TD_FEC_3_4, - TD_FEC_5_6, - TD_FEC_7_8 -}; - -static inline unsigned int dvbfec2tdfec(fe_code_rate_t fec) -{ - switch (fec) { - case FEC_1_2: // FEC_1_2 ... FEC_3_4 are equal to TD_FEC_1_2 ... TD_FEC_3_4 - case FEC_2_3: - case FEC_3_4: - return (unsigned int)fec; - case FEC_5_6: - return TD_FEC_5_6; - case FEC_7_8: - return TD_FEC_7_8; - default: - break; - } - return TD_FEC_AUTO; -} - -static inline fe_code_rate_t tdfec2dvbfec(unsigned int tdfec) -{ - switch (tdfec) - { - case TD_FEC_1_2: - case TD_FEC_2_3: - case TD_FEC_3_4: - return (fe_code_rate_t)tdfec; - case TD_FEC_5_6: - return FEC_5_6; - case TD_FEC_7_8: - return FEC_7_8; - default: - break; - } - return FEC_AUTO; -} - -#endif /* _td_value_compat_ */ diff --git a/lib/libtriple/td-compat/td-video-compat.h b/lib/libtriple/td-compat/td-video-compat.h deleted file mode 100644 index 137a3467a..000000000 --- a/lib/libtriple/td-compat/td-video-compat.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * compatibility stuff for Tripledragon video API - * - * (C) 2009 Stefan Seyfried - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __td_video_compat_h__ -#define __td_video_compat_h__ - -#include -// types -#define video_format_t vidDispSize_t -#define video_displayformat_t vidDispMode_t -typedef enum { - VIDEO_SOURCE_DEMUX = VID_SOURCE_DEMUX, - VIDEO_SOURCE_MEMORY = VID_SOURCE_MEMORY -} video_stream_source_t; -typedef enum { - VIDEO_STOPPED, /* Video is stopped */ - VIDEO_PLAYING, /* Video is currently playing */ - VIDEO_FREEZED /* Video is freezed */ -} video_play_state_t; -//#define video_play_state_t vidState_t -// ioctls -#define VIDEO_SET_SYSTEM MPEG_VID_SET_DISPFMT -#define VIDEO_SET_FORMAT MPEG_VID_SET_DISPSIZE -#define VIDEO_SET_DISPLAY_FORMAT MPEG_VID_SET_DISPMODE -#define VIDEO_SELECT_SOURCE MPEG_VID_SELECT_SOURCE -#define VIDEO_PLAY MPEG_VID_PLAY -#define VIDEO_STOP MPEG_VID_STOP -#define VIDEO_SET_BLANK MPEG_VID_SET_BLANK - -#endif /* __td_video_compat_h__ */ diff --git a/lib/libtuxtxt/Makefile.am b/lib/libtuxtxt/Makefile.am index 7ea232ad1..f40d16044 100644 --- a/lib/libtuxtxt/Makefile.am +++ b/lib/libtuxtxt/Makefile.am @@ -1,6 +1,8 @@ AM_CPPFLAGS = \ -I$(top_builddir) \ -I$(top_srcdir) \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/lib/libconfigfile \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/zapit/include \ $(FREETYPE_CFLAGS) \ diff --git a/lib/libtuxtxt/libtuxtxt.cpp b/lib/libtuxtxt/libtuxtxt.cpp index 27111f618..40af36282 100644 --- a/lib/libtuxtxt/libtuxtxt.cpp +++ b/lib/libtuxtxt/libtuxtxt.cpp @@ -37,6 +37,8 @@ int tuxtxt_init() tuxtxt_cache.vtxtpid = -1; tuxtxt_cache.thread_id = 0; tuxtxt_cache.dmx = -1; + /* not sure if this is correct here... */ + tuxtxt_cache.page = 0x100; return 1;//tuxtxt_init_demuxer(); } diff --git a/lib/libtuxtxt/tuxtxt.cpp b/lib/libtuxtxt/tuxtxt.cpp index 67890f7c9..c2e2a7a21 100644 --- a/lib/libtuxtxt/tuxtxt.cpp +++ b/lib/libtuxtxt/tuxtxt.cpp @@ -11,6 +11,8 @@ * * * ported 2009 to HD1 by Coolstream LTD * * * + * TD, SPARK and AZbox port (C) 2010-2013 Stefan Seyfried * + * * ******************************************************************************/ #include "teletext.h" @@ -19,12 +21,19 @@ #include #include #include +#include /* same as in rcinput.h... */ #define KEY_TTTV KEY_FN_1 #define KEY_TTZOOM KEY_FN_2 #define KEY_REVEAL KEY_FN_D +#ifdef HAVE_SPARK_HARDWARE +#define MARK_FB(a, b, c, d) if (p == lfb) CFrameBuffer::getInstance()->mark(a, b, (a) + (c), (b) + (d)) +#else +#define MARK_FB(a, b, c, d) +#endif + extern cVideo * videoDecoder; static pthread_t ttx_sub_thread; @@ -35,11 +44,24 @@ static int sub_pid, sub_page; static bool use_gui; static int cfg_national_subset; +static int screen_x, screen_y, screen_w, screen_h; + //#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver +unsigned char *getFBp(int *y) +{ + if (*y < (int)var_screeninfo.yres) + return lfb; + + *y -= var_screeninfo.yres; + return lbb; +} + void FillRect(int x, int y, int w, int h, int color) { - unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x*4 + y * fix_screeninfo.line_length; #if !HAVE_TRIPLEDRAGON unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0]; #else @@ -54,6 +76,7 @@ void FillRect(int x, int y, int w, int h, int color) } } + void FillBorder(int color) { int ys = (var_screeninfo.yres-var_screeninfo.yoffset); @@ -179,7 +202,6 @@ int toptext_getnext(int startpage, int up, int findgroup) nextgrp = nextblk = 0; current = startpage; - //NI if (startpage == 0) return 0; @@ -223,6 +245,13 @@ void RenderClearMenuLineBB(char *p, tstPageAttr *attrcol, tstPageAttr *attr) #if 0 RenderCharBB(' ', attr); /* separator */ #endif + /* the fontwidth_topmenusmall is not correctly calculated: the navigation + * indicator ' ' is not considered and thus the font is slightly too wide. + * Shift the topmenu to the left instead of using a smaller font, since + * the worst that can happen is that the indicator is partly obscured and + * that looks better than empty space on the right of the topmenu. + */ + PosX = screen_x + screen_w - TOPMENUCHARS * fontwidth_topmenusmall; for(col = 0; col < TOPMENUCHARS; col++) { RenderCharBB(*p++, attr); @@ -245,7 +274,8 @@ void ClearFB(int /*color*/) //never used void ClearB(int color) { - FillRect(0,0,var_screeninfo.xres,var_screeninfo.yres*2,color); + FillRect(0, 0, var_screeninfo.xres, var_screeninfo.yres, color); /* framebuffer */ + FillRect(0, var_screeninfo.yres, var_screeninfo.xres, var_screeninfo.yres, color); /* backbuffer */ } #endif int GetCurFontWidth() @@ -253,6 +283,7 @@ int GetCurFontWidth() int mx = (displaywidth)%(40-nofirst); // # of unused pixels int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert + return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0); } @@ -1537,7 +1568,7 @@ static void* reader_thread(void * /*arg*/) void tuxtx_pause_subtitle(bool pause) { if(!pause) { - printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page); + //printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page); ttx_paused = 0; if(!reader_running && sub_pid && sub_page) tuxtx_main(0, sub_pid, sub_page); @@ -1574,8 +1605,8 @@ void tuxtx_set_pid(int pid, int page, const char * cc) sub_page = page; cfg_national_subset = GetNationalSubset(cc); - printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset); #if 0 + printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset); ttx_paused = 1; if(sub_pid && sub_page) tuxtx_main(0, sub_pid, sub_page); @@ -1599,7 +1630,7 @@ int tuxtx_subtitle_running(int *pid, int *page, int *running) return ret; } -int tuxtx_main(int _rc, int pid, int page, int source) +int tuxtx_main(int /*_rc*/, int pid, int page, int source) { char cvs_revision[] = "$Revision: 1.95 $"; @@ -1623,14 +1654,18 @@ int tuxtx_main(int _rc, int pid, int page, int source) printf("TuxTxt %s\n", versioninfo); printf("for 32bpp framebuffer\n"); + fb = -1; +#ifdef USE_FBPAN if ((fb=open("/dev/fb/0", O_RDWR)) == -1) { perror("TuxTxt "); return 0; } +#endif - rc = _rc; - lfb = (unsigned char *) CFrameBuffer::getInstance()->getFrameBufferPointer(); + CFrameBuffer *fbp = CFrameBuffer::getInstance(); + lfb = (unsigned char *)fbp->getFrameBufferPointer(); + lbb = (unsigned char *)fbp->getBackBufferPointer(); tuxtxt_cache.vtxtpid = pid; @@ -1639,8 +1674,7 @@ int tuxtx_main(int _rc, int pid, int page, int source) else printf("[tuxtxt] using PID %x page %d\n", tuxtxt_cache.vtxtpid, tuxtxt_cache.page); - fcntl(rc, F_SETFL, fcntl(rc, F_GETFL) | O_EXCL | O_NONBLOCK); - +#if 0 /* just get it from the framebuffer class */ /* get fixed screeninfo */ if (ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1) { @@ -1654,7 +1688,12 @@ int tuxtx_main(int _rc, int pid, int page, int source) perror("TuxTxt "); return 0; } - +#else + struct fb_var_screeninfo *var; + var = fbp->getScreenInfo(); + memcpy(&var_screeninfo, var, sizeof(struct fb_var_screeninfo)); + fix_screeninfo.line_length = var_screeninfo.xres * sizeof(fb_pixel_t); +#endif /* set variable screeninfo for double buffering */ var_screeninfo.yoffset = 0; #if 0 @@ -1663,10 +1702,15 @@ int tuxtx_main(int _rc, int pid, int page, int source) ex = x + w - 10; ey = y + h - 10; #endif - int x = CFrameBuffer::getInstance()->getScreenX(); - int y = CFrameBuffer::getInstance()->getScreenY(); - int w = CFrameBuffer::getInstance()->getScreenWidth(); - int h = CFrameBuffer::getInstance()->getScreenHeight(); + screen_x = fbp->getScreenX(); + screen_y = fbp->getScreenY(); + screen_w = fbp->getScreenWidth(); + screen_h = fbp->getScreenHeight(); + + int x = screen_x; + int y = screen_y; + int w = screen_w; + int h = screen_h; int tx = 0; if (!screen_mode1) @@ -1727,6 +1771,7 @@ int tuxtx_main(int _rc, int pid, int page, int source) SwitchTranspMode(); break; /* and evaluate key */ + case RC_TTTV: case RC_MUTE: /* regular toggle to transparent */ case RC_TEXT: break; @@ -1799,20 +1844,25 @@ int tuxtx_main(int _rc, int pid, int page, int source) case RC_7: case RC_8: case RC_9: - PageInput(RCCode - RC_0); + PageInput(CRCInput::getNumericValue(RCCode)); break; case RC_RED: ColorKey(prev_100); break; case RC_GREEN: ColorKey(prev_10); break; case RC_YELLOW: ColorKey(next_10); break; case RC_BLUE: ColorKey(next_100); break; + case RC_TTZOOM: case RC_PLUS: SwitchZoomMode(); break; + case RC_SPLIT: case RC_MINUS: SwitchScreenMode(-1);prevscreenmode = screenmode; break; + case RC_TTTV: case RC_MUTE: SwitchTranspMode(); break; case RC_TEXT: if(transpmode == 1) RCCode = RC_HOME; SwitchTranspMode(); break; + case RC_TTREVEAL: + case RC_INFO: case RC_HELP: SwitchHintMode(); break; case RC_DBOX: ConfigMenu(0); break; case RC_HOME: @@ -1829,7 +1879,8 @@ int tuxtx_main(int _rc, int pid, int page, int source) /* exit */ CleanUp(); - close(fb); + if (fb >= 0) + close(fb); #if 1 if ( initialized ) @@ -1865,10 +1916,10 @@ FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library plibrary, FT_Pointer /*r ******************************************************************************/ extern std::string ttx_font_file; static bool ft_init_done = false; +static int oldfontheight = 0; int Init(int source) { int error, i; - unsigned char magazine; static std::string font_file; /* init data */ @@ -1876,12 +1927,13 @@ int Init(int source) //page_atrb[32] = transp<<4 | transp; inputcounter = 2; +#if TUXTXT_CFG_STANDALONE + unsigned char magazine; for (magazine = 1; magazine < 9; magazine++) { tuxtxt_cache.current_page [magazine] = -1; tuxtxt_cache.current_subpage [magazine] = -1; } -#if TUXTXT_CFG_STANDALONE /* init data */ memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable)); memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable)); @@ -2031,7 +2083,7 @@ int Init(int source) fontwidth_topmenumain = (TV43STARTX-sx) / 40; fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; //fontwidth_small = (TV169FULLSTARTX-sx) / 40; - fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / 40; + fontwidth_small = (screen_w / 2) / 40; ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */ ymosaic[1] = (fontheight + 1) / 3; ymosaic[2] = (fontheight * 2 + 1) / 3; @@ -2073,7 +2125,7 @@ int Init(int source) } } #endif - if(!ft_init_done || font_file != ttx_font_file) { + if(!ft_init_done || font_file != ttx_font_file || fontheight != oldfontheight) { printf("TuxTxt: init fontlibrary\n"); if(ft_init_done) { FTC_Manager_Done(manager); @@ -2123,6 +2175,7 @@ int Init(int source) } font_file = ttx_font_file; ft_init_done = true; + oldfontheight = fontheight; ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16); } @@ -2195,7 +2248,6 @@ int Init(int source) #else tuxtxt_start(tuxtxt_cache.vtxtpid, source); #endif - fcntl(rc, F_SETFL, O_NONBLOCK); gethotlist(); if(use_gui) @@ -2789,7 +2841,7 @@ void Menu_Init(char *menu, int current_pid, int menuitem, int hotindex) void ConfigMenu(int Init) { - int val, menuitem = M_Start; + int menuitem = M_Start; int current_pid = 0; int hotindex; int oldscreenmode, oldtrans = 0; @@ -2843,23 +2895,18 @@ void ConfigMenu(int Init) clearbbcolor = black; Menu_Init(menu, current_pid, menuitem, hotindex); - /* set blocking mode */ - val = fcntl(rc, F_GETFL); - fcntl(rc, F_SETFL, val &~ O_NONBLOCK); - /* loop */ do { if (GetRCCode() == 1) { + int rc_num = -1; - if ( -#if (RC_1 > 0) - RCCode >= RC_1 && /* generates a warning... */ -#endif - RCCode <= RC_1+M_MaxDirect) /* direct access */ + if (CRCInput::isNumeric(RCCode)) + rc_num = CRCInput::getNumericValue(RCCode) -1; /* valid: 1 to M_MaxDirect */ + if (rc_num >= 0 && rc_num <= M_MaxDirect) /* direct access */ { Menu_HighlightLine(menu, MenuLine[menuitem], 0); - menuitem = RCCode-RC_1; + menuitem = rc_num; Menu_HighlightLine(menu, MenuLine[menuitem], 1); if (menuitem != M_PID) /* just select */ @@ -3320,7 +3367,6 @@ void ConfigMenu(int Init) current_service = current_pid; // RenderMessage(ShowServiceName); - fcntl(rc, F_SETFL, O_NONBLOCK); RCCode = -1; if (oldscreenmode) SwitchScreenMode(oldscreenmode); /* restore divided screen */ @@ -3381,8 +3427,6 @@ void ConfigMenu(int Init) ClearBB(transp); CopyBB2FB(); - /* reset to nonblocking mode */ - fcntl(rc, F_SETFL, O_NONBLOCK); tuxtxt_cache.pageupdate = 1; RCCode = -1; if (oldscreenmode) @@ -3597,7 +3641,7 @@ void ColorKey(int target) void PageCatching() { - int val, byte; + int byte; int oldzoommode = zoommode; pagecatching = 1; @@ -3627,10 +3671,6 @@ void PageCatching() return; } - /* set blocking mode */ - val = fcntl(rc, F_GETFL); - fcntl(rc, F_SETFL, val &~ O_NONBLOCK); - /* loop */ do { GetRCCode(); @@ -3669,7 +3709,6 @@ void PageCatching() case RC_HOME: case RC_HELP: case RC_MUTE: - fcntl(rc, F_SETFL, O_NONBLOCK); tuxtxt_cache.pageupdate = 1; pagecatching = 0; RCCode = -1; @@ -3693,9 +3732,6 @@ void PageCatching() tuxtxt_cache.subpage = subp; else tuxtxt_cache.subpage = 0; - - /* reset to nonblocking mode */ - fcntl(rc, F_SETFL, O_NONBLOCK); } /****************************************************************************** @@ -3927,9 +3963,9 @@ void SwitchScreenMode(int newscreenmode) if (screenmode==1) /* split with topmenu */ { - int x = CFrameBuffer::getInstance()->getScreenX(); - int w = CFrameBuffer::getInstance()->getScreenWidth(); - int h = CFrameBuffer::getInstance()->getScreenHeight(); + int x = screen_x; + int w = screen_w; + int h = screen_h; fw = fontwidth_topmenumain; tx = 0; /* split means we start at the left edge */ @@ -3956,18 +3992,20 @@ void SwitchScreenMode(int newscreenmode) } else /* 2: split with full height tv picture */ { - StartX = CFrameBuffer::getInstance()->getScreenX(); + StartX = screen_x; fw = fontwidth_small; tx = TV169FULLSTARTX; ty = TV169FULLSTARTY; tw = TV169FULLWIDTH; th = TV169FULLHEIGHT; - displaywidth = CFrameBuffer::getInstance()->getScreenWidth()/2; + displaywidth = screen_w / 2; } setfontwidth(fw); - videoDecoder->Pig(tx, ty, tw, th, CFrameBuffer::getInstance()->getScreenWidth(true), CFrameBuffer::getInstance()->getScreenHeight(true)); + CFrameBuffer *f = CFrameBuffer::getInstance(); + videoDecoder->Pig(tx, ty, tw, th, + f->getScreenWidth(true), f->getScreenHeight(true)); #if 0 int sm = 0; ioctl(pig, VIDIOC_OVERLAY, &sm); @@ -3989,8 +4027,8 @@ void SwitchScreenMode(int newscreenmode) #endif videoDecoder->Pig(-1, -1, -1, -1); - int x = CFrameBuffer::getInstance()->getScreenX(); - int w = CFrameBuffer::getInstance()->getScreenWidth(); + int x = screen_x; + int w = screen_w; //int h = CFrameBuffer::getInstance()->getScreenHeight(); int tx = 0; /* see comment above on the TTX window dimensions */ @@ -4133,7 +4171,9 @@ void RenderDRCS( //FIX ME void DrawVLine(int x, int y, int l, int color) { - unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, 0, l); + p += x*4 + y * fix_screeninfo.line_length; for ( ; l > 0 ; l--) { @@ -4145,11 +4185,13 @@ void DrawVLine(int x, int y, int l, int color) void DrawHLine(int x, int y, int l, int color) { int ltmp; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, l, 0); if (l > 0) { for (ltmp=0; ltmp <= l; ltmp++) { - memmove(lfb + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); + memmove(p + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4); } } } @@ -4165,7 +4207,10 @@ void FillRectMosaicSeparated(int x, int y, int w, int h, int fgcolor, int bgcolo void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) { - unsigned char *p = lfb + x0*4 + y0 * fix_screeninfo.line_length; + unsigned char *p = getFBp(&y0); + MARK_FB(x0, y0, l0, h); + p += x0 * 4 + y0 * fix_screeninfo.line_length; + int xoffset, l; int yoffset; int ltmp; @@ -4187,7 +4232,10 @@ void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color) void FlipHorz(int x, int y, int w, int h) { unsigned char *buf= new unsigned char[w*4]; - unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x * 4 + y * fix_screeninfo.line_length; + int w1,h1; if(buf != NULL){ for (h1 = 0 ; h1 < h ; h1++) @@ -4205,7 +4253,11 @@ void FlipHorz(int x, int y, int w, int h) void FlipVert(int x, int y, int w, int h) { unsigned char *buf= new unsigned char[w*4]; - unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length, *p1, *p2; + unsigned char *p1, *p2; + unsigned char *p = getFBp(&y); + MARK_FB(x, y, w, h); + p += x*4 + y * fix_screeninfo.line_length; + int h1; if(buf != NULL){ for (h1 = 0 ; h1 < h/2 ; h1++) @@ -4466,7 +4518,11 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset) else if (*aShapes[Char - 0x20] == S_ADT) { int x,y,f,c; - unsigned char* p = lfb + PosX*4 + (PosY+yoffset)* fix_screeninfo.line_length; + y = yoffset; + unsigned char *p = getFBp(&y); + MARK_FB(PosX, PosY, curfontwidth, fontheight); + p += PosX * 4 + PosY * fix_screeninfo.line_length; + for (y=0; ytop + TTFShiftY + sbit->height > fontheight) sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */ + int y = yoffset; + p = getFBp(&y); + p += PosX * 4 + (PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */ - p = lfb + PosX*4 + (yoffset + PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */ for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */ { int pixtodo = (usettf ? sbit->width : curfontwidth); @@ -5119,8 +5179,8 @@ void DoFlashing(int startrow) } PosY += fontheight*factor; } - } + void RenderPage() { int row, col, byte, startrow = 0;; @@ -5191,7 +5251,7 @@ void RenderPage() fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst); fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS; //fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst); - fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / (40-nofirst); + fontwidth_small = (screen_w / 2) / (40 - nofirst); switch(screenmode) { case 0: @@ -5199,7 +5259,7 @@ void RenderPage() displaywidth = ex - sx; break; case 2: setfontwidth(fontwidth_small); - displaywidth = CFrameBuffer::getInstance()->getScreenWidth() / 2; + displaywidth = screen_w / 2; break; } if (transpmode || (boxed && !screenmode)) @@ -5442,7 +5502,7 @@ void CreateLine25() showlink(3, next_100); } - if (//tuxtxt_cache.bttok && + if (tuxtxt_cache.bttok && screenmode == 1) /* TOP-Info present, divided screen -> create TOP overview */ { char line[TOPMENUCHARS]; @@ -5552,6 +5612,9 @@ void CopyBB2FB() { unsigned char *src, *dst, *topsrc; int fillcolor, i, screenwidth, swtmp; +#ifdef HAVE_SPARK_HARDWARE + CFrameBuffer *f = CFrameBuffer::getInstance(); +#endif /* line 25 */ if (!pagecatching && use_gui) @@ -5572,12 +5635,16 @@ void CopyBB2FB() if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1) perror("TuxTxt "); #else - memmove(lfb, lfb+fix_screeninfo.line_length * var_screeninfo.yres, fix_screeninfo.line_length*var_screeninfo.yres); +#ifdef HAVE_SPARK_HARDWARE + f->blit2FB(lbb, var_screeninfo.xres, var_screeninfo.yres, 0, 0, 0, 0, true); +#else + memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres); +#endif #endif /* adapt background of backbuffer if changed */ - if (StartX > 0 && *lfb != *(lfb + fix_screeninfo.line_length * var_screeninfo.yres)) { - FillBorder(*(lfb + fix_screeninfo.line_length * var_screeninfo.yoffset)); + if (StartX > 0 && *lfb != *lbb) { + FillBorder(*lbb); // ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset)); } @@ -5589,8 +5656,11 @@ void CopyBB2FB() return; } - src = dst = topsrc = lfb + StartY*fix_screeninfo.line_length; + src = topsrc = lbb + StartY * fix_screeninfo.line_length; + dst = lfb + StartY * fix_screeninfo.line_length; +#ifdef USE_FBPAN + #error USE_FBPAN code is not working right now. if (var_screeninfo.yoffset) dst += fix_screeninfo.line_length * var_screeninfo.yres; else @@ -5598,6 +5668,7 @@ void CopyBB2FB() src += fix_screeninfo.line_length * var_screeninfo.yres; topsrc += fix_screeninfo.line_length * var_screeninfo.yres; } +#endif /* copy line25 in normal height */ if (!pagecatching ) memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight); @@ -5613,9 +5684,15 @@ void CopyBB2FB() /* copy topmenu in normal height (since PIG also keeps dimensions) */ if (screenmode == 1) { - unsigned char *topdst = dst; - screenwidth = ( TV43STARTX ) * 4; +#ifdef HAVE_SPARK_HARDWARE + int cx = var_screeninfo.xres - TV43STARTX; /* x start */ + int cw = TV43STARTX; /* width */ + int cy = StartY; + int ch = 24*fontheight; + f->blit2FB(lbb, cw, ch, cx, cy, cx, cy, true); +#else + unsigned char *topdst = dst; size_t width = ex * sizeof(fb_pixel_t) - screenwidth; topsrc += screenwidth; @@ -5626,6 +5703,7 @@ void CopyBB2FB() topdst += fix_screeninfo.line_length; topsrc += fix_screeninfo.line_length; } +#endif } else if (screenmode == 2) screenwidth = ( TV169FULLSTARTX ) * 4; @@ -5656,6 +5734,9 @@ void CopyBB2FB() memmove(dst + fix_screeninfo.line_length*(fontheight+i)+swtmp*4, bgra[fillcolor], 4); } } +#ifdef HAVE_SPARK_HARDWARE + f->mark(0, 0, var_screeninfo.xres, var_screeninfo.yres); +#endif } /****************************************************************************** @@ -6345,6 +6426,21 @@ void DecodePage() /****************************************************************************** * GetRCCode * ******************************************************************************/ +int GetRCCode() +{ + neutrino_msg_t msg; + neutrino_msg_data_t data; + g_RCInput->getMsg_ms(&msg, &data, 40); + RCCode = -1; + + if (msg <= CRCInput::RC_MaxRC) { + RCCode = msg; + return 1; + } + return 0; +} + +#if 0 #if 1 int GetRCCode() { @@ -6418,7 +6514,7 @@ printf("[tuxtxt] new key, code %X\n", RCCode); } RCCode = -1; - usleep(1000000/100); + usleep(1000000/25); return 0; } @@ -6483,6 +6579,7 @@ int GetRCCode() return 1; } #endif +#endif /* Local Variables: */ /* indent-tabs-mode:t */ /* tab-width:3 */ diff --git a/lib/libtuxtxt/tuxtxt.h b/lib/libtuxtxt/tuxtxt.h index 6a46e1fc7..1a6974c86 100644 --- a/lib/libtuxtxt/tuxtxt.h +++ b/lib/libtuxtxt/tuxtxt.h @@ -12,6 +12,8 @@ * ported 2006 to Dreambox 7025 / 32Bit framebuffer * * by Seddi * * * + * * + * ported to Tripledragon, SPARK and AZbox 2010-2013 Stefan Seyfried * ******************************************************************************/ #define TUXTXT_CFG_STANDALONE 0 // 1:plugin only 0:use library @@ -42,6 +44,8 @@ #include FT_CACHE_H #include FT_CACHE_SMALL_BITMAPS_H +#include + /* devices */ #if TUXTXT_CFG_STANDALONE @@ -82,20 +86,19 @@ int tv_pip_y; #define fontwidth_small_lcd 8 #define TV43STARTX (ex) -#define TVENDX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()) //ex +#define TVENDX (screen_x + screen_w) //ex // #define TVENDY (StartY + 25*fontheight) // #define TV43WIDTH (TVENDX - TV43STARTX) // #define TV43HEIGHT (TV43WIDTH *9/16) // #define TV43STARTY (TVENDY - TV43HEIGHT) //#define TV169FULLSTARTX (sx+ 8*40) //(sx +(ex +1 - sx)/2) -#define TV169FULLSTARTX (CFrameBuffer::getInstance()->getScreenX() + CFrameBuffer::getInstance()->getScreenWidth()/2) +#define TV169FULLSTARTX (screen_x + screen_w / 2) #define TV169FULLSTARTY sy //#define TV169FULLWIDTH (ex - sx)/2 -#define TV169FULLWIDTH (CFrameBuffer::getInstance()->getScreenWidth()/2) +#define TV169FULLWIDTH (screen_w / 2) #define TV169FULLHEIGHT (ey - sy) - -#define TOPMENUSTARTX TV43STARTX+2 +#define TOPMENUSTARTX (TV43STARTX+2) //#define TOPMENUENDX TVENDX #define TOPMENUSTARTY StartY #define TOPMENUENDY TV43STARTY @@ -105,7 +108,7 @@ int tv_pip_y; #define TOPMENUINDENTGRP 1 #define TOPMENUINDENTDEF 2 #define TOPMENUSPC 0 -#define TOPMENUCHARS (TOPMENUINDENTDEF+12+TOPMENUSPC+3) //NI +#define TOPMENUCHARS (TOPMENUINDENTDEF+12+TOPMENUSPC+3) #define FLOFSIZE 4 @@ -143,6 +146,7 @@ int tv_pip_y; #define hold_mosaic 0x1E #define release_mosaic 0x1F +#if 0 /* rc codes */ #define RC_0 0x00 #define RC_1 0x01 @@ -171,6 +175,48 @@ int tv_pip_y; #define RC_DBOX 0x18 #define RC_TEXT 0x19 #define RC_HOME 0x1F +#else +#define RC_0 CRCInput::RC_0 +#define RC_1 CRCInput::RC_1 +#define RC_2 CRCInput::RC_2 +#define RC_3 CRCInput::RC_3 +#define RC_4 CRCInput::RC_4 +#define RC_5 CRCInput::RC_5 +#define RC_6 CRCInput::RC_6 +#define RC_7 CRCInput::RC_7 +#define RC_8 CRCInput::RC_8 +#define RC_9 CRCInput::RC_9 +#define RC_RIGHT CRCInput::RC_right +#define RC_LEFT CRCInput::RC_left +#define RC_UP CRCInput::RC_up +#define RC_DOWN CRCInput::RC_down +#define RC_OK CRCInput::RC_ok +#define RC_MUTE CRCInput::RC_spkr +#define RC_STANDBY CRCInput::RC_standby +#define RC_GREEN CRCInput::RC_green +#define RC_YELLOW CRCInput::RC_yellow +#define RC_RED CRCInput::RC_red +#define RC_BLUE CRCInput::RC_blue +#define RC_PLUS CRCInput::RC_plus +#define RC_MINUS CRCInput::RC_minus +#define RC_HELP CRCInput::RC_help +#define RC_INFO CRCInput::RC_info +#define RC_DBOX CRCInput::RC_setup +#define RC_HOME CRCInput::RC_home +#define RC_TTTV CRCInput::RC_tttv +#define RC_TTZOOM CRCInput::RC_ttzoom +#define RC_TTREVEAL CRCInput::RC_ttreveal +#if HAVE_TRIPLEDRAGON +/* td has more keys so use ttx key for switching split mode... */ +#define RC_SPLIT CRCInput::RC_text +/* rc_text is now unused */ +#define RC_TEXT (CRCInput::RC_MaxRC + 1) +#else +/* ...while other receivers use the vol- key for that, so rc_split is unused */ +#define RC_SPLIT (CRCInput::RC_MaxRC + 1) +#define RC_TEXT CRCInput::RC_text +#endif +#endif typedef enum /* object type */ { @@ -202,6 +248,7 @@ const char *ObjectType[] = /* framebuffer stuff */ static unsigned char *lfb = 0; +static unsigned char *lbb = 0; struct fb_var_screeninfo var_screeninfo; struct fb_fix_screeninfo fix_screeninfo; @@ -545,7 +592,7 @@ char versioninfo[16]; int hotlist[10]; int maxhotlist; -int pig, rc, fb, lcd; +int pig, fb, lcd; int sx, ex, sy, ey; int PosX, PosY, StartX, StartY; int lastpage; @@ -577,7 +624,7 @@ int subtitledelay, delaystarted; FILE *conf; -unsigned short RCCode; +neutrino_msg_t RCCode; struct _pid_table { @@ -702,11 +749,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Bildschirmformat " "3 Standard-Modus 16:9 " " " - "5 Helligkeit " + "4 Helligkeit " " " - "6 Transparenz " + "5 Transparenz " " " - "7 nationaler Zeichensatz " + "6 nationaler Zeichensatz " "automatische Erkennung " " " " Sprache/Language deutsch " @@ -729,11 +776,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Screen format " "3 Standard mode 16:9 " " " - "5 Brightness " + "4 Brightness " " " - "6 Transparency " + "5 Transparency " " " - "7 national characterset " + "6 national characterset " " automatic recognition " " " " Sprache/language english " @@ -756,11 +803,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Format de l'#cran " "3 Mode standard 16:9 " " " - "5 Clarte " + "4 Clarte " " " - "6 Transparence " + "5 Transparence " " " - "7 police nationale " + "6 police nationale " "reconn. automatique " " " " Sprache/language francais" @@ -783,11 +830,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Beeldschermformaat " "3 Standaardmode 16:9 " " " - "5 Helderheid " + "4 Helderheid " " " - "6 Transparantie " + "5 Transparantie " " " - "7 nationale tekenset " + "6 nationale tekenset " "automatische herkenning " " " " Sprache/Language nederl. " @@ -810,11 +857,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Loqv^ oh|mgr " "3 Tq|por pq|tupor 16:9 " " " - "5 Kalpq|tgta " + "4 Kalpq|tgta " " " - "6 Diav\\meia " + "5 Diav\\meia " " " - "7 Ehmij^ tuposeiq\\ " + "6 Ehmij^ tuposeiq\\ " "aut|latg amacm~qisg " " " " Ck~ssa/Language ekkgmij\\ " @@ -837,11 +884,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Formato schermo " "3 Modo standard 16:9 " " " - "5 Luminosit{ " + "4 Luminosit{ " " " - "6 Trasparenza " + "5 Trasparenza " " " - "7 nazionalita'caratteri " + "6 nazionalita'caratteri " " riconoscimento automatico " " " " Lingua/Language Italiana " @@ -864,11 +911,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Format obrazu " "3 Tryb standard 16:9 " " " - "5 Jasno|^ " + "4 Jasno|^ " " " - "6 Prze~roczysto|^ " + "5 Prze~roczysto|^ " " " - "7 Znaki charakterystyczne " + "6 Znaki charakterystyczne " " automatyczne rozpozn. " " " " J`zyk/Language polski " @@ -891,11 +938,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " TV- format " "3 Standard l{ge 16:9 " " " - "5 Ljusstyrka " + "4 Ljusstyrka " " " - "6 Genomskinlighet " + "5 Genomskinlighet " " " - "7nationell teckenupps{ttning" + "6nationell teckenupps{ttning" " automatisk igenk{nning " " " " Sprache/language svenska " @@ -918,11 +965,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " N{ytt|tila " "3 Vakiotila 16:9 " " " - "5 Kirkkaus " + "4 Kirkkaus " " " - "6 L{pin{kyvyys " + "5 L{pin{kyvyys " " " - "7 kansallinen merkist| " + "6 kansallinen merkist| " " automaattinen tunnistus " " " " Kieli suomi " @@ -945,11 +992,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " formato ecran " "3 Standard mode 16:9 " " " - "5 Brilho " + "4 Brilho " " " - "6 Transparencia " + "5 Transparencia " " " - "7 Caracteres nacionaist " + "6 Caracteres nacionaist " "reconhecimento utomatico " " " " Lingua Portuguesa " @@ -972,11 +1019,11 @@ const char configmenu[][Menu_Height*(Menu_Width+1)] = " Format kartinki " "3 Stand. revim 16:9 " " " - "5 Qrkostx " + "4 Qrkostx " " " - "6 Prozra~nostx " + "5 Prozra~nostx " " " - "7 Ispolxzuem&j alfawit " + "6 Ispolxzuem&j alfawit " " awtoopredelenie " " " " Qz&k: Russkij " diff --git a/lib/libtuxtxt/tuxtxt_common.h b/lib/libtuxtxt/tuxtxt_common.h index bd7e15fa8..26d8754c6 100644 --- a/lib/libtuxtxt/tuxtxt_common.h +++ b/lib/libtuxtxt/tuxtxt_common.h @@ -1,4 +1,6 @@ - +/* tuxtxt_common.h + * for license info see the other tuxtxt files + */ #include #include #include @@ -15,6 +17,7 @@ tuxtxt_cache_struct tuxtxt_cache; static pthread_mutex_t tuxtxt_cache_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t tuxtxt_cache_biglock = PTHREAD_MUTEX_INITIALIZER; int tuxtxt_get_zipsize(int p,int sp) { tstCachedPage* pg = tuxtxt_cache.astCachetable[p][sp]; @@ -350,6 +353,7 @@ int tuxtxt_GetSubPage(int page, int subpage, int offset) void tuxtxt_clear_cache(void) { + pthread_mutex_lock(&tuxtxt_cache_biglock); pthread_mutex_lock(&tuxtxt_cache_lock); int clear_page, clear_subpage, d26; tuxtxt_cache.maxadippg = -1; @@ -413,6 +417,7 @@ void tuxtxt_clear_cache(void) printf("TuxTxt cache cleared\n"); #endif pthread_mutex_unlock(&tuxtxt_cache_lock); + pthread_mutex_unlock(&tuxtxt_cache_biglock); } /****************************************************************************** * init_demuxer * @@ -540,6 +545,7 @@ void tuxtxt_allocate_cache(int magazine) // Lock here as we have a possible race here with // tuxtxt_clear_cache(). We should not be allocating and // freeing at the same time. + // *** this is probably worked around by tuxtxt_cacehe_biglock now *** --seife pthread_mutex_lock(&tuxtxt_cache_lock); /* check cachetable and allocate memory if needed */ @@ -612,6 +618,13 @@ void *tuxtxt_CacheThread(void * /*arg*/) continue; } + /* this "big hammer lock" is a hack: it avoids a crash if + * tuxtxt_clear_cache() is called while the cache thread is in the + * middle of the following loop, leading to tuxtxt_cache.current_page[] + * etc. being set to -1 and tuxtxt_cache.astCachetable[] etc. being set + * to NULL + * it probably also avoids the possible race in tuxtxt_allocate_cache() */ + pthread_mutex_lock(&tuxtxt_cache_biglock); /* analyze it */ for (line = 0; line < readcnt/0x2e /*4*/; line++) { @@ -1053,6 +1066,7 @@ void *tuxtxt_CacheThread(void * /*arg*/) printf("line %d row %X %X, continue\n", line, vtx_rowbyte[0], vtx_rowbyte[1]); #endif } + pthread_mutex_unlock(&tuxtxt_cache_biglock); } pthread_exit(NULL); diff --git a/lib/sectionsdclient/Makefile.am b/lib/sectionsdclient/Makefile.am index 016fb6603..df4484b01 100644 --- a/lib/sectionsdclient/Makefile.am +++ b/lib/sectionsdclient/Makefile.am @@ -1,4 +1,6 @@ AM_CPPFLAGS = \ + @HWLIB_CFLAGS@ \ + -I$(top_builddir) \ -I$(top_srcdir)/lib \ -I$(top_srcdir)/src/zapit/include \ -I$(top_srcdir)/lib/connection \ diff --git a/lib/sectionsdclient/sectionsdclient.cpp b/lib/sectionsdclient/sectionsdclient.cpp index e4dcee4e5..4b259babe 100644 --- a/lib/sectionsdclient/sectionsdclient.cpp +++ b/lib/sectionsdclient/sectionsdclient.cpp @@ -28,6 +28,11 @@ #include #include +#ifdef PEDANTIC_VALGRIND_SETUP +#define VALGRIND_PARANOIA(x) memset(&x, 0, sizeof(x)) +#else +#define VALGRIND_PARANOIA(x) {} +#endif unsigned char CSectionsdClient::getVersion () const { @@ -59,6 +64,7 @@ int CSectionsdClient::readResponse(char* data,unsigned int size) bool CSectionsdClient::send(const unsigned char command, const char* data, const unsigned int size) { sectionsd::msgRequestHeader msgHead; + VALGRIND_PARANOIA(msgHead); msgHead.version = getVersion(); msgHead.command = command; @@ -78,6 +84,7 @@ bool CSectionsdClient::send(const unsigned char command, const char* data, const void CSectionsdClient::registerEvent(const unsigned int eventID, const unsigned int clientID, const char * const udsName) { CEventServer::commandRegisterEvent msg2; + VALGRIND_PARANOIA(msg2); msg2.eventID = eventID; msg2.clientID = clientID; @@ -92,6 +99,7 @@ void CSectionsdClient::registerEvent(const unsigned int eventID, const unsigned void CSectionsdClient::unRegisterEvent(const unsigned int eventID, const unsigned int clientID) { CEventServer::commandUnRegisterEvent msg2; + VALGRIND_PARANOIA(msg2); msg2.eventID = eventID; msg2.clientID = clientID; @@ -150,6 +158,7 @@ bool CSectionsdClient::getIsScanningActive() void CSectionsdClient::setServiceChanged(const t_channel_id channel_id, const bool requestEvent, int dnum) { sectionsd::commandSetServiceChanged msg; + VALGRIND_PARANOIA(msg); msg.channel_id = channel_id; msg.requestEvent = requestEvent; diff --git a/lib/sectionsdclient/sectionsdclient.h b/lib/sectionsdclient/sectionsdclient.h index 1f70b01f2..f3d071fb2 100644 --- a/lib/sectionsdclient/sectionsdclient.h +++ b/lib/sectionsdclient/sectionsdclient.h @@ -150,7 +150,16 @@ class CSectionsdClient : private CBasicClient }; struct CurrentNextInfo : public responseGetCurrentNextInfoChannelID - {}; + { + CurrentNextInfo() { + current_uniqueKey = 0; + current_name = ""; + current_fsk = 0x0; + next_uniqueKey = 0; + next_name = ""; + flags = 0x0; + } + }; typedef struct { diff --git a/lib/timerdclient/Makefile.am b/lib/timerdclient/Makefile.am index ce2f0f72d..3eddb0fa4 100644 --- a/lib/timerdclient/Makefile.am +++ b/lib/timerdclient/Makefile.am @@ -1,4 +1,6 @@ AM_CPPFLAGS = \ + @HWLIB_CFLAGS@ \ + -I$(top_builddir) \ -I$(top_srcdir)/lib \ -I$(top_srcdir)/src/zapit/include \ -I$(top_srcdir)/lib/connection \ diff --git a/lib/timerdclient/timerdclient.cpp b/lib/timerdclient/timerdclient.cpp index 0368e7011..2b6dd2863 100644 --- a/lib/timerdclient/timerdclient.cpp +++ b/lib/timerdclient/timerdclient.cpp @@ -28,6 +28,14 @@ #include #include +#ifdef PEDANTIC_VALGRIND_SETUP +#define VALGRIND_PARANOIA(x) memset(&x, 0, sizeof(x)) +#else +#define VALGRIND_PARANOIA(x) {} +#endif + +//int CTimerdClient::adzap_eventID = 0; + unsigned char CTimerdClient::getVersion () const { return CTimerdMsg::ACTVERSION; @@ -43,6 +51,7 @@ const char * CTimerdClient::getSocketName() const void CTimerdClient::registerEvent(unsigned int eventID, unsigned int clientID, const char * const udsName) { CEventServer::commandRegisterEvent msg2; + VALGRIND_PARANOIA(msg2); msg2.eventID = eventID; msg2.clientID = clientID; @@ -58,6 +67,7 @@ void CTimerdClient::registerEvent(unsigned int eventID, unsigned int clientID, c void CTimerdClient::unRegisterEvent(unsigned int eventID, unsigned int clientID) { CEventServer::commandUnRegisterEvent msg2; + VALGRIND_PARANOIA(msg2); msg2.eventID = eventID; msg2.clientID = clientID; @@ -165,6 +175,7 @@ bool CTimerdClient::modifyTimerEvent(int eventid, time_t announcetime, time_t al // set new time values for event eventid CTimerdMsg::commandModifyTimer msgModifyTimer; + VALGRIND_PARANOIA(msgModifyTimer); msgModifyTimer.eventID = eventid; msgModifyTimer.announceTime = announcetime; msgModifyTimer.alarmTime = alarmtime; @@ -203,6 +214,7 @@ bool CTimerdClient::rescheduleTimerEvent(int eventid, time_t diff) bool CTimerdClient::rescheduleTimerEvent(int eventid, time_t announcediff, time_t alarmdiff, time_t stopdiff) { CTimerdMsg::commandModifyTimer msgModifyTimer; + VALGRIND_PARANOIA(msgModifyTimer); msgModifyTimer.eventID = eventid; msgModifyTimer.announceTime = announcediff; msgModifyTimer.alarmTime = alarmdiff; @@ -298,6 +310,9 @@ int CTimerdClient::addTimerEvent( CTimerd::CTimerEventTypes evType, void* data, CTimerd::TransferEventInfo tei; CTimerd::TransferRecordingInfo tri; CTimerdMsg::commandAddTimer msgAddTimer; + VALGRIND_PARANOIA(tei); + VALGRIND_PARANOIA(tri); + VALGRIND_PARANOIA(msgAddTimer); msgAddTimer.alarmTime = alarmtime; msgAddTimer.announceTime = announcetime; msgAddTimer.stopTime = stoptime; @@ -368,6 +383,8 @@ int CTimerdClient::addTimerEvent( CTimerd::CTimerEventTypes evType, void* data, void CTimerdClient::removeTimerEvent( int evId) { CTimerdMsg::commandRemoveTimer msgRemoveTimer; + VALGRIND_PARANOIA(msgRemoveTimer); + msgRemoveTimer.eventID = evId; send(CTimerdMsg::CMD_REMOVETIMER, (char*) &msgRemoveTimer, sizeof(msgRemoveTimer)); @@ -436,6 +453,7 @@ bool CTimerdClient::shutdown() void CTimerdClient::modifyTimerAPid(int eventid, unsigned char apids) { CTimerdMsg::commandSetAPid data; + VALGRIND_PARANOIA(data); data.eventID=eventid; data.apids = apids; send(CTimerdMsg::CMD_SETAPID, (char*) &data, sizeof(data)); @@ -446,6 +464,7 @@ void CTimerdClient::modifyTimerAPid(int eventid, unsigned char apids) void CTimerdClient::setRecordingSafety(int pre, int post) { CTimerdMsg::commandRecordingSafety data; + VALGRIND_PARANOIA(data); data.pre = pre; data.post = post; send(CTimerdMsg::CMD_SETRECSAFETY, (char*) &data, sizeof(data)); @@ -518,6 +537,7 @@ void CTimerdClient::setWeekdaysToStr(CTimerd::CTimerEventRepeat rep, std::string void CTimerdClient::stopTimerEvent( int evId) { CTimerdMsg::commandRemoveTimer msgRemoveTimer; + VALGRIND_PARANOIA(msgRemoveTimer); msgRemoveTimer.eventID = evId; diff --git a/lib/xmltree/xmltok.h b/lib/xmltree/xmltok.h index 6d0b91dff..cfbc427ba 100644 --- a/lib/xmltree/xmltok.h +++ b/lib/xmltree/xmltok.h @@ -21,6 +21,17 @@ Contributor(s): #ifndef XmlTok_INCLUDED #define XmlTok_INCLUDED 1 +/* ugly: prefix all functions to avoid clashing with "real" libexpat + * or similar pulled in by other libs e.g. on PC */ +#define XmlParseXmlDecl NEUTRINO_MP_XmlParseXmlDecl +#define XmlInitEncoding NEUTRINO_MP_XmlInitEncoding +#define XmlGetUtf8InternalEncoding NEUTRINO_MP_XmlGetUtf8InternalEncoding +#define XmlGetUtf16InternalEncoding NEUTRINO_MP_XmlGetUtf16InternalEncoding +#define XmlUtf8Encode NEUTRINO_MP_XmlUtf8Encode +#define XmlUtf16Encode NEUTRINO_MP_XmlUtf16Encode +#define XmlSizeOfUnknownEncoding NEUTRINO_MP_XmlSizeOfUnknownEncoding +#define XmlInitUnknownEncoding NEUTRINO_MP_XmlInitUnknownEncoding + #ifdef __cplusplus extern "C" { #endif diff --git a/src/Makefile.am b/src/Makefile.am index 36725b473..503ed1ef4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,6 +40,10 @@ else VORBISLIBS = -lvorbisfile -lvorbis -logg endif +bin_PROGRAMS = neutrino + +neutrino_SOURCES = neutrino_menue.cpp neutrino.cpp + if ENABLE_FLAC FLACLIBS = -lFLAC else @@ -56,10 +60,6 @@ ADEC_LIBS = @MAD_LIBS@ \ $(VORBISLIBS) endif -bin_PROGRAMS = neutrino rcsim - -neutrino_SOURCES = neutrino_menue.cpp neutrino.cpp - AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64 if BOXMODEL_APOLLO @@ -141,14 +141,24 @@ neutrino_LDADD += \ $(top_builddir)/lib/libupnpclient/libtuxbox-upnpclient.a endif +if BOXTYPE_COOL +neutrino_LDADD += \ + $(top_builddir)/lib/libtuxtxt/libtuxtxt.a +else +neutrino_LDADD += \ + $(top_builddir)/lib/libtuxtxt/libtuxtxt.a +endif + if BOXTYPE_COOL neutrino_LDADD += -lcoolstream-mt -lca-sc if ENABLE_TMSDK else if BOXMODEL_APOLLO -neutrino_LDADD += -lca-ci -llnxtmvssUsr -llnxUKAL -llnxplatUsr -llnxtmasUsr -llnxdvbciUsr -llnxpvrUsr -llnxcssUsr -llnxnotifyqUsr -ltmpvrDataManager-cst -ltmpvrIndexStorage -llnxscsUsr +neutrino_LDADD += -lca-ci -llnxtmvssUsr -llnxUKAL -llnxplatUsr -llnxtmasUsr -llnxdvbciUsr -llnxpvrUsr -llnxcssUsr -llnxnotifyqUsr -ltmpvrDataManager-cst -ltmpvrIndexStorage -llnxscsUsr \ + $(top_builddir)/lib/libcoolstream2/libhwcaps.a else -neutrino_LDADD += -lnxp +neutrino_LDADD += -lnxp \ + $(top_builddir)/lib/libcoolstream/libhwcaps.a endif endif @@ -158,16 +168,46 @@ endif 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 += \ + -lstb-hal +neutrino_LDFLAGS = \ + $(STB_HAL_LIB) endif + if BOXTYPE_TRIPLE neutrino_LDADD += \ - $(top_builddir)/lib/libtriple/libtriple.a \ - @DIRECTFB_LIBS@ \ $(top_builddir)/src/lcddisplay/liblcddisplay.a endif +neutrino_LDADD += \ + @AVFORMAT_LIBS@ \ + @AVUTIL_LIBS@ \ + @AVCODEC_LIBS@ + +if BOXMODEL_RASPI +neutrino_LDADD += \ + -L/opt/vc/lib/ -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt +endif + +if BOXTYPE_COOL +bin_PROGRAMS += uncooloff +uncooloff_SOURCES = uncooloff.c +if BOXMODEL_APOLLO +else +noinst_PROGRAMS = uncoolinit +uncoolinit_SOURCES = uncoolinit.cpp +uncoolinit_LDADD = \ + @AVFORMAT_LIBS@ \ + @AVCODEC_LIBS@ \ + @BLURAY_LIBS@ \ + -lcoolstream-mt -lca-sc -lnxp \ + -lOpenThreads -lrt +endif +endif diff --git a/src/create_rcsim_h.sh b/src/create_rcsim_h.sh old mode 100755 new mode 100644 diff --git a/src/daemonc/Makefile.am b/src/daemonc/Makefile.am index c272b2dee..ee7f8ea80 100644 --- a/src/daemonc/Makefile.am +++ b/src/daemonc/Makefile.am @@ -15,7 +15,6 @@ AM_CPPFLAGS += \ @AVFORMAT_CFLAGS@ \ @HWLIB_CFLAGS@ - noinst_LIBRARIES = libneutrino_daemonc.a libneutrino_daemonc_a_SOURCES = remotecontrol.cpp diff --git a/src/daemonc/remotecontrol.cpp b/src/daemonc/remotecontrol.cpp index 03e515d01..42653752d 100644 --- a/src/daemonc/remotecontrol.cpp +++ b/src/daemonc/remotecontrol.cpp @@ -4,6 +4,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ + (C) 2008-2013 Stefan Seyfried + Kommentar: Diese GUI wurde von Grund auf neu programmiert und sollte nun vom @@ -106,9 +108,11 @@ CRemoteControl::CRemoteControl() selected_subchannel = -1; needs_nvods = false; director_mode = 0; +// current_programm_timer = 0; is_video_started = true; - //current_programm_timer = 0; //next_EPGid = 0; + are_subchannels = false; + has_unresolved_ctags = false; } @@ -207,86 +211,70 @@ int CRemoteControl::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data } } - if ( msg == NeutrinoMessages::EVT_CURRENTEPG ) { - CSectionsdClient::CurrentNextInfo* info_CN = (CSectionsdClient::CurrentNextInfo*) data; - -#if 0 - printf("[neutrino] EVT_CURRENTEPG: uniqueKey %llx chid %llx subid %llx flags %x\n", - info_CN->current_uniqueKey >> 16, current_channel_id & 0xFFFFFFFFFFFFULL, - current_sub_channel_id&0xFFFFFFFFFFFFULL, info_CN->flags); -#endif - t_channel_id chid = (info_CN->current_uniqueKey >> 16); - if(chid != (current_channel_id&0xFFFFFFFFFFFFULL) && chid != (current_sub_channel_id&0xFFFFFFFFFFFFULL)) + if ( msg == NeutrinoMessages::EVT_CURRENTEPG ) + { + if ((*(t_channel_id *)data) != (current_channel_id & 0xFFFFFFFFFFFFULL) && + (*(t_channel_id *)data) != (current_sub_channel_id & 0xFFFFFFFFFFFFULL)) return messages_return::handled; - /* current event came for current channel */ - if ( info_CN->current_uniqueKey != current_EPGid ) + const CSectionsdClient::CurrentNextInfo info_CN = g_InfoViewer->getCurrentNextInfo(); + if ((info_CN.current_uniqueKey >> 16) == (current_channel_id & 0xFFFFFFFFFFFFULL) || (info_CN.current_uniqueKey >> 16) == (current_sub_channel_id & 0xFFFFFFFFFFFFULL)) { - if ( current_EPGid != 0 ) + //CURRENT-EPG for current channel arrived!; + CVFD::getInstance()->setEPGTitle(info_CN.current_name); + if (info_CN.current_uniqueKey != current_EPGid) { - /* new event, not channel. get pids */ - g_Zapit->getPIDS( current_PIDs ); - has_unresolved_ctags = true; - // infobar indicate on epg change - g_InfoViewer->showEpgInfo(); + if ( current_EPGid != 0 ) + { + // ist nur ein neues Programm, kein neuer Kanal + // PIDs neu holen + g_Zapit->getPIDS( current_PIDs ); + // APID Bearbeitung neu anstossen + has_unresolved_ctags = true; + // infobar indicate on epg change + g_InfoViewer->showEpgInfo(); + } + + current_EPGid = info_CN.current_uniqueKey; + + if ( has_unresolved_ctags ) + processAPIDnames(); + + if (selected_subchannel <= 0 && info_CN.flags & CSectionsdClient::epgflags::current_has_linkagedescriptors) + { + subChannels.clear(); + getSubChannels(); + } + + if ( needs_nvods ) + getNVODs(); } - current_EPGid= info_CN->current_uniqueKey; - - if ( has_unresolved_ctags ) - processAPIDnames(); - - if ( info_CN->flags & CSectionsdClient::epgflags::current_has_linkagedescriptors ) { - subChannels.clear(); - getSubChannels(); - } - - if ( needs_nvods ) - getNVODs(); - -#if 0 - g_RCInput->killTimer( current_programm_timer ); - - time_t end_program= info_CN->current_zeit.startzeit+ info_CN->current_zeit.dauer; - current_programm_timer = g_RCInput->addTimer( &end_program ); -#endif + // is_video_started is only false if channel is locked + if ((!is_video_started) && + (info_CN.current_fsk == 0 || g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_CHANGETOLOCKED)) + g_RCInput->postMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, 0x100, false); + else + g_RCInput->postMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, info_CN.current_fsk, false); } - - // is_video_started is only false if channel is locked - if ((!is_video_started) && - (info_CN->current_fsk == 0 || g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_CHANGETOLOCKED)) - g_RCInput->postMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, 0x100, false); - else - g_RCInput->postMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, info_CN->current_fsk, false); return messages_return::handled; } else if ( msg == NeutrinoMessages::EVT_NEXTEPG ) { - CSectionsdClient::CurrentNextInfo* info_CN = (CSectionsdClient::CurrentNextInfo*) data; - t_channel_id chid = (info_CN->next_uniqueKey >> 16); - if(chid != (current_channel_id&0xFFFFFFFFFFFFULL) && chid != (current_sub_channel_id&0xFFFFFFFFFFFFULL)) + if ((*(t_channel_id *)data) != current_channel_id) return messages_return::handled; - #if 0 - if ( ( info_CN->next_uniqueKey >> 16) == (current_channel_id&0xFFFFFFFFFFFFULL) ) + const CSectionsdClient::CurrentNextInfo info_CN = g_InfoViewer->getCurrentNextInfo(); + if ((info_CN.next_uniqueKey >> 16) == (current_channel_id&0xFFFFFFFFFFFFULL) ) { - // next-EPG fr den aktuellen Kanal bekommen, current ist leider net da?!; - if ( info_CN->next_uniqueKey != next_EPGid ) - { - next_EPGid = info_CN->next_uniqueKey; - - // timer setzen - g_RCInput->killTimer( current_programm_timer ); - - time_t end_program = info_CN->next_zeit.startzeit; - current_programm_timer = g_RCInput->addTimer( &end_program ); - } + // next-EPG for current channel arrived. no current-EPG?! + if (info_CN.next_uniqueKey != next_EPGid) + next_EPGid = info_CN.next_uniqueKey; } #endif if ( !is_video_started ) g_RCInput->postMsg( NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, 0x100, false ); - - return messages_return::handled; + return messages_return::handled; } else if (msg == NeutrinoMessages::EVT_NOEPG_YET) { @@ -350,8 +338,8 @@ int CRemoteControl::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data { //printf("new program !\n"); - char *p = new char[sizeof(t_channel_id)]; - memcpy(p, ¤t_channel_id, sizeof(t_channel_id)); + t_channel_id * p = new t_channel_id; + *p = current_channel_id; g_RCInput->postMsg(NeutrinoMessages::EVT_NEXTPROGRAM, (const neutrino_msg_data_t)p, false); // data is pointer to allocated memory return messages_return::handled; @@ -509,10 +497,16 @@ void CRemoteControl::processAPIDnames() if((pref_idx >= 0) && (pref_idx < pref_ac3_idx)) pref_ac3_found = -1; } - +#ifdef APID_DEBUG + if (! current_PIDs.APIDs.empty()) + printf("Neutrino: "); +#endif for(unsigned int count=0; count< current_PIDs.APIDs.size(); count++) { - printf("Neutrino: apid name= %s (%s) pid= %X\n", current_PIDs.APIDs[count].desc, getISO639Description( current_PIDs.APIDs[count].desc ), current_PIDs.APIDs[count].pid); +#ifdef APID_DEBUG + const char *iso = getISO639Description(current_PIDs.APIDs[count].desc); + printf("apid=%04x/%s/%s ", current_PIDs.APIDs[count].pid, current_PIDs.APIDs[count].desc, iso); +#endif if ( current_PIDs.APIDs[count].component_tag != 0xFF ) { has_unresolved_ctags= true; @@ -521,7 +515,14 @@ void CRemoteControl::processAPIDnames() if ( tmp_desc.size() == 3 ) { // unaufgeloeste Sprache... +/* merge conflict */ +#if 0 + /* getISO639Description returns same pointer as input if nothing is found */ + if (current_PIDs.APIDs[count].desc != iso) + strcpy(current_PIDs.APIDs[count].desc, iso); +#else tmp_desc = getISO639Description( current_PIDs.APIDs[count].desc ); +#endif } if ( current_PIDs.APIDs[count].is_ac3 ) @@ -542,7 +543,10 @@ void CRemoteControl::processAPIDnames() } } - +#ifdef APID_DEBUG + if (! current_PIDs.APIDs.empty()) + printf("\n"); +#endif if ( has_unresolved_ctags ) { if ( current_EPGid != 0 ) @@ -581,16 +585,24 @@ void CRemoteControl::processAPIDnames() } } } +#ifdef APID_DEBUG printf("Neutrino: pref_found %d pref_ac3_found %d ac3_found %d\n", pref_found, pref_ac3_found, ac3_found); +#endif if(pref_ac3_found >= 0) { +#ifdef APID_DEBUG printf("Neutrino: set apid name= %s pid= %X\n", current_PIDs.APIDs[pref_ac3_found].desc, current_PIDs.APIDs[pref_ac3_found].pid); +#endif setAPID(pref_ac3_found); } else if(pref_found >= 0) { +#ifdef APID_DEBUG printf("Neutrino: set apid name= %s pid= %X\n", current_PIDs.APIDs[pref_found].desc, current_PIDs.APIDs[pref_found].pid); +#endif setAPID(pref_found); } else if(ac3_found >= 0) { +#ifdef APID_DEBUG printf("Neutrino: set apid name= %s pid= %X\n", current_PIDs.APIDs[ac3_found].desc, current_PIDs.APIDs[ac3_found].pid); +#endif setAPID(ac3_found); } else if ( current_PIDs.PIDs.selected_apid >= current_PIDs.APIDs.size() ) @@ -725,7 +737,7 @@ void CRemoteControl::zapTo_ChannelID(const t_channel_id channel_id, const std::s g_Zapit->zapTo_serviceID_NOWAIT(channel_id); zap_completion_timeout = now + ZAP_GUARD_TIME; - //g_RCInput->killTimer( current_programm_timer ); +// g_RCInput->killTimer( current_programm_timer ); } current_channel_id = channel_id; current_channel_name = channame; @@ -738,7 +750,7 @@ void CRemoteControl::startvideo() { is_video_started= true; //g_Zapit->startPlayBack(); - g_Zapit->unlockPlayBack(); + g_Zapit->unlockPlayBack(true); /* TODO: check if sendpmt=false is correct in stopvideo() */ } } @@ -749,8 +761,8 @@ void CRemoteControl::stopvideo() is_video_started= false; /* we need stopPlayback to blank video, lockPlayback prevents it from being inadvertently starting */ - g_Zapit->stopPlayBack(); - g_Zapit->lockPlayBack(); + g_Zapit->stopPlayBack(false); + g_Zapit->lockPlayBack(false); } } diff --git a/src/daemonc/remotecontrol.h b/src/daemonc/remotecontrol.h index 7a93eead3..4c4cae072 100644 --- a/src/daemonc/remotecontrol.h +++ b/src/daemonc/remotecontrol.h @@ -71,7 +71,7 @@ typedef std::vector CSubServiceListSorted; class CRemoteControl { - //unsigned int current_programm_timer; +// unsigned int current_programm_timer; uint64_t zap_completion_timeout; std::string current_channel_name; int current_channel_num; diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am index 965e9083d..cf228beda 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -27,9 +27,10 @@ libneutrino_driver_a_SOURCES = \ colorgradient.cpp \ fade.cpp \ fb_window.cpp \ + fbaccel.cpp \ file.cpp \ fontrenderer.cpp \ - framebuffer.cpp \ + framebuffer_ng.cpp \ genpsi.cpp \ moviecut.cpp \ neutrinofonts.cpp \ @@ -55,4 +56,21 @@ libneutrino_driver_a_SOURCES += \ lcdd.cpp endif +if BOXTYPE_SPARK +libneutrino_driver_a_SOURCES += \ + simple_display.cpp +endif +if BOXTYPE_AZBOX +libneutrino_driver_a_SOURCES += \ + simple_display.cpp +endif +if BOXTYPE_GENERIC +libneutrino_driver_a_SOURCES += \ + simple_display.cpp +endif +if USE_STB_HAL +AM_CPPFLAGS += \ + @DIRECTFB_CFLAGS@ +endif + libneutrino_driver_netfile_a_SOURCES = netfile.cpp diff --git a/src/driver/audiodec/Makefile.am b/src/driver/audiodec/Makefile.am index eccc74b27..d3332a48a 100644 --- a/src/driver/audiodec/Makefile.am +++ b/src/driver/audiodec/Makefile.am @@ -25,7 +25,6 @@ ASOURCES = cdrdec.cpp \ mp3dec.cpp \ oggdec.cpp \ tag.c \ - vis.cpp \ wavdec.cpp endif diff --git a/src/driver/audiodec/flacdec.cpp b/src/driver/audiodec/flacdec.cpp index 242337945..1ed0fd0d0 100644 --- a/src/driver/audiodec/flacdec.cpp +++ b/src/driver/audiodec/flacdec.cpp @@ -448,8 +448,8 @@ CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int /*OutputFd*/, State* con // State oldstate=*state; int jumppos=0; int actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; - int bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); - int bytes_to_play = (int) (1.0 * MSECS_TO_PLAY / 1000 * meta_data->bitrate / 8); + int bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; + int bytes_to_play = MSECS_TO_PLAY * meta_data->bitrate / 8000; unsigned int oldSecsToSkip = *secondsToSkip; FLAC__uint64 position; @@ -463,7 +463,7 @@ CBaseDec::RetCode CFlacDec::Decoder(FILE *in, const int /*OutputFd*/, State* con if (oldSecsToSkip != *secondsToSkip) { actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; - bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); + bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; oldSecsToSkip = *secondsToSkip; } printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip); diff --git a/src/driver/audiodec/mp3dec.cpp b/src/driver/audiodec/mp3dec.cpp index 69c11d5b4..dc921f788 100644 --- a/src/driver/audiodec/mp3dec.cpp +++ b/src/driver/audiodec/mp3dec.cpp @@ -3,6 +3,7 @@ Copyright (C) 2002 Bjoern Kalkbrenner (C) 2002,2003,2004 Zwen + Copyright (C) 2010-2011 Stefan Seyfried libmad MP3 low-level core Homepage: http://www.cyberphoria.org/ @@ -71,8 +72,8 @@ void sanalyzer_render_freq(short data[1024]); finish_file function. */ extern "C" { -void id3_tag_addref(struct id3_tag *); -void id3_tag_delref(struct id3_tag *); +//void id3_tag_addref(struct id3_tag *); +void my_id3_tag_delref(struct id3_tag *); struct filetag { struct id3_tag *tag; unsigned long location; @@ -283,8 +284,7 @@ void CMP3Dec::CreateInfo(CAudioMetaData* m, int FrameNumber) if ( !m->hasInfoOrXingTag ) { m->total_time = m->avg_bitrate != 0 ? - static_cast( round( static_cast( m->filesize ) - / m->avg_bitrate ) ) + static_cast(m->filesize / m->avg_bitrate) : 0; } @@ -897,7 +897,9 @@ q * next mad_frame_decode() invocation. (See the comments marked } } audioDecoder->StopClip(); +#ifdef SPECTRUM CVFD::getInstance ()->Unlock (); +#endif /* Accounting report if no error occured. */ if(Status==OK) { @@ -1141,8 +1143,7 @@ bool CMP3Dec::GetMP3Info( FILE* input, const bool nice, { meta->vbr = true; meta->avg_bitrate = meta->total_time != 0 - ? static_cast( round( static_cast(meta->filesize) - / meta->total_time ) ) + ? static_cast(meta->filesize / meta->total_time) : 0; } else /* we do not know wether the file is vbr or not */ @@ -1443,7 +1444,7 @@ void id3_finish_file(struct id3_file* file) free(file->path); if (file->primary) { - id3_tag_delref(file->primary); + my_id3_tag_delref(file->primary); id3_tag_delete(file->primary); } @@ -1452,7 +1453,7 @@ void id3_finish_file(struct id3_file* file) tag = file->tags[i].tag; if (tag) { - id3_tag_delref(tag); + my_id3_tag_delref(tag); id3_tag_delete(tag); } } @@ -1463,3 +1464,10 @@ void id3_finish_file(struct id3_file* file) free(file); } +/* copy of id3_tag_delref, since a properly built libid3tag does + * not export this (it's not part of the public API... */ +void my_id3_tag_delref(struct id3_tag *tag) +{ + assert(tag && tag->refcount > 0); + --tag->refcount; +} diff --git a/src/driver/audiodec/wavdec.cpp b/src/driver/audiodec/wavdec.cpp index 9a0f8c9c4..e7c900bf1 100644 --- a/src/driver/audiodec/wavdec.cpp +++ b/src/driver/audiodec/wavdec.cpp @@ -2,6 +2,7 @@ Neutrino-GUI - DBoxII-Project Copyright (C) 2004 Zwen + Copyright (C) 2010-2011 Stefan Seyfried Homepage: http://www.dbox2.info/ @@ -118,8 +119,8 @@ CBaseDec::RetCode CWavDec::Decoder(FILE *in, int /*OutputFd*/, State* state, CAu unsigned int oldSecsToSkip = *secondsToSkip; int jumppos=0; int bytes; - int bytes_to_play = (int) (1.0 * MSECS_TO_PLAY / 1000 * meta_data->bitrate / 8); - int bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); + int bytes_to_play = MSECS_TO_PLAY * meta_data->bitrate / 8000; + int bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; int buffersize = MAX_OUTPUT_SAMPLES * mChannels * mBitsPerSample / 8; buffer = (char*) malloc (buffersize); do @@ -132,7 +133,7 @@ CBaseDec::RetCode CWavDec::Decoder(FILE *in, int /*OutputFd*/, State* state, CAu if (oldSecsToSkip != *secondsToSkip) { actSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip : MSECS_TO_SKIP / 1000; - bytes_to_skip = (int) (1.0 * actSecsToSkip * meta_data->bitrate / 8); + bytes_to_skip = actSecsToSkip * meta_data->bitrate / 8; oldSecsToSkip = *secondsToSkip; } //printf("skipping %d secs and %d bytes\n",actSecsToSkip,bytes_to_skip); diff --git a/src/driver/fader.cpp b/src/driver/fader.cpp new file mode 100644 index 000000000..cdb6a4985 --- /dev/null +++ b/src/driver/fader.cpp @@ -0,0 +1,98 @@ +/* + Neutrino-HD GUI, COSDFader implementation + Copyright (C) 2011 Stefan Seyfried + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +COSDFader::COSDFader(int trans) +{ + fb = CFrameBuffer::getInstance(); + target_trans = trans; + timer = 0; + step = 0; +} + +COSDFader::~COSDFader() +{ + Stop(); +} + +void COSDFader::StartFadeIn() +{ + transparency = 100; + step = -FADE_STEP; + Fade(); +} + +/* returns true if fade out was not started before and fade is enabled */ +bool COSDFader::StartFadeOut() +{ + if (!g_settings.widget_fade) /* disabled */ + return false; + if (step == FADE_STEP) /* already fading out... */ + return false; + + /* start fading */ + step = FADE_STEP; + Fade(); + return true; +} + +void COSDFader::Stop() +{ + if (!step) + return; + + g_RCInput->killTimer(timer); + fb->setBlendMode(1); /* per pixel alpha */ +} + +/* returns true if fade out is finished */ +bool COSDFader::Fade() +{ + if (!g_settings.widget_fade) + return false; + + if (timer == 0) + timer = g_RCInput->addTimer(FADE_TIME, false); + + if (transparency == 100 || transparency == target_trans) + { + fb->setBlendMode(2); /* 2 == "global alpha x pixel alpha" */ + fb->setBlendLevel(transparency); + transparency += step; + return false; + } + transparency += step; + if (step > 0 && transparency >= 100) /* finished fading out */ + { + transparency = target_trans; + g_RCInput->killTimer(timer); + return true; + } + if (step < 0 && transparency <= target_trans) /* finished fading in */ + { + transparency = target_trans; + g_RCInput->killTimer(timer); + fb->setBlendMode(1); /* 1 == "per pixel alpha" */ + return false; + } + fb->setBlendLevel(transparency); + return false; +} diff --git a/src/driver/fader.h b/src/driver/fader.h new file mode 100644 index 000000000..fa386010b --- /dev/null +++ b/src/driver/fader.h @@ -0,0 +1,42 @@ +/* + Neutrino-HD GUI, COSDFader implementation + Copyright (C) 2011 Stefan Seyfried + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __FADER_H__ +#define __FADER_H__ + +#include + +class COSDFader +{ + private: + CFrameBuffer *fb; + int step; + int target_trans; + int transparency; + uint32_t timer; + public: + COSDFader(int trans); + ~COSDFader(); + + void StartFadeIn(); + bool StartFadeOut(); + void Stop(); + bool Fade(); + uint32_t GetTimer(){ return timer; }; +}; +#endif diff --git a/src/driver/fb_window.cpp b/src/driver/fb_window.cpp index 19431f358..2b5bb0028 100644 --- a/src/driver/fb_window.cpp +++ b/src/driver/fb_window.cpp @@ -4,6 +4,7 @@ * abstract fb_window class - d-box2 linux project * * (C) 2003 by thegoodguy + * (C) 2009-2012 Stefan Seyfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/driver/fbaccel.cpp b/src/driver/fbaccel.cpp new file mode 100644 index 000000000..b43c4c2ae --- /dev/null +++ b/src/driver/fbaccel.cpp @@ -0,0 +1,1383 @@ +/* + Neutrino-GUI - DBoxII-Project + + Copyright (C) 2001 Steffen Hehn 'McClean' + 2003 thegoodguy + Copyright (C) 2007-2013 Stefan Seyfried + + Framebuffer acceleration hardware abstraction functions. + The various hardware dependent framebuffer acceleration functions + are represented in this class. + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#if HAVE_COOL_HARDWARE +#include +#include +#endif +#if HAVE_SPARK_HARDWARE +#include +#include +#endif +#if HAVE_GENERIC_HARDWARE +#include +extern GLFramebuffer *glfb; +#endif + +#include +#include +#include + +#if HAVE_COOL_HARDWARE || HAVE_TRIPLEDRAGON +#define NEED_BLIT_THREAD 0 +#else +#define NEED_BLIT_THREAD 1 +#endif + +#ifdef BOXMODEL_APOLLO +#ifndef FB_HW_ACCELERATION +#define FB_HW_ACCELERATION +#endif +#endif +#if defined(FB_HW_ACCELERATION) && defined(USE_NEVIS_GXA) +#error +#endif + +/* note that it is *not* enough to just change those values */ +#define DEFAULT_XRES 1280 +#define DEFAULT_YRES 720 +#define DEFAULT_BPP 32 + +//#undef USE_NEVIS_GXA //FIXME +/*******************************************************************************/ +#ifdef USE_NEVIS_GXA +#define GXA_POINT(x, y) (((y) & 0x0FFF) << 16) | ((x) & 0x0FFF) +#define GXA_SRC_BMP_SEL(x) (x << 8) +#define GXA_DST_BMP_SEL(x) (x << 5) +#define GXA_PARAM_COUNT(x) (x << 2) + +#define GXA_CMD_REG 0x001C +#define GXA_FG_COLOR_REG 0x0020 +#define GXA_BG_COLOR_REG 0x0024 +#define GXA_LINE_CONTROL_REG 0x0038 +#define GXA_BMP1_TYPE_REG 0x0048 +#define GXA_BMP1_ADDR_REG 0x004C +#define GXA_BMP2_TYPE_REG 0x0050 +#define GXA_BMP2_ADDR_REG 0x0054 +#define GXA_BMP3_TYPE_REG 0x0058 +#define GXA_BMP3_ADDR_REG 0x005C +#define GXA_BMP4_TYPE_REG 0x0060 +#define GXA_BMP4_ADDR_REG 0x0064 +#define GXA_BMP5_TYPE_REG 0x0068 +#define GXA_BMP5_ADDR_REG 0x006C +#define GXA_BMP6_TYPE_REG 0x0070 +#define GXA_BMP7_TYPE_REG 0x0078 +#define GXA_DEPTH_REG 0x00F4 +#define GXA_CONTENT_ID_REG 0x0144 + +#define GXA_CMD_BLT 0x00010800 +#define GXA_CMD_NOT_ALPHA 0x00011000 +#define GXA_CMD_NOT_TEXT 0x00018000 +#define GXA_CMD_QMARK 0x00001000 + +#define GXA_BLEND_CFG_REG 0x003C +#define GXA_CFG_REG 0x0030 +#define GXA_CFG2_REG 0x00FC +/* +static unsigned int _read_gxa(volatile unsigned char *base_addr, unsigned int offset) +{ + return *(volatile unsigned int *)(base_addr + offset); +} +*/ + +static unsigned int _mark = 0; + +static void _write_gxa(volatile unsigned char *base_addr, unsigned int offset, unsigned int value) +{ + while ((*(volatile unsigned int *)(base_addr + GXA_DEPTH_REG)) & 0x40000000) {}; + *(volatile unsigned int *)(base_addr + offset) = value; +} + +/* this adds a tagged marker into the GXA queue. Once this comes out + of the other end of the queue, all commands before it are finished */ +void CFbAccel::add_gxa_sync_marker(void) +{ + unsigned int cmd = GXA_CMD_QMARK | GXA_PARAM_COUNT(1); + // TODO: locking? + _mark++; + _mark &= 0x0000001F; /* bit 0x20 crashes the kernel, if set */ + _write_gxa(gxa_base, cmd, _mark); + //fprintf(stderr, "%s: wrote %02x\n", __FUNCTION__, _mark); +} + +/* wait until the current marker comes out of the GXA command queue */ +void CFbAccel::waitForIdle(void) +{ + unsigned int cfg, count = 0; + do { + cfg = *(volatile unsigned int *)(gxa_base + GXA_CMD_REG); + cfg >>= 24; /* the token is stored in bits 31...24 */ + if (cfg == _mark) + break; + /* usleep is too coarse, because of CONFIG_HZ=100 in kernel + so use sched_yield to at least give other threads a chance to run */ + sched_yield(); + //fprintf(stderr, "%s: read %02x, expected %02x\n", __FUNCTION__, cfg, _mark); + } while(++count < 8192); /* don't deadlock here if there is an error */ + + if (count > 2048) /* more than 2000 are unlikely, even for large BMP6 blits */ + fprintf(stderr, "CFbAccel::waitForIdle: count is big (%d)!\n", count); +} +#elif HAVE_TRIPLEDRAGON +#include +#include +extern IDirectFB *dfb; +extern IDirectFBSurface *dfbdest; +extern int gfxfd; +void CFbAccel::waitForIdle(void) +{ +#if 0 + struct timeval ts, te; + gettimeofday(&ts, NULL); +#endif + /* does not work: DFBResult r = dfb->WaitForSync(dfb); */ + ioctl(gfxfd, STB04GFX_ENGINE_SYNC); +#if 0 + gettimeofday(&te, NULL); + printf("STB04GFX_ENGINE_SYNC took %lld us\n", (te.tv_sec * 1000000LL + te.tv_usec) - (ts.tv_sec * 1000000LL + ts.tv_usec)); +#endif +} +#elif HAVE_SPARK_HARDWARE + +static int bpafd = -1; +static size_t lbb_sz = 1920 * 1080; /* offset from fb start in 'pixels' */ +static size_t lbb_off = lbb_sz * sizeof(fb_pixel_t); /* same in bytes */ +static int backbuf_sz = 0; + +void CFbAccel::waitForIdle(void) +{ +#if 0 /* blits too often and does not seem to be necessary */ + blit_mutex.lock(); + if (blit_pending) + { + blit_mutex.unlock(); + _blit(); + return; + } + blit_mutex.unlock(); +#endif + OpenThreads::ScopedLock m_lock(mutex); + ioctl(fb->fd, STMFBIO_SYNC_BLITTER); +} +#else +void CFbAccel::waitForIdle(void) +{ +} +#endif + +CFbAccel::CFbAccel(CFrameBuffer *_fb) +{ + blit_thread = false; + fb = _fb; + init(); + lastcol = 0xffffffff; + lbb = fb->lfb; /* the memory area to draw to... */ +#ifdef HAVE_SPARK_HARDWARE + if (fb->available < 12*1024*1024) + { + /* for old installations that did not upgrade their module config + * it will still work good enough to display the message below */ + fprintf(stderr, "[neutrino] WARNING: not enough framebuffer memory available!\n"); + fprintf(stderr, "[neutrino] I need at least 12MB.\n"); + FILE *f = fopen("/tmp/infobar.txt", "w"); + if (f) { + fprintf(f, "NOT ENOUGH FRAMEBUFFER MEMORY!"); + fclose(f); + } + lbb_sz = 0; + lbb_off = 0; + } + lbb = fb->lfb + lbb_sz; + bpafd = open("/dev/bpamem0", O_RDWR | O_CLOEXEC); + if (bpafd < 0) + { + fprintf(stderr, "[neutrino] FB: cannot open /dev/bpamem0: %m\n"); + return; + } + backbuf_sz = 1280 * 720 * sizeof(fb_pixel_t); + BPAMemAllocMemData bpa_data; + bpa_data.bpa_part = (char *)"LMI_VID"; + bpa_data.mem_size = backbuf_sz; + int res; + res = ioctl(bpafd, BPAMEMIO_ALLOCMEM, &bpa_data); + if (res) + { + fprintf(stderr, "[neutrino] FB: cannot allocate from bpamem: %m\n"); + fprintf(stderr, "backbuf_sz: %d\n", backbuf_sz); + close(bpafd); + bpafd = -1; + return; + } + close(bpafd); + + char bpa_mem_device[30]; + sprintf(bpa_mem_device, "/dev/bpamem%d", bpa_data.device_num); + bpafd = open(bpa_mem_device, O_RDWR | O_CLOEXEC); + if (bpafd < 0) + { + fprintf(stderr, "[neutrino] FB: cannot open secondary %s: %m\n", bpa_mem_device); + return; + } + + backbuffer = (fb_pixel_t *)mmap(0, bpa_data.mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, bpafd, 0); + if (backbuffer == MAP_FAILED) + { + fprintf(stderr, "[neutrino] FB: cannot map from bpamem: %m\n"); + ioctl(bpafd, BPAMEMIO_FREEMEM); + close(bpafd); + bpafd = -1; + return; + } +#ifdef PARTIAL_BLIT + to_blit.xs = to_blit.ys = INT_MAX; + to_blit.xe = to_blit.ye = 0; + last_xres = 0; +#endif +#endif + +#ifdef USE_NEVIS_GXA + /* Open /dev/mem for HW-register access */ + devmem_fd = open("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC); + if (devmem_fd < 0) { + perror("CFbAccel open /dev/mem"); + goto error; + } + + /* mmap the GXA's base address */ + gxa_base = (volatile unsigned char*)mmap(0, 0x00040000, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, 0xE0600000); + if (gxa_base == (void *)-1) { + perror("CFbAccel mmap /dev/mem"); + goto error; + } + + setupGXA(); + error: + /* TODO: what to do here? does this really happen? */ + ; +#endif /* USE_NEVIS_GXA */ + +#if NEED_BLIT_THREAD + /* start the autoblit-thread (run() function) */ + OpenThreads::Thread::start(); +#endif +}; + +CFbAccel::~CFbAccel() +{ + if (blit_thread) + { + blit_thread = false; + blit(); /* wakes up the thread */ + OpenThreads::Thread::join(); + } +#if HAVE_SPARK_HARDWARE + if (backbuffer) + { + fprintf(stderr, "CFbAccel: unmap backbuffer\n"); + munmap(backbuffer, backbuf_sz); + } + if (bpafd != -1) + { + fprintf(stderr, "CFbAccel: BPAMEMIO_FREEMEM\n"); + ioctl(bpafd, BPAMEMIO_FREEMEM); + close(bpafd); + } +#endif +#ifdef USE_NEVIS_GXA + if (gxa_base != MAP_FAILED) + munmap((void *)gxa_base, 0x40000); + if (devmem_fd != -1) + close(devmem_fd); +#endif +#if ! HAVE_GENERIC_HARDWARE + if (fb->lfb) + munmap(fb->lfb, fb->available); + if (fb->fd > -1) + close(fb->fd); +#endif +} + +void CFbAccel::update() +{ +#ifndef HAVE_SPARK_HARDWARE + int needmem = fb->stride * fb->yRes * 2; + if (fb->available >= needmem) + { + backbuffer = fb->lfb + fb->stride / sizeof(fb_pixel_t) * fb->yRes; + return; + } + fprintf(stderr, "CFbAccel: not enough FB memory (have %d, need %d)\n", fb->available, needmem); + backbuffer = fb->lfb; /* will not work well, but avoid crashes */ +#endif +} + +void CFbAccel::setColor(fb_pixel_t col) +{ +#if HAVE_TRIPLEDRAGON + if (col == lastcol) + return; + char *c = (char *)&col; + dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]); + lastcol = col; +#elif defined USE_NEVIS_GXA + if (col == lastcol) + return; + _write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int)col); /* setup the drawing color */ + lastcol = col; +#else + (void)col; /* avoid "unused parameter" compiler warning */ +#endif +} + +void CFbAccel::paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col) +{ +#if HAVE_TRIPLEDRAGON + setColor(col); + dfbdest->FillRectangle(dfbdest, x, y, dx, dy); +#elif defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); + unsigned int cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_CMD_NOT_ALPHA | + GXA_SRC_BMP_SEL(6) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2); + + _write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)col); /* setup the drawing color */ + _write_gxa(gxa_base, GXA_BMP6_TYPE_REG, (3 << 16) | (1 << 27)); /* 3 == 32bpp, 1<<27 == fill */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* destination pos */ + _write_gxa(gxa_base, cmd, GXA_POINT(dx, dy)); /* destination size */ + _write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)fb->backgroundColor); + + /* the GXA seems to do asynchronous rendering, so we add a sync marker + to which the fontrenderer code can synchronize */ + add_gxa_sync_marker(); +#elif HAVE_SPARK_HARDWARE + if (dx <= 0 || dy <= 0) + return; + + // The STM blitter introduces considerable overhead probably not worth for single lines. --martii + if (dx == 1) { + waitForIdle(); + fb_pixel_t *fbs = fb->getFrameBufferPointer() + (DEFAULT_XRES * y) + x; + fb_pixel_t *fbe = fbs + DEFAULT_XRES * dy; + while (fbs < fbe) { + *fbs = col; + fbs += DEFAULT_XRES; + } + mark(x , y, x + 1, y + dy); + return; + } + if (dy == 1) { + waitForIdle(); + fb_pixel_t *fbs = fb->getFrameBufferPointer() + (DEFAULT_XRES * y) + x; + fb_pixel_t *fbe = fbs + dx; + while (fbs < fbe) + *fbs++ = col; + mark(x , y, x + dx, y + 1); + return; + } + + /* function has const parameters, so copy them here... */ + int width = dx; + int height = dy; + int xx = x; + int yy = y; + /* maybe we should just return instead of fixing this up... */ + if (x < 0) { + fprintf(stderr, "[neutrino] fb::%s: x < 0 (%d)\n", __func__, x); + width += x; + if (width <= 0) + return; + xx = 0; + } + + if (y < 0) { + fprintf(stderr, "[neutrino] fb::%s: y < 0 (%d)\n", __func__, y); + height += y; + if (height <= 0) + return; + yy = 0; + } + + int right = xx + width; + int bottom = yy + height; + + if (right > (int)fb->xRes) { + if (xx >= (int)fb->xRes) { + fprintf(stderr, "[neutrino] fb::%s: x >= xRes (%d > %d)\n", __func__, xx, fb->xRes); + return; + } + fprintf(stderr, "[neutrino] fb::%s: x+w > xRes! (%d+%d > %d)\n", __func__, xx, width, fb->xRes); + right = fb->xRes; + } + if (bottom > (int)fb->yRes) { + if (yy >= (int)fb->yRes) { + fprintf(stderr, "[neutrino] fb::%s: y >= yRes (%d > %d)\n", __func__, yy, fb->yRes); + return; + } + fprintf(stderr, "[neutrino] fb::%s: y+h > yRes! (%d+%d > %d)\n", __func__, yy, height, fb->yRes); + bottom = fb->yRes; + } + + STMFBIO_BLT_DATA bltData; + memset(&bltData, 0, sizeof(STMFBIO_BLT_DATA)); + + bltData.operation = BLT_OP_FILL; + bltData.dstOffset = lbb_off; + bltData.dstPitch = fb->stride; + + bltData.dst_left = xx; + bltData.dst_top = yy; + bltData.dst_right = right; + bltData.dst_bottom = bottom; + + bltData.dstFormat = SURF_ARGB8888; + bltData.srcFormat = SURF_ARGB8888; + bltData.dstMemBase = STMFBGP_FRAMEBUFFER; + bltData.srcMemBase = STMFBGP_FRAMEBUFFER; + bltData.colour = col; + + mark(xx, yy, bltData.dst_right, bltData.dst_bottom); + OpenThreads::ScopedLock m_lock(mutex); + if (ioctl(fb->fd, STMFBIO_BLT, &bltData ) < 0) + fprintf(stderr, "blitRect FBIO_BLIT: %m x:%d y:%d w:%d h:%d s:%d\n", xx,yy,width,height,fb->stride); +#else + int line = 0; + int swidth = fb->stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = fb->getFrameBufferPointer() + (swidth * y); + int pos; + while (line < dy) + { + for (pos = x; pos < x + dx; pos++) + *(fbp + pos) = col; + fbp += swidth; + line++; + } +#endif + blit(); +} + +void CFbAccel::paintPixel(const int x, const int y, const fb_pixel_t col) +{ +#if HAVE_TRIPLEDRAGON + setColor(col); + dfbdest->DrawLine(dfbdest, x, y, x, y); +#elif defined (USE_NEVIS_GXA) + paintLine(x, y, x + 1, y, col); +#else + fb_pixel_t *pos = fb->getFrameBufferPointer(); + pos += (fb->stride / sizeof(fb_pixel_t)) * y; + pos += x; + *pos = col; +#endif +} + +void CFbAccel::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) +{ +#if HAVE_TRIPLEDRAGON + setColor(col); + dfbdest->DrawLine(dfbdest, xa, ya, xb, yb); +#elif defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); + /* draw a single vertical line from point xa/ya to xb/yb */ + unsigned int cmd = GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(2) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA; + + setColor(col); + _write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */ + _write_gxa(gxa_base, cmd, GXA_POINT(xb, yb)); /* end point */ + _write_gxa(gxa_base, cmd, GXA_POINT(xa, ya)); /* start point */ +#else + int dx = abs (xa - xb); + int dy = abs (ya - yb); + if (dy == 0) /* horizontal line */ + { + /* paintRect actually is 1 pixel short to the right, + * but that's bug-compatibility with the GXA code */ + paintRect(xa, ya, xb - xa, 1, col); + return; + } + if (dx == 0) /* vertical line */ + { + paintRect(xa, ya, 1, yb - ya, col); + return; + } + int x; + int y; + int End; + int step; + + if (dx > dy) + { + int p = 2 * dy - dx; + int twoDy = 2 * dy; + int twoDyDx = 2 * (dy-dx); + + if (xa > xb) + { + x = xb; + y = yb; + End = xa; + step = ya < yb ? -1 : 1; + } + else + { + x = xa; + y = ya; + End = xb; + step = yb < ya ? -1 : 1; + } + + paintPixel(x, y, col); + + while (x < End) + { + x++; + if (p < 0) + p += twoDy; + else + { + y += step; + p += twoDyDx; + } + paintPixel(x, y, col); + } + } + else + { + int p = 2 * dx - dy; + int twoDx = 2 * dx; + int twoDxDy = 2 * (dx-dy); + + if (ya > yb) + { + x = xb; + y = yb; + End = ya; + step = xa < xb ? -1 : 1; + } + else + { + x = xa; + y = ya; + End = yb; + step = xb < xa ? -1 : 1; + } + + paintPixel(x, y, col); + + while (y < End) + { + y++; + if (p < 0) + p += twoDx; + else + { + x += step; + p += twoDxDy; + } + paintPixel(x, y, col); + } + } + mark(xa, ya, xb, yb); + blit(); +#endif +} + +#if !HAVE_TRIPLEDRAGON +void CFbAccel::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) +{ +#if !HAVE_SPARK_HARDWARE + int xc, yc; + xc = (width > fb->xRes) ? fb->xRes : width; + yc = (height > fb->yRes) ? fb->yRes : height; +#endif +#if defined(FB_HW_ACCELERATION) + if(!(width%4)) { + fb_image image; + image.dx = xoff; + image.dy = yoff; + image.width = xc; + image.height = yc; + image.cmap.len = 0; + image.depth = 32; + image.data = (const char*)fbbuff; + ioctl(fb->fd, FBIO_IMAGE_BLT, &image); + //printf("\033[33m>>>>\033[0m [%s:%s:%d] FB_HW_ACCELERATION x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); + return; + } + printf("\033[31m>>>>\033[0m [%s:%s:%d] Not use FB_HW_ACCELERATION x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); +#elif defined(USE_NEVIS_GXA) + (void)transp; + u32 cmd; + void *uKva; + + uKva = cs_phys_addr(fbbuff); + //printf("CFbAccel::blit2FB: data %x Kva %x\n", (int) fbbuff, (int) uKva); + + if (uKva != NULL) { + OpenThreads::ScopedLock m_lock(mutex); + cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(1) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(3); + + _write_gxa(gxa_base, GXA_BMP1_TYPE_REG, (3 << 16) | width); + _write_gxa(gxa_base, GXA_BMP1_ADDR_REG, (unsigned int)uKva); + + _write_gxa(gxa_base, cmd, GXA_POINT(xoff, yoff)); /* destination pos */ + _write_gxa(gxa_base, cmd, GXA_POINT(xc, yc)); /* source width, FIXME real or adjusted xc, yc ? */ + _write_gxa(gxa_base, cmd, GXA_POINT(xp, yp)); /* source pos */ + + return; + } +#elif HAVE_SPARK_HARDWARE + int x, y, dw, dh; + x = xoff; + y = yoff; + dw = width - xp; + dh = height - yp; + + size_t mem_sz = width * height * sizeof(fb_pixel_t); + unsigned long ulFlags = 0; + if (!transp) /* transp == false (default): use transparency from source alphachannel */ + ulFlags = BLT_OP_FLAGS_BLEND_SRC_ALPHA|BLT_OP_FLAGS_BLEND_DST_MEMORY; // we need alpha blending + + STMFBIO_BLT_EXTERN_DATA blt_data; + memset(&blt_data, 0, sizeof(STMFBIO_BLT_EXTERN_DATA)); + blt_data.operation = BLT_OP_COPY; + blt_data.ulFlags = ulFlags; + blt_data.srcOffset = 0; + blt_data.srcPitch = width * 4; + blt_data.dstOffset = lbb_off; + blt_data.dstPitch = fb->stride; + blt_data.src_left = xp; + blt_data.src_top = yp; + blt_data.src_right = width; + blt_data.src_bottom = height; + blt_data.dst_left = x; + blt_data.dst_top = y; + blt_data.dst_right = x + dw; + blt_data.dst_bottom = y + dh; + blt_data.srcFormat = SURF_ARGB8888; + blt_data.dstFormat = SURF_ARGB8888; + blt_data.srcMemBase = (char *)backbuffer; + blt_data.dstMemBase = (char *)fb->lfb; + blt_data.srcMemSize = mem_sz; + blt_data.dstMemSize = fb->stride * fb->yRes + lbb_off; + + mark(x, y, blt_data.dst_right, blt_data.dst_bottom); + OpenThreads::ScopedLock m_lock(mutex); + ioctl(fb->fd, STMFBIO_SYNC_BLITTER); + if (fbbuff != backbuffer) + memmove(backbuffer, fbbuff, mem_sz); + // icons are so small that they will still be in cache + msync(backbuffer, backbuf_sz, MS_SYNC); + + if (ioctl(fb->fd, STMFBIO_BLT_EXTERN, &blt_data) < 0) + perror("CFbAccel blit2FB STMFBIO_BLT_EXTERN"); + return; +#endif + fb_pixel_t *data = (fb_pixel_t *) fbbuff; + + uint8_t *d = (uint8_t *)lbb + xoff * sizeof(fb_pixel_t) + fb->stride * yoff; + fb_pixel_t * d2; + + for (int count = 0; count < yc; count++ ) { + fb_pixel_t *pixpos = &data[(count + yp) * width]; + d2 = (fb_pixel_t *) d; + for (int count2 = 0; count2 < xc; count2++ ) { + fb_pixel_t pix = *(pixpos + xp); + if (transp || (pix & 0xff000000) == 0xff000000) + *d2 = pix; + else { + uint8_t *in = (uint8_t *)(pixpos + xp); + uint8_t *out = (uint8_t *)d2; + int a = in[3]; /* TODO: big/little endian */ + *out = (*out + ((*in - *out) * a) / 256); + in++; out++; + *out = (*out + ((*in - *out) * a) / 256); + in++; out++; + *out = (*out + ((*in - *out) * a) / 256); + } + d2++; + pixpos++; + } + d += fb->stride; + } + blit(); +#if 0 + for(int i = 0; i < yc; i++){ + memmove(clfb + (i + yoff)*stride + xoff*4, ip + (i + yp)*width + xp, xc*4); + } +#endif +} +#else +void CFbAccel::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) +{ + DFBRectangle src; + DFBResult err; + IDirectFBSurface *surf; + DFBSurfaceDescription dsc; + + src.x = xp; + src.y = yp; + src.w = width - xp; + src.h = height - yp; + + dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED); + dsc.caps = DSCAPS_NONE; + dsc.width = width; + dsc.height = height; + dsc.preallocated[0].data = fbbuff; + dsc.preallocated[0].pitch = width * sizeof(fb_pixel_t); + err = dfb->CreateSurface(dfb, &dsc, &surf); + /* TODO: maybe we should not die if this fails? */ + if (err != DFB_OK) { + fprintf(stderr, "CFbAccel::blit2FB: "); + DirectFBErrorFatal("dfb->CreateSurface(dfb, &dsc, &surf)", err); + } + + if (transp) + { + surf->SetSrcColorKey(surf, 0, 0, 0); + dfbdest->SetBlittingFlags(dfbdest, DSBLIT_SRC_COLORKEY); + } + else + dfbdest->SetBlittingFlags(dfbdest, DSBLIT_BLEND_ALPHACHANNEL); + + dfbdest->Blit(dfbdest, surf, &src, xoff, yoff); + surf->Release(surf); + return; +} +#endif + +#ifdef USE_NEVIS_GXA +void CFbAccel::setupGXA() +{ + // We (re)store the GXA regs here in case DFB override them and was not + // able to restore them. + _write_gxa(gxa_base, GXA_BMP2_TYPE_REG, (3 << 16) | (unsigned int)fb->screeninfo.xres); + _write_gxa(gxa_base, GXA_BMP2_ADDR_REG, (unsigned int) fb->fix.smem_start); + _write_gxa(gxa_base, GXA_BLEND_CFG_REG, 0x00089064); + // TODO check mono-flip, bit 8 + _write_gxa(gxa_base, GXA_CFG_REG, 0x100 | (1 << 12) | (1 << 29)); + _write_gxa(gxa_base, GXA_CFG2_REG, 0x1FF); + _write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int)fb->backgroundColor); + add_gxa_sync_marker(); +} +#endif + +#define BLIT_INTERVAL_MIN 40 +#define BLIT_INTERVAL_MAX 250 +void CFbAccel::run() +{ + printf("CFbAccel::run start\n"); + time_t last_blit = 0; + blit_pending = false; + blit_thread = true; + blit_mutex.lock(); + set_threadname("fb::autoblit"); + while (blit_thread) { + blit_cond.wait(&blit_mutex, blit_pending ? BLIT_INTERVAL_MIN : BLIT_INTERVAL_MAX); + time_t now = time_monotonic_ms(); + if (now - last_blit < BLIT_INTERVAL_MIN) + { + blit_pending = true; + //printf("CFbAccel::run: skipped, time %ld\n", now - last_blit); + } + else + { + blit_pending = false; + blit_mutex.unlock(); + _blit(); + blit_mutex.lock(); + last_blit = now; + } + } + blit_mutex.unlock(); + printf("CFbAccel::run end\n"); +} + +void CFbAccel::blit() +{ + //printf("CFbAccel::blit\n"); + blit_mutex.lock(); + blit_cond.signal(); + blit_mutex.unlock(); +} + +#if HAVE_SPARK_HARDWARE +void CFbAccel::_blit() +{ +#if 0 + static time_t last = 0; + time_t now = time_monotonic_ms(); + printf("%s %ld\n", __func__, now - last); + last = now; +#endif + OpenThreads::ScopedLock m_lock(mutex); +#ifdef PARTIAL_BLIT + if (to_blit.xs == INT_MAX) + return; + + int srcXa = to_blit.xs; + int srcYa = to_blit.ys; + int srcXb = to_blit.xe; + int srcYb = to_blit.ye; +#else + const int srcXa = 0; + const int srcYa = 0; + int srcXb = fb->xRes; + int srcYb = fb->yRes; +#endif + STMFBIO_BLT_DATA bltData; + memset(&bltData, 0, sizeof(STMFBIO_BLT_DATA)); + + bltData.operation = BLT_OP_COPY; + //bltData.ulFlags = BLT_OP_FLAGS_BLEND_SRC_ALPHA | BLT_OP_FLAGS_BLEND_DST_MEMORY; // we need alpha blending + // src + bltData.srcOffset = lbb_off; + bltData.srcPitch = fb->stride; + + bltData.src_left = srcXa; + bltData.src_top = srcYa; + bltData.src_right = srcXb; + bltData.src_bottom = srcYb; + + bltData.srcFormat = SURF_BGRA8888; + bltData.srcMemBase = STMFBGP_FRAMEBUFFER; + + /* calculate dst/blit factor */ + fb_var_screeninfo s; + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &s) == -1) + perror("CFbAccel "); + +#ifdef PARTIAL_BLIT + if (s.xres != last_xres) /* fb resolution has changed -> clear artifacts */ + { + last_xres = s.xres; + bltData.src_left = 0; + bltData.src_top = 0; + bltData.src_right = fb->xRes; + bltData.src_bottom = fb->yRes; + } + + double xFactor = (double)s.xres/(double)fb->xRes; + double yFactor = (double)s.yres/(double)fb->yRes; + + int desXa = xFactor * bltData.src_left; + int desYa = yFactor * bltData.src_top; + int desXb = xFactor * bltData.src_right; + int desYb = yFactor * bltData.src_bottom; +#else + const int desXa = 0; + const int desYa = 0; + int desXb = s.xres; + int desYb = s.yres; +#endif + + /* dst */ + bltData.dstOffset = 0; + bltData.dstPitch = s.xres * 4; + + bltData.dst_left = desXa; + bltData.dst_top = desYa; + bltData.dst_right = desXb; + bltData.dst_bottom = desYb; + + bltData.dstFormat = SURF_BGRA8888; + bltData.dstMemBase = STMFBGP_FRAMEBUFFER; + + //printf("CFbAccel::blit: sx:%d sy:%d sxe:%d sye: %d dx:%d dy:%d dxe:%d dye:%d\n", srcXa, srcYa, srcXb, srcYb, desXa, desYa, desXb, desYb); + if ((bltData.dst_right > s.xres) || (bltData.dst_bottom > s.yres)) + printf("CFbAccel::blit: values out of range desXb:%d desYb:%d\n", + bltData.dst_right, bltData.dst_bottom); + + if(ioctl(fb->fd, STMFBIO_SYNC_BLITTER) < 0) + perror("CFbAccel::blit ioctl STMFBIO_SYNC_BLITTER 1"); + msync(lbb, fb->xRes * 4 * fb->yRes, MS_SYNC); + if (ioctl(fb->fd, STMFBIO_BLT, &bltData ) < 0) + perror("STMFBIO_BLT"); + if(ioctl(fb->fd, STMFBIO_SYNC_BLITTER) < 0) + perror("CFbAccel::blit ioctl STMFBIO_SYNC_BLITTER 2"); + +#ifdef PARTIAL_BLIT + to_blit.xs = to_blit.ys = INT_MAX; + to_blit.xe = to_blit.ye = 0; +#endif +} + +#elif HAVE_AZBOX_HARDWARE + +#ifndef FBIO_WAITFORVSYNC +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#endif +#ifndef FBIO_BLIT +#define FBIO_BLIT 0x22 +#define FBIO_SET_MANUAL_BLIT _IOW('F', 0x21, __u8) +#endif +static bool autoblit = getenv("AZBOX_KERNEL_BLIT") ? true : false; +void CFbAccel::_blit() +{ + if (autoblit) + return; + // blit + if (ioctl(fb->fd, FBIO_BLIT) < 0) + perror("CFbAccel FBIO_BLIT"); +#if 0 + // sync bliter + int c = 0; + if( ioctl(fd, FBIO_WAITFORVSYNC, &c) < 0 ) + perror("FBIO_WAITFORVSYNC"); +#endif +} + +#else +/* not azbox and not spark -> no blit() needed */ +void CFbAccel::_blit() +{ +#if HAVE_GENERIC_HARDWARE + if (glfb) + glfb->blit(); +#endif +} +#endif + +/* not really used yet */ +#ifdef PARTIAL_BLIT +void CFbAccel::mark(int xs, int ys, int xe, int ye) +{ + OpenThreads::ScopedLock m_lock(mutex); + if (xs < to_blit.xs) + to_blit.xs = xs; + if (ys < to_blit.ys) + to_blit.ys = ys; + if (xe > to_blit.xe) { + if (xe >= (int)fb->xRes) + to_blit.xe = fb->xRes - 1; + else + to_blit.xe = xe; + } + if (ye > to_blit.ye) { + if (ye >= (int)fb->xRes) + to_blit.ye = fb->yRes - 1; + else + to_blit.ye = ye; + } +#if 0 + /* debug code that kills neutrino right away if the blit area is invalid + * only enable this for creating a coredumo for debugging */ + fb_var_screeninfo s; + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &s) == -1) + perror("CFbAccel "); + if ((xe > s.xres) || (ye > s.yres)) { + fprintf(stderr, "CFbAccel::mark: values out of range xe:%d ye:%d\n", xe, ye); + int *kill = NULL; + *kill = 1; /* oh my */ + } +#endif +} +#else +void CFbAccel::mark(int, int, int, int) +{ +} +#endif + +bool CFbAccel::init(void) +{ + fb_pixel_t *lfb; + fb->lfb = NULL; + fb->fd = -1; +#if HAVE_GENERIC_HARDWARE + if (!glfb) { + fprintf(stderr, "CFbAccel::init: GL Framebuffer is not set up? we are doomed...\n"); + return false; + } + fb->screeninfo = glfb->getScreenInfo(); + fb->stride = 4 * fb->screeninfo.xres; + fb->available = glfb->getOSDBuffer()->size(); /* allocated in glfb constructor */ + lfb = reinterpret_cast(glfb->getOSDBuffer()->data()); +#else + int fd; +#if HAVE_TRIPLEDRAGON + /* kernel is too old for O_CLOEXEC :-( */ + fd = open("/dev/fb0", O_RDWR); + if (fd != -1) + fcntl(fd, F_SETFD, FD_CLOEXEC); +#else + fd = open("/dev/fb0", O_RDWR|O_CLOEXEC); +#endif + if (fd < 0) { + perror("open /dev/fb0"); + return false; + } + fb->fd = fd; + + if (ioctl(fd, FBIOGET_VSCREENINFO, &fb->screeninfo) < 0) { + perror("FBIOGET_VSCREENINFO"); + return false; + } + + if (ioctl(fd, FBIOGET_FSCREENINFO, &fb->fix) < 0) { + perror("FBIOGET_FSCREENINFO"); + return false; + } + + fb->available = fb->fix.smem_len; + printf("%dk video mem\n", fb->available / 1024); + lfb = (fb_pixel_t *)mmap(0, fb->available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); + + if (lfb == MAP_FAILED) { + perror("mmap"); + return false;; + } +#endif /* ! GENERIC_HARDWARE */ + + memset(lfb, 0, fb->available); + fb->lfb = lfb; + return true; +} + +/* wrong name... */ +int CFbAccel::setMode(void) +{ + int fd = fb->fd; + t_fb_var_screeninfo *si = &fb->screeninfo; +#if HAVE_AZBOX_HARDWARE + // set auto blit if AZBOX_KERNEL_BLIT environment variable is set + unsigned char tmp = getenv("AZBOX_KERNEL_BLIT") ? 0 : 1; + if (ioctl(fd, FBIO_SET_MANUAL_BLIT, &tmp) < 0) + perror("FBIO_SET_MANUAL_BLIT"); + + const unsigned int nxRes = DEFAULT_XRES; + const unsigned int nyRes = DEFAULT_YRES; + const unsigned int nbpp = DEFAULT_BPP; + si->xres_virtual = si->xres = nxRes; + si->yres_virtual = (si->yres = nyRes) * 2; + si->height = 0; + si->width = 0; + si->xoffset = si->yoffset = 0; + si->bits_per_pixel = nbpp; + + si->transp.offset = 24; + si->transp.length = 8; + si->red.offset = 16; + si->red.length = 8; + si->green.offset = 8; + si->green.length = 8; + si->blue.offset = 0; + si->blue.length = 8; + + if (ioctl(fd, FBIOPUT_VSCREENINFO, si) < 0) { + // try single buffering + si->yres_virtual = si->yres = nyRes; + if (ioctl(fd, FBIOPUT_VSCREENINFO, si) < 0) + perror("FBIOPUT_VSCREENINFO"); + printf("FB: double buffering not available.\n"); + } + else + printf("FB: double buffering available!\n"); + + ioctl(fd, FBIOGET_VSCREENINFO, si); + + if (si->xres != nxRes || si->yres != nyRes || si->bits_per_pixel != nbpp) + { + printf("SetMode failed: wanted: %dx%dx%d, got %dx%dx%d\n", + nxRes, nyRes, nbpp, + si->xres, si->yres, si->bits_per_pixel); + } +#endif +#if HAVE_SPARK_HARDWARE + /* it's all fake... :-) */ + si->xres = si->xres_virtual = DEFAULT_XRES; + si->yres = si->yres_virtual = DEFAULT_YRES; + si->bits_per_pixel = DEFAULT_BPP; + fb->stride = si->xres * si->bits_per_pixel / 8; +#else +#if ! HAVE_GENERIC_HARDWARE + fb_fix_screeninfo _fix; + + if (ioctl(fd, FBIOGET_FSCREENINFO, &_fix) < 0) { + perror("FBIOGET_FSCREENINFO"); + return -1; + } + fb->stride = _fix.line_length; +#endif +#endif +#if HAVE_COOL_HARDWARE + if (ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) + printf("screen unblanking failed\n"); +#endif + /* avoid compiler warnings on various platforms */ + (void) fd; + (void) si; + return 0; +} + +#if HAVE_COOL_HARDWARE + +void CFbAccel::paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col) +{ + +#if defined(FB_HW_ACCELERATION) + fb_fillrect fillrect; + fillrect.dx = x; + fillrect.dy = y; + fillrect.width = 1; + fillrect.height = dy; + fillrect.color = col; + fillrect.rop = ROP_COPY; + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); +#elif defined(USE_NEVIS_GXA) + /* draw a single vertical line from point x/y with hight dx */ + unsigned int cmd = GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(2) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA; + + _write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int) col); /* setup the drawing color */ + _write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y + dy)); /* end point */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* start point */ +#else /* USE_NEVIS_GXA */ + uint8_t * pos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + + for(int count=0;count= 10) { + fb_fillrect fillrect; + fillrect.dx = x; + fillrect.dy = y; + fillrect.width = dx; + fillrect.height = 1; + fillrect.color = col; + fillrect.rop = ROP_COPY; + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); + return; + } +#endif +#if defined(USE_NEVIS_GXA) + /* draw a single horizontal line from point x/y with width dx */ + unsigned int cmd = GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(2) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA; + + _write_gxa(gxa_base, GXA_FG_COLOR_REG, (unsigned int) col); /* setup the drawing color */ + _write_gxa(gxa_base, GXA_LINE_CONTROL_REG, 0x00000404); /* X is major axis, skip last pixel */ + _write_gxa(gxa_base, cmd, GXA_POINT(x + dx, y)); /* end point */ + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* start point */ +#else /* USE_NEVIS_GXA */ + uint8_t * pos = ((uint8_t *)fb->getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + fb->stride * y; + + fb_pixel_t * dest = (fb_pixel_t *)pos; + for (int i = 0; i < dx; i++) + *(dest++) = col; +#endif /* USE_NEVIS_GXA */ +} + +void CFbAccel::paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type) +{ + /* draw a filled rectangle (with additional round corners) */ + if (dx == 0 || dy == 0) { + dprintf(DEBUG_NORMAL, "[CFbAccel] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __FUNCTION__, __LINE__, radius, x, y, x+dx, y+dy); + return; + } + + bool corner_tl = !!(type & CORNER_TOP_LEFT); + bool corner_tr = !!(type & CORNER_TOP_RIGHT); + bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); + bool corner_br = !!(type & CORNER_BOTTOM_RIGHT); + +#if defined(FB_HW_ACCELERATION) + fb_fillrect fillrect; + fillrect.color = col; + fillrect.rop = ROP_COPY; +#elif defined(USE_NEVIS_GXA) + if (!fb_no_check) + OpenThreads::ScopedLock m_lock(mutex); + /* solid fill with background color */ + unsigned int cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(7) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(2) | GXA_CMD_NOT_ALPHA; + _write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int) col); /* setup the drawing color */ +#endif + + if (type && radius) { + radius = fb->limitRadius(dx, dy, radius); + + int line = 0; + while (line < dy) { + int ofl, ofr; + if (fb->calcCorners(NULL, &ofl, &ofr, dy, line, radius, + corner_tl, corner_tr, corner_bl, corner_br)) { + //printf("3: x %d y %d dx %d dy %d rad %d line %d\n", x, y, dx, dy, radius, line); +#if defined(FB_HW_ACCELERATION) || defined(USE_NEVIS_GXA) + int rect_height_mult = ((type & CORNER_TOP) && (type & CORNER_BOTTOM)) ? 2 : 1; +#if defined(FB_HW_ACCELERATION) + fillrect.dx = x; + fillrect.dy = y + line; + fillrect.width = dx; + fillrect.height = dy - (radius * rect_height_mult); + + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); +#elif defined(USE_NEVIS_GXA) + _write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0); + _write_gxa(gxa_base, cmd, GXA_POINT(x, y + line)); /* destination x/y */ + _write_gxa(gxa_base, cmd, GXA_POINT(dx, dy - (radius * rect_height_mult))); /* width/height */ +#endif + line += dy - (radius * rect_height_mult); + continue; +#endif + } + + if (dx-ofr-ofl < 1) { + if (dx-ofr-ofl == 0){ + dprintf(DEBUG_INFO, "[CFbAccel] [%s - %d]: radius %d, start x %d y %d end x %d y %d\n", __func__, __LINE__, radius, x, y, x+dx-ofr-ofl, y+line); + }else{ + dprintf(DEBUG_INFO, "[CFbAccel] [%s - %04d]: Calculated width: %d\n (radius %d, dx %d, offsetLeft %d, offsetRight %d).\n Width can not be less than 0, abort.\n", + __func__, __LINE__, dx-ofr-ofl, radius, dx, ofl, ofr); + } + line++; + continue; + } +#ifdef USE_NEVIS_GXA + _write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0); + _write_gxa(gxa_base, cmd, GXA_POINT(x + ofl, y + line)); /* destination x/y */ + _write_gxa(gxa_base, cmd, GXA_POINT(dx-ofl-ofr, 1)); /* width/height */ +#else + paintHLineRelInternal(x+ofl, dx-ofl-ofr, y+line, col); +#endif + line++; + } + } else { +#if defined(FB_HW_ACCELERATION) + /* FIXME small size faster to do by software */ + if (dx > 10 || dy > 10) { + fillrect.dx = x; + fillrect.dy = y; + fillrect.width = dx; + fillrect.height = dy; + ioctl(fb->fd, FBIO_FILL_RECT, &fillrect); + return; + } +#endif +#if defined(USE_NEVIS_GXA) + _write_gxa(gxa_base, GXA_BLT_CONTROL_REG, 0); + _write_gxa(gxa_base, cmd, GXA_POINT(x, y)); /* destination x/y */ + _write_gxa(gxa_base, cmd, GXA_POINT(dx, dy)); /* width/height */ +#else + int swidth = fb->stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = fb->getFrameBufferPointer() + (swidth * y); + int line = 0; + while (line < dy) { + for (int pos = x; pos < x + dx; pos++) + *(fbp + pos) = col; + + fbp += swidth; + line++; + } +#endif + } +#ifdef USE_NEVIS_GXA + _write_gxa(gxa_base, GXA_BG_COLOR_REG, (unsigned int) backgroundColor); //FIXME needed ? + /* the GXA seems to do asynchronous rendering, so we add a sync marker + * to which the fontrenderer code can synchronize + */ + add_gxa_sync_marker(); +#endif +} + +void CFbAccel::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff) +{ + uint32_t xc = (width > fb->getScreenWidth(true)) ? (uint32_t)fb->getScreenWidth(true) : width; + uint32_t yc = (height > fb->getScreenHeight(true)) ? (uint32_t)fb->getScreenHeight(true) : height; + +#if defined(FB_HW_ACCELERATION) + if (!(width%4)) { + fb_image image; + image.dx = xoff; + image.dy = yoff; + image.width = xc; + image.height = yc; + image.cmap.len = 0; + image.depth = 32; + image.data = (const char*)boxBuf; + ioctl(fb->fd, FBIO_IMAGE_BLT, &image); + //printf("\033[33m>>>>\033[0m [%s:%s:%d] FB_HW_ACCELERATION x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); + return; + } + printf("\033[31m>>>>\033[0m [%s:%s:%d] Not use FB_HW_ACCELERATION x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); +#elif defined(USE_NEVIS_GXA) + void* uKva = cs_phys_addr((void*)boxBuf); + if(uKva != NULL) { + OpenThreads::ScopedLock m_lock(mutex); + u32 cmd = GXA_CMD_BLT | GXA_CMD_NOT_TEXT | GXA_SRC_BMP_SEL(1) | GXA_DST_BMP_SEL(2) | GXA_PARAM_COUNT(3); + _write_gxa(gxa_base, GXA_BMP1_TYPE_REG, (3 << 16) | width); + _write_gxa(gxa_base, GXA_BMP1_ADDR_REG, (unsigned int) uKva); + _write_gxa(gxa_base, cmd, GXA_POINT(xoff, yoff)); + _write_gxa(gxa_base, cmd, GXA_POINT(xc, yc)); + _write_gxa(gxa_base, cmd, GXA_POINT(0, 0)); + //printf("\033[33m>>>>\033[0m [%s:%s:%d] USE_NEVIS_GXA x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); + add_gxa_sync_marker(); + return; + } + printf("\033[31m>>>>\033[0m [%s:%s:%d] Not use USE_NEVIS_GXA x: %d, y: %d, w: %d, h: %d\n", __file__, __func__, __LINE__, xoff, yoff, xc, yc); +#endif + uint32_t swidth = fb->stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = fb->getFrameBufferPointer() + (swidth * yoff); + fb_pixel_t* data = (fb_pixel_t*)boxBuf; + + uint32_t line = 0; + while (line < yc) { + fb_pixel_t *pixpos = &data[line * xc]; + for (uint32_t pos = xoff; pos < xoff + xc; pos++) { + //don't paint backgroundcolor (*pixpos = 0x00000000) + if (*pixpos) + *(fbp + pos) = *pixpos; + pixpos++; + } + fbp += swidth; + line++; + } +} + +#endif // #if HAVE_COOL_HARDWARE diff --git a/src/driver/fbaccel.h b/src/driver/fbaccel.h new file mode 100644 index 000000000..5d3375d6a --- /dev/null +++ b/src/driver/fbaccel.h @@ -0,0 +1,101 @@ +/* + Copyright (C) 2007-2013 Stefan Seyfried + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + private functions for the fbaccel class (only used in CFrameBuffer) +*/ + + +#ifndef __fbaccel__ +#define __fbaccel__ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SPARK_HARDWARE +#define PARTIAL_BLIT 1 +#endif + +class CFrameBuffer; +class CFbAccel + : public OpenThreads::Thread +{ + private: + CFrameBuffer *fb; + fb_pixel_t lastcol; + OpenThreads::Mutex mutex; +#ifdef USE_NEVIS_GXA + int devmem_fd; /* to access the GXA register we use /dev/mem */ + unsigned int smem_start; /* as aquired from the fbdev, the framebuffers physical start address */ + volatile uint8_t *gxa_base; /* base address for the GXA's register access */ + void add_gxa_sync_marker(void); +#endif /* USE_NEVIS_GXA */ + void setColor(fb_pixel_t col); + void run(void); + void blit(void); + void _blit(void); + bool blit_thread; + bool blit_pending; + OpenThreads::Condition blit_cond; + OpenThreads::Mutex blit_mutex; +#ifdef PARTIAL_BLIT + OpenThreads::Mutex to_blit_mutex; + struct { + int xs; + int ys; + int xe; + int ye; + } to_blit; + uint32_t last_xres; +#endif + public: + fb_pixel_t *backbuffer; + fb_pixel_t *lbb; + CFbAccel(CFrameBuffer *fb); + ~CFbAccel(); + bool init(void); + int setMode(void); + void paintPixel(int x, int y, const fb_pixel_t col); + void paintRect(const int x, const int y, const int dx, const int dy, const fb_pixel_t col); + void paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col); + void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp); + void waitForIdle(void); + void mark(int x, int y, int dx, int dy); + void update(); +#ifdef USE_NEVIS_GXA + void setupGXA(void); +#endif + +#if HAVE_COOL_HARDWARE + void paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col); + void paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col); + void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type); + void blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff); +#endif +}; + +#endif diff --git a/src/driver/file.h b/src/driver/file.h index b26e52475..e8d7ff8b8 100644 --- a/src/driver/file.h +++ b/src/driver/file.h @@ -33,12 +33,16 @@ #ifndef __FILE_H__ #define __FILE_H__ +#include +#if 0 +/* this is already done by AC_SYS_LARGEFILE */ #include /* make sure off_t has size 8 in __USE_FILE_OFFSET64 mode */ #ifndef __USE_FILE_OFFSET64 -#define __USE_FILE_OFFSET64 +#error not using 64 bit file offsets #endif /* __USE_FILE__OFFSET64 */ +#endif #include #include diff --git a/src/driver/fontrenderer.cpp b/src/driver/fontrenderer.cpp index 7f76ff854..f000fc84f 100644 --- a/src/driver/fontrenderer.cpp +++ b/src/driver/fontrenderer.cpp @@ -629,6 +629,8 @@ void Font::RenderString(int x, int y, const int width, const char *text, const f //printf("RenderStat: %d %d %d \n", renderer->cacheManager->num_nodes, renderer->cacheManager->num_bytes, renderer->cacheManager->max_bytes); pthread_mutex_unlock( &renderer->render_mutex ); frameBuffer->checkFbArea(x, y-height, width, height, false); + /* x is the rightmost position of the last drawn character */ + frameBuffer->mark(left, y + lower - height, x, y + lower); } void Font::RenderString(int x, int y, const int width, const std::string & text, const fb_pixel_t color, const int boxheight, const unsigned int flags) diff --git a/src/driver/framebuffer.h b/src/driver/framebuffer.h index 5150b17de..103ee6d01 100644 --- a/src/driver/framebuffer.h +++ b/src/driver/framebuffer.h @@ -21,6 +21,8 @@ Boston, MA 02110-1301, USA. */ +#include "framebuffer_ng.h" +#if 0 #ifndef __framebuffer__ #define __framebuffer__ @@ -331,7 +333,9 @@ class CFrameBuffer : public sigc::trackable void fbNoCheck(bool noCheck) { fb_no_check = noCheck; } void doPaintMuteIcon(bool mode) { do_paint_mute_icon = mode; } void blit(void) {} + void mark(int, int, int, int) {} sigc::signal OnAfterSetPallette; }; #endif +#endif diff --git a/src/driver/framebuffer_ng.cpp b/src/driver/framebuffer_ng.cpp new file mode 100644 index 000000000..570558c27 --- /dev/null +++ b/src/driver/framebuffer_ng.cpp @@ -0,0 +1,1485 @@ +/* + Neutrino-GUI - DBoxII-Project + + Copyright (C) 2001 Steffen Hehn 'McClean' + 2003 thegoodguy + Copyright (C) 2007-2015 Stefan Seyfried + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_COOL_HARDWARE +#include +#endif +#if HAVE_TRIPLEDRAGON +#ifdef SCALE +#undef SCALE +#endif +#include +extern int gfxfd; +#endif + +extern CPictureViewer * g_PicViewer; +#define ICON_CACHE_SIZE 1024*1024*2 // 2mb + +#define BACKGROUNDIMAGEWIDTH 720 + +/* note that it is *not* enough to just change those values */ +#define DEFAULT_XRES 1280 +#define DEFAULT_YRES 720 +#define DEFAULT_BPP 32 + +/*******************************************************************************/ + +void CFrameBuffer::waitForIdle(const char *) +{ + accel->waitForIdle(); +} + +/*******************************************************************************/ + +static uint8_t * virtual_fb = NULL; +inline unsigned int make16color(uint16_t r, uint16_t g, uint16_t b, uint16_t t, + uint32_t /*rl*/ = 0, uint32_t /*ro*/ = 0, + uint32_t /*gl*/ = 0, uint32_t /*go*/ = 0, + uint32_t /*bl*/ = 0, uint32_t /*bo*/ = 0, + uint32_t /*tl*/ = 0, uint32_t /*to*/ = 0) +{ + return ((t << 24) & 0xFF000000) | ((r << 8) & 0xFF0000) | ((g << 0) & 0xFF00) | (b >> 8 & 0xFF); +} + +/* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed + radius of 540 px which is the half of the max HD graphics size of 1080 px. So with that table we + ca draw boxes with round corners and als circles by just setting dx = dy = radius (max 540). */ +static const int q_circle[541] = { + 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, + 539, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 537, 537, 537, 537, 537, 537, 537, + 537, 537, 536, 536, 536, 536, 536, 536, 536, 536, 535, 535, 535, 535, 535, 535, 535, 535, 534, 534, + 534, 534, 534, 534, 533, 533, 533, 533, 533, 533, 532, 532, 532, 532, 532, 532, 531, 531, 531, 531, + 531, 531, 530, 530, 530, 530, 529, 529, 529, 529, 529, 529, 528, 528, 528, 528, 527, 527, 527, 527, + 527, 526, 526, 526, 526, 525, 525, 525, 525, 524, 524, 524, 524, 523, 523, 523, 523, 522, 522, 522, + 522, 521, 521, 521, 521, 520, 520, 520, 519, 519, 519, 518, 518, 518, 518, 517, 517, 517, 516, 516, + 516, 515, 515, 515, 515, 514, 514, 514, 513, 513, 513, 512, 512, 512, 511, 511, 511, 510, 510, 510, + 509, 509, 508, 508, 508, 507, 507, 507, 506, 506, 506, 505, 505, 504, 504, 504, 503, 503, 502, 502, + 502, 501, 501, 500, 500, 499, 499, 499, 498, 498, 498, 497, 497, 496, 496, 496, 495, 495, 494, 494, + 493, 493, 492, 492, 491, 491, 490, 490, 490, 489, 489, 488, 488, 487, 487, 486, 486, 485, 485, 484, + 484, 483, 483, 482, 482, 481, 481, 480, 480, 479, 479, 478, 478, 477, 477, 476, 476, 475, 475, 474, + 473, 473, 472, 472, 471, 471, 470, 470, 469, 468, 468, 467, 466, 466, 465, 465, 464, 464, 463, 462, + 462, 461, 460, 460, 459, 459, 458, 458, 457, 456, 455, 455, 454, 454, 453, 452, 452, 451, 450, 450, + 449, 449, 448, 447, 446, 446, 445, 445, 444, 443, 442, 441, 441, 440, 440, 439, 438, 437, 436, 436, + 435, 435, 434, 433, 432, 431, 431, 430, 429, 428, 427, 427, 426, 425, 425, 424, 423, 422, 421, 421, + 420, 419, 418, 417, 416, 416, 415, 414, 413, 412, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, + 403, 402, 401, 400, 399, 398, 397, 397, 395, 394, 393, 393, 392, 391, 390, 389, 388, 387, 386, 385, + 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, 369, 368, 367, 367, 365, 364, + 363, 362, 361, 360, 358, 357, 356, 355, 354, 353, 352, 351, 350, 348, 347, 346, 345, 343, 342, 341, + 340, 339, 337, 336, 335, 334, 332, 331, 329, 328, 327, 326, 324, 323, 322, 321, 319, 317, 316, 315, + 314, 312, 310, 309, 308, 307, 305, 303, 302, 301, 299, 297, 296, 294, 293, 291, 289, 288, 287, 285, + 283, 281, 280, 278, 277, 275, 273, 271, 270, 268, 267, 265, 263, 261, 259, 258, 256, 254, 252, 250, + 248, 246, 244, 242, 240, 238, 236, 234, 232, 230, 228, 225, 223, 221, 219, 217, 215, 212, 210, 207, + 204, 202, 200, 197, 195, 192, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 160, 157, 154, 150, + 147, 144, 140, 136, 132, 128, 124, 120, 115, 111, 105, 101, 95, 89, 83, 77, 69, 61, 52, 40, + 23}; + +bool CFrameBuffer::calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, + const bool& tl, const bool& tr, const bool& bl, const bool& br) +{ +/* just a multiplicator for all math to reduce rounding errors */ +#define MUL 32768 + int scl, _ofs = 0; + bool ret = false; + if (ofl != NULL) *ofl = 0; + if (ofr != NULL) *ofr = 0; + int scf = 540 * MUL / radius; + /* one of the top corners */ + if (line < radius && (tl || tr)) { + /* uper round corners */ + scl = scf * (radius - line) / MUL; + if ((scf * (radius - line) % MUL) >= (MUL / 2)) /* round up */ + scl++; + _ofs = radius - (q_circle[scl] * MUL / scf); + if (ofl != NULL && tl) *ofl = _ofs; + if (ofr != NULL && tr) *ofr = _ofs; + } + /* one of the bottom corners */ + else if ((line >= dy - radius) && (bl || br)) { + /* lower round corners */ + scl = scf * (radius - (dy - (line + 1))) / MUL; + if ((scf * (radius - (dy - (line + 1))) % MUL) >= (MUL / 2)) /* round up */ + scl++; + _ofs = radius - (q_circle[scl] * MUL / scf); + if (ofl != NULL && bl) *ofl = _ofs; + if (ofr != NULL && br) *ofr = _ofs; + } + else + ret = true; + if (ofs != NULL) *ofs = _ofs; + return ret; +} + +int CFrameBuffer::limitRadius(const int& dx, const int& dy, const int& radius) +{ + int m = std::min(dx, dy); + if (radius > m) + return m; + if (radius > 540) + return 540; + return radius; +} + +CFrameBuffer::CFrameBuffer() +: active ( true ) +{ + iconBasePath = ""; + available = 0; + cmap.start = 0; + cmap.len = 256; + cmap.red = red; + cmap.green = green; + cmap.blue = blue; + cmap.transp = trans; + backgroundColor = 0; + useBackgroundPaint = false; + background = NULL; + backupBackground = NULL; + backgroundFilename = ""; + fbAreaActiv = false; + fb_no_check = false; + fd = 0; + tty = 0; + bpp = 0; + locked = false; + m_transparent_default = CFrameBuffer::TM_BLACK; // TM_BLACK: Transparency when black content ('pseudo' transparency) + // TM_NONE: No 'pseudo' transparency + // TM_INI: Transparency depends on g_settings.infobar_alpha ??? + m_transparent = m_transparent_default; +//FIXME: test + memset(red, 0, 256*sizeof(__u16)); + memset(green, 0, 256*sizeof(__u16)); + memset(blue, 0, 256*sizeof(__u16)); + memset(trans, 0, 256*sizeof(__u16)); +} + +CFrameBuffer* CFrameBuffer::getInstance() +{ + static CFrameBuffer* frameBuffer = NULL; + + if(!frameBuffer) { + frameBuffer = new CFrameBuffer(); + printf("[neutrino] frameBuffer Instance created\n"); + } else { + //printf("[neutrino] frameBuffer Instace requested\n"); + } + return frameBuffer; +} + +#ifdef USE_NEVIS_GXA +void CFrameBuffer::setupGXA(void) +{ + accel->setupGXA(); +} +#endif + +void CFrameBuffer::init(const char * const) +{ + int tr = 0xFF; + accel = new CFbAccel(this); + cache_size = 0; + + /* Windows Colors */ + paletteSetColor(0x1, 0x010101, tr); + paletteSetColor(0x2, 0x800000, tr); + paletteSetColor(0x3, 0x008000, tr); + paletteSetColor(0x4, 0x808000, tr); + paletteSetColor(0x5, 0x000080, tr); + paletteSetColor(0x6, 0x800080, tr); + paletteSetColor(0x7, 0x008080, tr); + paletteSetColor(0x8, 0xA0A0A0, tr); + paletteSetColor(0x9, 0x505050, tr); + paletteSetColor(0xA, 0xFF0000, tr); + paletteSetColor(0xB, 0x00FF00, tr); + paletteSetColor(0xC, 0xFFFF00, tr); + paletteSetColor(0xD, 0x0000FF, tr); + paletteSetColor(0xE, 0xFF00FF, tr); + paletteSetColor(0xF, 0x00FFFF, tr); + paletteSetColor(0x10, 0xFFFFFF, tr); + paletteSetColor(0x11, 0x000000, tr); + paletteSetColor(COL_BACKGROUND, 0x000000, 0x0); + + paletteSet(); + + useBackground(false); + m_transparent = m_transparent_default; + return; +} + + +CFrameBuffer::~CFrameBuffer() +{ + active = false; /* keep people/infoclocks from accessing */ + std::map::iterator it; + + for(it = icon_cache.begin(); it != icon_cache.end(); ++it) { + /* printf("FB: delete cached icon %s: %x\n", it->first.c_str(), (int) it->second.data); */ + cs_free_uncached(it->second.data); + } + icon_cache.clear(); + + if (background) { + delete[] background; + background = NULL; + } + + if (backupBackground) { + delete[] backupBackground; + backupBackground = NULL; + } + + if (virtual_fb){ + delete[] virtual_fb; + virtual_fb = NULL; + } + delete accel; +} + +int CFrameBuffer::getFileHandle() const +{ + fprintf(stderr, "[fb]::%s: WARNING, this should never be used, please report!\n", __func__); + return fd; +} + +unsigned int CFrameBuffer::getStride() const +{ + return stride; +} + +unsigned int CFrameBuffer::getScreenWidth(bool real) +{ + if(real) + return xRes; + else + return g_settings.screen_EndX - g_settings.screen_StartX; +} + +unsigned int CFrameBuffer::getScreenHeight(bool real) +{ + if(real) + return yRes; + else + return g_settings.screen_EndY - g_settings.screen_StartY; +} + +unsigned int CFrameBuffer::getScreenWidthRel(bool force_small) +{ + int percent = force_small ? WINDOW_SIZE_MIN_FORCED : g_settings.window_width; + // always reduce a possible detailline + return (g_settings.screen_EndX - g_settings.screen_StartX - 2*ConnectLineBox_Width) * percent / 100; +} + +unsigned int CFrameBuffer::getScreenHeightRel(bool force_small) +{ + int percent = force_small ? WINDOW_SIZE_MIN_FORCED : g_settings.window_height; + return (g_settings.screen_EndY - g_settings.screen_StartY) * percent / 100; +} + +unsigned int CFrameBuffer::getScreenX() +{ + return g_settings.screen_StartX; +} + +unsigned int CFrameBuffer::getScreenY() +{ + return g_settings.screen_StartY; +} + +fb_pixel_t * CFrameBuffer::getFrameBufferPointer() const +{ + if (active || (virtual_fb == NULL)) + return accel->lbb; + else + return (fb_pixel_t *)virtual_fb; +} + +fb_pixel_t * CFrameBuffer::getBackBufferPointer() const +{ + return accel->backbuffer; +} + +bool CFrameBuffer::getActive() const +{ + return (active || (virtual_fb != NULL)); +} + +void CFrameBuffer::setActive(bool enable) +{ + active = enable; +} + +t_fb_var_screeninfo *CFrameBuffer::getScreenInfo() +{ + return &screeninfo; +} + +int CFrameBuffer::setMode(unsigned int /*nxRes*/, unsigned int /*nyRes*/, unsigned int /*nbpp*/) +{ +fprintf(stderr, "CFrameBuffer::setMode avail: %d active: %d\n", available, active); + if (!available&&!active) + return -1; + + int ret = accel->setMode(); + xRes = screeninfo.xres; + yRes = screeninfo.yres; + bpp = screeninfo.bits_per_pixel; + printf("FB: %dx%dx%d line length %d. %s accelerator.\n", xRes, yRes, bpp, stride, +#if defined(USE_NEVIS_GXA) + "Using nevis GXA" +#elif defined(BOXMODEL_APOLLO) + "Using fb hw graphics" +#else + "Not using graphics" +#endif + ); + accel->update(); /* just in case we need to update stuff */ + + //memset(getFrameBufferPointer(), 0, stride * yRes); + paintBackground(); + return ret; +} +#if 0 +//never used +void CFrameBuffer::setTransparency( int /*tr*/ ) +{ +} +#endif + +#if !HAVE_TRIPLEDRAGON +void CFrameBuffer::setBlendMode(uint8_t mode) +{ + (void)mode; +#ifdef HAVE_COOL_HARDWARE + if (ioctl(fd, FBIO_SETBLENDMODE, mode)) + printf("FBIO_SETBLENDMODE failed.\n"); +#endif +} + +void CFrameBuffer::setBlendLevel(int level) +{ + (void)level; +#ifdef HAVE_COOL_HARDWARE + //printf("CFrameBuffer::setBlendLevel %d\n", level); + unsigned char value = 0xFF; + if((level >= 0) && (level <= 100)) + value = convertSetupAlpha2Alpha(level); + + if (ioctl(fd, FBIO_SETOPACITY, value)) + printf("FBIO_SETOPACITY failed.\n"); +#if 1 + if(level == 100) // TODO: sucks. + usleep(20000); +#endif +#endif +} +#else +/* TRIPLEDRAGON */ +void CFrameBuffer::setBlendMode(uint8_t mode) +{ + Stb04GFXOsdControl g; + ioctl(gfxfd, STB04GFX_OSD_GETCONTROL, &g); + g.use_global_alpha = (mode == 2); /* 1 == pixel alpha, 2 == global alpha */ + ioctl(gfxfd, STB04GFX_OSD_SETCONTROL, &g); +} + +void CFrameBuffer::setBlendLevel(int level) +{ + /* this is bypassing directfb, but faster and easier */ + Stb04GFXOsdControl g; + ioctl(gfxfd, STB04GFX_OSD_GETCONTROL, &g); + if (g.use_global_alpha == 0) + return; + + if (level < 0 || level > 100) + return; + + /* this is the same as convertSetupAlpha2Alpha(), but non-float */ + g.global_alpha = 255 - (255 * level / 100); + ioctl(gfxfd, STB04GFX_OSD_SETCONTROL, &g); + if (level == 100) // sucks + usleep(20000); +} +#endif + +#if 0 +//never used +void CFrameBuffer::setAlphaFade(int in, int num, int tr) +{ + for (int i=0; i>16)*level; + *g= ((rgb2&0x00FF00)>>8 )*level; + *b= ((rgb2&0x0000FF) )*level; + *r+=((rgb1&0xFF0000)>>16)*(255-level); + *g+=((rgb1&0x00FF00)>>8 )*(255-level); + *b+=((rgb1&0x0000FF) )*(255-level); +} + +void CFrameBuffer::paletteGenFade(int in, __u32 rgb1, __u32 rgb2, int num, int tr) +{ + for (int i=0; i>8; + cmap.green[i] =(rgb&0x00FF00) ; + cmap.blue[i] =(rgb&0x0000FF)<<8; + cmap.transp[i] = tr; +} + +void CFrameBuffer::paletteSet(struct fb_cmap *map) +{ + if (!active) + return; + + if(map == NULL) + map = &cmap; + + if(bpp == 8) { +//printf("Set palette for %dbit\n", bpp); + ioctl(fd, FBIOPUTCMAP, map); + } + uint32_t rl, ro, gl, go, bl, bo, tl, to; + rl = screeninfo.red.length; + ro = screeninfo.red.offset; + gl = screeninfo.green.length; + go = screeninfo.green.offset; + bl = screeninfo.blue.length; + bo = screeninfo.blue.offset; + tl = screeninfo.transp.length; + to = screeninfo.transp.offset; + for (int i = 0; i < 256; i++) { + realcolor[i] = make16color(cmap.red[i], cmap.green[i], cmap.blue[i], cmap.transp[i], + rl, ro, gl, go, bl, bo, tl, to); + } + OnAfterSetPallette(); +} + +void CFrameBuffer::paintHLineRelInternal2Buf(const int& x, const int& dx, const int& y, const int& box_dx, const fb_pixel_t& col, fb_pixel_t* buf) +{ + uint8_t * pos = ((uint8_t *)buf) + x * sizeof(fb_pixel_t) + box_dx * sizeof(fb_pixel_t) * y; + fb_pixel_t * dest = (fb_pixel_t *)pos; + for (int i = 0; i < dx; i++) + *(dest++) = col; +} + +fb_pixel_t* CFrameBuffer::paintBoxRel2Buf(const int dx, const int dy, const int w_align, const int offs_align, const fb_pixel_t col, fb_pixel_t* buf/* = NULL*/, int radius/* = 0*/, int type/* = CORNER_ALL*/) +{ + if (!getActive()) + return buf; + if (dx == 0 || dy == 0) { + dprintf(DEBUG_INFO, "[CFrameBuffer] [%s - %d]: radius %d, dx %d dy %d\n", __func__, __LINE__, radius, dx, dy); + return buf; + } + + fb_pixel_t* pixBuf = buf; + if (pixBuf == NULL) { + pixBuf = (fb_pixel_t*) cs_malloc_uncached(w_align*dy*sizeof(fb_pixel_t)); + if (pixBuf == NULL) { + dprintf(DEBUG_NORMAL, "[%s #%d] Error cs_malloc_uncached\n", __func__, __LINE__); + return NULL; + } + } + memset((void*)pixBuf, '\0', w_align*dy*sizeof(fb_pixel_t)); + + if (type && radius) { + //setCornerFlags(type); + radius = limitRadius(dx, dy, radius); + + bool corner_tl = !!(type & CORNER_TOP_LEFT); + bool corner_tr = !!(type & CORNER_TOP_RIGHT); + bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); + bool corner_br = !!(type & CORNER_BOTTOM_RIGHT); + + int line = 0; + while (line < dy) { + int ofl, ofr; + calcCorners(NULL, &ofl, &ofr, dy, line, radius, + corner_tl, corner_tr, corner_bl, corner_br); + if (dx-ofr-ofl < 1) { + if (dx-ofr-ofl == 0) { + dprintf(DEBUG_INFO, "[%s - %d]: radius %d, end x %d y %d\n", __func__, __LINE__, radius, dx-ofr-ofl, line); + } + else { + dprintf(DEBUG_INFO, "[%s - %04d]: Calculated width: %d\n (radius %d, dx %d, offsetLeft %d, offsetRight %d).\n Width can not be less than 0, abort.\n", + __func__, __LINE__, dx-ofr-ofl, radius, dx, ofl, ofr); + } + line++; + continue; + } + paintHLineRelInternal2Buf(ofl+offs_align, dx-ofl-ofr, line, w_align, col, pixBuf); + line++; + } + } else { + fb_pixel_t *bp = pixBuf; + int line = 0; + while (line < dy) { + for (int pos = offs_align; pos < dx+offs_align; pos++) + *(bp + pos) = col; + bp += w_align; + line++; + } + } + return pixBuf; +} + +fb_pixel_t* CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int dy, + const fb_pixel_t /*col*/, gradientData_t *gradientData, + int radius, int type) +{ + if (!getActive()) + return NULL; + + fb_pixel_t MASK = 0xFFFFFFFF; + int _dx = dx; + int w_align; + int offs_align; + +#ifdef BOXMODEL_APOLLO + if (_dx%4 != 0) { + w_align = GetWidth4FB_HW_ACC(x, _dx, true); + if (w_align < _dx) + _dx = w_align; + offs_align = w_align - _dx; + if ((x - offs_align) < 0) + offs_align = 0; + } + else { + w_align = _dx; + offs_align = 0; + } +#else + w_align = _dx; + offs_align = 0; +#endif + + fb_pixel_t* boxBuf = paintBoxRel2Buf(_dx, dy, w_align, offs_align, MASK, NULL, radius, type); + if (boxBuf == NULL) + return NULL; + fb_pixel_t *bp = boxBuf; + fb_pixel_t *gra = gradientData->gradientBuf; + gradientData->boxBuf = boxBuf; + gradientData->x = x - offs_align; + gradientData->dx = w_align; + + if (gradientData->direction == gradientVertical) { + // vertical + for (int pos = offs_align; pos < _dx+offs_align; pos++) { + for(int count = 0; count < dy; count++) { + if (*(bp + pos) == MASK) + *(bp + pos) = (fb_pixel_t)(*(gra + count)); + bp += w_align; + } + bp = boxBuf; + } + } else { + // horizontal + for (int line = 0; line < dy; line++) { + int gra_pos = 0; + for (int pos = 0; pos < w_align; pos++) { + if ((*(bp + pos) == MASK) && (pos >= offs_align) && (gra_pos < _dx)) { + *(bp + pos) = (fb_pixel_t)(*(gra + gra_pos)); + gra_pos++; + } + } + bp += w_align; + } + } + + if ((gradientData->mode & pbrg_noPaint) == pbrg_noPaint) + return boxBuf; + + blitBox2FB(boxBuf, w_align, dy, x-offs_align, y); + + if ((gradientData->mode & pbrg_noFree) == pbrg_noFree) + return boxBuf; + + cs_free_uncached(boxBuf); + + return NULL; +} + +void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius, int type) +{ + /* draw a filled rectangle (with additional round corners) */ + if (!getActive()) + return; + +#if HAVE_COOL_HARDWARE + checkFbArea(x, y, dx, dy, true); + accel->paintBoxRel(x, y, dx, dy, col, radius, type); + checkFbArea(x, y, dx, dy, false); +#else + + bool corner_tl = !!(type & CORNER_TOP_LEFT); + bool corner_tr = !!(type & CORNER_TOP_RIGHT); + bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); + bool corner_br = !!(type & CORNER_BOTTOM_RIGHT); + + checkFbArea(x, y, dx, dy, true); + + if (!type || !radius) + { + accel->paintRect(x, y, dx, dy, col); + checkFbArea(x, y, dx, dy, false); + return; + } + + /* limit the radius */ + radius = limitRadius(dx, dy, radius); + if (radius < 1) /* dx or dy = 0... */ + radius = 1; /* avoid div by zero below */ + + int line = 0; + while (line < dy) { + int ofl, ofr; + if (calcCorners(NULL, &ofl, &ofr, dy, line, radius, + corner_tl, corner_tr, corner_bl, corner_br)) + { + int height = dy - ((corner_tl || corner_tr)?radius: 0 ) - ((corner_bl || corner_br) ? radius : 0); + accel->paintRect(x, y + line, dx, height, col); + line += height; + continue; + } + if (dx - ofr - ofl < 1) { + //printf("FB-NG::%s:%d x %d y %d dx %d dy %d l %d r %d\n", __func__, __LINE__, x,y,dx,dy, ofl, ofr); + line++; + continue; + } + accel->paintLine(x + ofl, y + line, x + dx - ofr, y + line, col); + line++; + } + checkFbArea(x, y, dx, dy, false); + accel->mark(x, y, x+dx, y+dy); +#endif +} + +void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) +{ + if (!getActive()) + return; + if (x > (int)xRes || y > (int)yRes || x < 0 || y < 0) + return; + + accel->paintPixel(x, y, col); +} + +void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) +{ + if (!getActive()) + return; + + accel->paintLine(xa, ya, xb, yb, col); +} + +void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col) +{ +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintVLineRelInternal(x, ya, yb-ya, col); +#else + paintLine(x, ya, x, yb, col); +#endif +} + +void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col) +{ +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintVLineRelInternal(x, y, dy, col); +#else + paintLine(x, y, x, y + dy, col); +#endif +} + +void CFrameBuffer::paintHLine(int xa, int xb, int y, const fb_pixel_t col) +{ +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintHLineRelInternal(xa, xb-xa, y, col); +#else + paintLine(xa, y, xb, y, col); +#endif +} + +void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col) +{ +#if HAVE_COOL_HARDWARE +#if defined(USE_NEVIS_GXA) + OpenThreads::ScopedLock m_lock(mutex); +#endif + paintHLineRelInternal(x, dx, y, col); +#else + paintLine(x, y, x + dx, y, col); +#endif +} + +void CFrameBuffer::setIconBasePath(const std::string & iconPath) +{ + iconBasePath = iconPath; + if (!iconBasePath.empty() && '/' == *iconBasePath.rbegin()) /* .back() is only c++11 :-( */ + return; + iconBasePath += "/"; +} + +std::string CFrameBuffer::getIconPath(std::string icon_name, std::string file_type) +{ + std::string path, filetype; + filetype = "." + file_type; + path = std::string(ICONSDIR_VAR) + "/" + icon_name + filetype; + if (access(path.c_str(), F_OK)) + path = iconBasePath + "/" + icon_name + filetype; + if (icon_name.find("/", 0) != std::string::npos) + path = icon_name; + return path; +} + +void CFrameBuffer::getIconSize(const char * const filename, int* width, int *height) +{ + *width = 0; + *height = 0; + + if(filename == NULL) + return; + + std::map::iterator it; + + /* if code ask for size, lets cache it. assume we have enough ram for cache */ + /* FIXME offset seems never used in code, always default = 1 ? */ + + it = icon_cache.find(filename); + if(it == icon_cache.end()) { + if(paintIcon(filename, 0, 0, 0, 1, false)) { + it = icon_cache.find(filename); + } + } + if(it != icon_cache.end()) { + *width = it->second.width; + *height = it->second.height; + } +} + +bool CFrameBuffer::paintIcon8(const std::string & filename, const int x, const int y, const unsigned char offset) +{ + if (!getActive()) + return false; + +//printf("%s(file, %d, %d, %d)\n", __FUNCTION__, x, y, offset); + + struct rawHeader header; + uint16_t width, height; + int lfd; + + lfd = open((iconBasePath + filename).c_str(), O_RDONLY); + + if (lfd == -1) { + printf("paintIcon8: error while loading icon: %s%s\n", iconBasePath.c_str(), filename.c_str()); + return false; + } + + read(lfd, &header, sizeof(struct rawHeader)); + + width = (header.width_hi << 8) | header.width_lo; + height = (header.height_hi << 8) | header.height_lo; + + unsigned char pixbuf[768]; + + uint8_t * d = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + fb_pixel_t * d2; + for (int count=0; countmark(x, y, x + width, y + height); + return true; +} + +/* paint icon at position x/y, + if height h is given, center vertically between y and y+h + offset is a color offset (probably only useful with palette) */ +bool CFrameBuffer::paintIcon(const std::string & filename, const int x, const int y, + const int h, const unsigned char offset, bool paint, bool paintBg, const fb_pixel_t colBg) +{ + struct rawHeader header; + int width, height; + fb_pixel_t * data; + struct rawIcon tmpIcon; + std::map::iterator it; + + if (!getActive()) + return false; + + int yy = y; + //printf("CFrameBuffer::paintIcon: load %s\n", filename.c_str());fflush(stdout); + + /* we cache and check original name */ + it = icon_cache.find(filename); + if(it == icon_cache.end()) { + std::string newname = getIconPath(filename); + //printf("CFrameBuffer::paintIcon: check for %s\n", newname.c_str());fflush(stdout); + + data = g_PicViewer->getIcon(newname, &width, &height); + + if(data) { //TODO: intercepting of possible full icon cache, that could cause strange behavior while painting of uncached icons + int dsize = width*height*sizeof(fb_pixel_t); + //printf("CFrameBuffer::paintIcon: %s found, data %x size %d x %d\n", newname.c_str(), data, width, height);fflush(stdout); + if(cache_size+dsize < ICON_CACHE_SIZE) { + cache_size += dsize; + tmpIcon.width = width; + tmpIcon.height = height; + tmpIcon.data = data; + icon_cache.insert(std::pair (filename, tmpIcon)); + //printf("Cached %s, cache size %d\n", newname.c_str(), cache_size); + } + goto _display; + } + + newname = getIconPath(filename, "raw"); + + int lfd = open(newname.c_str(), O_RDONLY); + + if (lfd == -1) { + //printf("paintIcon: error while loading icon: %s\n", newname.c_str()); + return false; + } + + ssize_t s = read(lfd, &header, sizeof(struct rawHeader)); + if (s < 0) { + perror("read"); + return false; + } + + if (s < (ssize_t) sizeof(rawHeader)){ + printf("paintIcon: error while loading icon: %s, header too small\n", newname.c_str()); + return false; + } + + + tmpIcon.width = width = (header.width_hi << 8) | header.width_lo; + tmpIcon.height = height = (header.height_hi << 8) | header.height_lo; + if (!width || !height) { + printf("paintIcon: error while loading icon: %s, wrong dimensions (%dHx%dW)\n", newname.c_str(), height, width); + return false; + } + + int dsize = width*height*sizeof(fb_pixel_t); + + tmpIcon.data = (fb_pixel_t*) cs_malloc_uncached(dsize); + data = tmpIcon.data; + + unsigned char pixbuf[768]; + for (int count = 0; count < height; count ++ ) { + read(lfd, &pixbuf[0], width >> 1 ); + unsigned char *pixpos = &pixbuf[0]; + for (int count2 = 0; count2 < width >> 1; count2 ++ ) { + unsigned char compressed = *pixpos; + unsigned char pix1 = (compressed & 0xf0) >> 4; + unsigned char pix2 = (compressed & 0x0f); + if (pix1 != header.transp) + *data++ = realcolor[pix1+offset]; + else + *data++ = 0; + if (pix2 != header.transp) + *data++ = realcolor[pix2+offset]; + else + *data++ = 0; + pixpos++; + } + } + close(lfd); + + data = tmpIcon.data; + + if(cache_size+dsize < ICON_CACHE_SIZE) { + cache_size += dsize; + icon_cache.insert(std::pair (filename, tmpIcon)); + //printf("Cached %s, cache size %d\n", newname.c_str(), cache_size); + } + } else { + data = it->second.data; + width = it->second.width; + height = it->second.height; + //printf("paintIcon: already cached %s %d x %d\n", newname.c_str(), width, height); + } +_display: + if(!paint) + return true; + + if (h != 0) + yy += (h - height) / 2; + + checkFbArea(x, yy, width, height, true); + if (paintBg) + paintBoxRel(x, yy, width, height, colBg); + blit2FB(data, width, height, x, yy, 0, 0, true); + checkFbArea(x, yy, width, height, false); + return true; +} + +void CFrameBuffer::loadPal(const std::string & filename, const unsigned char offset, const unsigned char endidx) +{ + if (!getActive()) + return; + +//printf("%s()\n", __FUNCTION__); + + struct rgbData rgbdata; + int lfd; + + lfd = open((iconBasePath + filename).c_str(), O_RDONLY); + + if (lfd == -1) { + printf("error while loading palette: %s%s\n", iconBasePath.c_str(), filename.c_str()); + return; + } + + int pos = 0; + int readb = read(lfd, &rgbdata, sizeof(rgbdata) ); + while(readb) { + __u32 rgb = (rgbdata.r<<16) | (rgbdata.g<<8) | (rgbdata.b); + int colpos = offset+pos; + if( colpos>endidx) + break; + + paletteSetColor(colpos, rgb, 0xFF); + readb = read(lfd, &rgbdata, sizeof(rgbdata) ); + pos++; + } + paletteSet(&cmap); + close(lfd); +} + + +void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const int dy, const int px, const fb_pixel_t col, const int rad, int type) +{ + if (!getActive()) + return; + + int radius = rad; + bool corner_tl = !!(type & CORNER_TOP_LEFT); + bool corner_tr = !!(type & CORNER_TOP_RIGHT); + bool corner_bl = !!(type & CORNER_BOTTOM_LEFT); + bool corner_br = !!(type & CORNER_BOTTOM_RIGHT); + + int r_tl = 0, r_tr = 0, r_bl = 0, r_br = 0; + if (type && radius) { + int x_rad = radius - 1; + if (corner_tl) r_tl = x_rad; + if (corner_tr) r_tr = x_rad; + if (corner_bl) r_bl = x_rad; + if (corner_br) r_br = x_rad; + } + paintBoxRel(sx + r_tl, sy , dx - r_tl - r_tr, px, col); // top horizontal + paintBoxRel(sx + r_bl, sy + dy - px, dx - r_bl - r_br, px, col); // bottom horizontal + paintBoxRel(sx , sy + r_tl, px, dy - r_tl - r_bl, col); // left vertical + paintBoxRel(sx + dx - px, sy + r_tr, px, dy - r_tr - r_br, col); // right vertical + + if (!radius || !type) + return; + + radius = limitRadius(dx, dy, radius); + if (radius < 1) /* dx or dy = 0... */ + radius = 1; /* avoid div by zero below */ + int line = 0; + while (line < dy) { + int ofs = 0, ofs_i = 0; + // inner box + if ((line >= px) && (line < (dy - px))) + calcCorners(&ofs_i, NULL, NULL, dy - 2 * px, line - px, radius - px, + corner_tl, corner_tr, corner_bl, corner_br); + // outer box + calcCorners(&ofs, NULL, NULL, dy, line, radius, corner_tl, corner_tr, corner_bl, corner_br); + + int _y = sy + line; + if (line < px || line >= (dy - px)) { + // left + if ((corner_tl && line < radius) || (corner_bl && line >= dy - radius)) + accel->paintLine(sx + ofs, _y, sx + ofs + radius, _y, col); + // right + if ((corner_tr && line < radius) || (corner_br && line >= dy - radius)) + accel->paintLine(sx + dx - radius, _y, sx + dx - ofs, _y, col); + } + else if (line < (dy - px)) { + int _dx = (ofs_i - ofs) + px; + // left + if ((corner_tl && line < radius) || (corner_bl && line >= dy - radius)) + accel->paintLine(sx + ofs, _y, sx + ofs + _dx, _y, col); + // right + if ((corner_tr && line < radius) || (corner_br && line >= dy - radius)) + accel->paintLine(sx + dx - ofs_i - px, _y, sx + dx - ofs_i - px + _dx, _y, col); + } + if (line == radius && dy > 2 * radius) + // line outside the rounded corners + line = dy - radius; + else + line++; + } +} + +void CFrameBuffer::useBackground(bool ub) +{ + useBackgroundPaint = ub; + if(!useBackgroundPaint) { + delete[] background; + background=0; + } +} + +bool CFrameBuffer::getuseBackground(void) +{ + return useBackgroundPaint; +} + +void CFrameBuffer::saveBackgroundImage(void) +{ + if (backupBackground != NULL){ + delete[] backupBackground; + backupBackground = NULL; + } + backupBackground = background; + //useBackground(false); // <- necessary since no background is available + useBackgroundPaint = false; + background = NULL; +} + +void CFrameBuffer::restoreBackgroundImage(void) +{ + fb_pixel_t * tmp = background; + + if (backupBackground != NULL) + { + background = backupBackground; + backupBackground = NULL; + } + else + useBackground(false); // <- necessary since no background is available + + if (tmp != NULL){ + delete[] tmp; + tmp = NULL; + } +} + +void CFrameBuffer::paintBackgroundBoxRel(int x, int y, int dx, int dy) +{ + if (!getActive()) + return; + + if(!useBackgroundPaint) + { + /* paintBoxRel does its own checkFbArea() */ + paintBoxRel(x, y, dx, dy, backgroundColor); + } + else + { + checkFbArea(x, y, dx, dy, true); + uint8_t * fbpos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + fb_pixel_t * bkpos = background + x + BACKGROUNDIMAGEWIDTH * y; + for(int count = 0;count < dy; count++) + { + memmove(fbpos, bkpos, dx * sizeof(fb_pixel_t)); + fbpos += stride; + bkpos += BACKGROUNDIMAGEWIDTH; + } + checkFbArea(x, y, dx, dy, false); + accel->mark(x, y, x + dx, y + dy); + } +} + +void CFrameBuffer::paintBackground() +{ + if (!getActive()) + return; + + if (useBackgroundPaint && (background != NULL)) + { + checkFbArea(0, 0, xRes, yRes, true); + /* this does not really work anyway... */ + for (int i = 0; i < 576; i++) + memmove(((uint8_t *)getFrameBufferPointer()) + i * stride, (background + i * BACKGROUNDIMAGEWIDTH), BACKGROUNDIMAGEWIDTH * sizeof(fb_pixel_t)); + checkFbArea(0, 0, xRes, yRes, false); + accel->mark(0, 0, xRes, yRes); + } + else + { + paintBoxRel(0, 0, xRes, yRes, backgroundColor); + } +} + +void CFrameBuffer::SaveScreen(int x, int y, int dx, int dy, fb_pixel_t * const memp) +{ + if (!getActive() || memp == NULL) + return; + + checkFbArea(x, y, dx, dy, true); + uint8_t * pos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + fb_pixel_t * bkpos = memp; + for (int count = 0; count < dy; count++) { + fb_pixel_t * dest = (fb_pixel_t *)pos; + for (int i = 0; i < dx; i++) + *(bkpos++) = *(dest++); + pos += stride; + } +#if 0 + /* todo: check what the problem with this is, it should be better -- probably caching issue */ + uint8_t * fbpos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + fb_pixel_t * bkpos = memp; + for (int count = 0; count < dy; count++) + { + memmove(bkpos, fbpos, dx * sizeof(fb_pixel_t)); + fbpos += stride; + bkpos += dx; + } +#endif + checkFbArea(x, y, dx, dy, false); +} + +void CFrameBuffer::RestoreScreen(int x, int y, int dx, int dy, fb_pixel_t * const memp) +{ + if (!getActive() || memp == NULL) + return; + + checkFbArea(x, y, dx, dy, true); + uint8_t * fbpos = ((uint8_t *)getFrameBufferPointer()) + x * sizeof(fb_pixel_t) + stride * y; + fb_pixel_t * bkpos = memp; + for (int count = 0; count < dy; count++) + { + memmove(fbpos, bkpos, dx * sizeof(fb_pixel_t)); + fbpos += stride; + bkpos += dx; + } + accel->mark(x, y, x + dx, y + dy); + checkFbArea(x, y, dx, dy, false); +} + +void CFrameBuffer::Clear() +{ + paintBackground(); + //memset(getFrameBufferPointer(), 0, stride * yRes); +} + +bool CFrameBuffer::Lock() +{ + if(locked) + return false; + locked = true; + return true; +} + +void CFrameBuffer::Unlock() +{ + locked = false; +} + +void * CFrameBuffer::int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp, bool alpha) +{ + unsigned long i; + unsigned int *fbbuff; + unsigned long count = x * y; + + fbbuff = (unsigned int *) cs_malloc_uncached(count * sizeof(unsigned int)); + if(fbbuff == NULL) { + printf("convertRGB2FB%s: Error: cs_malloc_uncached\n", ((alpha) ? " (Alpha)" : "")); + return NULL; + } + + if (alpha) { + for(i = 0; i < count ; i++) + fbbuff[i] = ((rgbbuff[i*4+3] << 24) & 0xFF000000) | + ((rgbbuff[i*4] << 16) & 0x00FF0000) | + ((rgbbuff[i*4+1] << 8) & 0x0000FF00) | + ((rgbbuff[i*4+2]) & 0x000000FF); + } else { + switch (m_transparent) { + case CFrameBuffer::TM_BLACK: + for(i = 0; i < count ; i++) { + transp = 0; + if(rgbbuff[i*3] || rgbbuff[i*3+1] || rgbbuff[i*3+2]) + transp = 0xFF; + fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF); + } + break; + case CFrameBuffer::TM_INI: + for(i = 0; i < count ; i++) + fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF); + break; + case CFrameBuffer::TM_NONE: + default: + for(i = 0; i < count ; i++) + fbbuff[i] = 0xFF000000 | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF); + break; + } + } + return (void *) fbbuff; +} + +void * CFrameBuffer::convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp) +{ + return int_convertRGB2FB(rgbbuff, x, y, transp, false); +} + +void * CFrameBuffer::convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y) +{ + return int_convertRGB2FB(rgbbuff, x, y, 0, true); +} + +void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) +{ + checkFbArea(xoff, yoff, width, height, true); + accel->blit2FB(fbbuff, width, height, xoff, yoff, xp, yp, transp); + checkFbArea(xoff, yoff, width, height, false); +} + +void CFrameBuffer::blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff) +{ + checkFbArea(xoff, yoff, width, height, true); +#if HAVE_COOL_HARDWARE + accel->blitBox2FB(boxBuf, width, height, xoff, yoff); +#else + uint32_t swidth = stride / sizeof(fb_pixel_t); + fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * yoff); + fb_pixel_t* data = (fb_pixel_t*)boxBuf; + + uint32_t line = 0; + while (line < height) { + fb_pixel_t *pixpos = &data[line * width]; + for (uint32_t pos = xoff; pos < xoff + width; pos++) { + //don't paint backgroundcolor (*pixpos = 0x00000000) + if (*pixpos) + *(fbp + pos) = *pixpos; + pixpos++; + } + fbp += swidth; + line++; + } + accel->mark(xoff, yoff, xoff + width, yoff + height); +#endif + checkFbArea(xoff, yoff, width, height, false); +} + +void CFrameBuffer::displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb, int transp) +{ + void *fbbuff = NULL; + + if(rgbbuff == NULL) + return; + + /* correct panning */ + if(x_pan > x_size - (int)xRes) x_pan = 0; + if(y_pan > y_size - (int)yRes) y_pan = 0; + + /* correct offset */ + if(x_offs + x_size > (int)xRes) x_offs = 0; + if(y_offs + y_size > (int)yRes) y_offs = 0; + + /* blit buffer 2 fb */ + fbbuff = convertRGB2FB(rgbbuff, x_size, y_size, transp); + if(fbbuff==NULL) + return; + + /* ClearFB if image is smaller */ + /* if(x_size < (int)xRes || y_size < (int)yRes) */ + if(clearfb) + CFrameBuffer::getInstance()->Clear(); + + blit2FB(fbbuff, x_size, y_size, x_offs, y_offs, x_pan, y_pan); + cs_free_uncached(fbbuff); +} + +void CFrameBuffer::setFbArea(int element, int _x, int _y, int _dx, int _dy) +{ + if (_x == 0 && _y == 0 && _dx == 0 && _dy == 0) { + // delete area + for (fbarea_iterator_t it = v_fbarea.begin(); it != v_fbarea.end(); ++it) { + if (it->element == element) { + v_fbarea.erase(it); + break; + } + } + if (v_fbarea.empty()) { + fbAreaActiv = false; + } + } + else { + // change area + bool found = false; + for (unsigned int i = 0; i < v_fbarea.size(); i++) { + if (v_fbarea[i].element == element) { + v_fbarea[i].x = _x; + v_fbarea[i].y = _y; + v_fbarea[i].dx = _dx; + v_fbarea[i].dy = _dy; + found = true; + break; + } + } + // set new area + if (!found) { + fb_area_t area; + area.x = _x; + area.y = _y; + area.dx = _dx; + area.dy = _dy; + area.element = element; + v_fbarea.push_back(area); + } + fbAreaActiv = true; + } +} + +int CFrameBuffer::checkFbAreaElement(int _x, int _y, int _dx, int _dy, fb_area_t *area) +{ + if (fb_no_check) + return FB_PAINTAREA_MATCH_NO; + + if (_y > area->y + area->dy) + return FB_PAINTAREA_MATCH_NO; + if (_x + _dx < area->x) + return FB_PAINTAREA_MATCH_NO; + if (_x > area->x + area->dx) + return FB_PAINTAREA_MATCH_NO; + if (_y + _dy < area->y) + return FB_PAINTAREA_MATCH_NO; + return FB_PAINTAREA_MATCH_OK; +} + +bool CFrameBuffer::_checkFbArea(int _x, int _y, int _dx, int _dy, bool prev) +{ + if (v_fbarea.empty()) + return true; + + for (unsigned int i = 0; i < v_fbarea.size(); i++) { + int ret = checkFbAreaElement(_x, _y, _dx, _dy, &v_fbarea[i]); + if (ret == FB_PAINTAREA_MATCH_OK) { + switch (v_fbarea[i].element) { + case FB_PAINTAREA_MUTEICON1: + if (!do_paint_mute_icon) + break; + fb_no_check = true; + if (prev) + CAudioMute::getInstance()->hide(); + else + CAudioMute::getInstance()->paint(); + fb_no_check = false; + break; + default: + break; + } + } + } + + return true; +} + +/* TODO: can we get rid of that? */ +void CFrameBuffer::mark(int x, int y, int dx, int dy) +{ + accel->mark(x, y, dx, dy); +}; + +/* argh. really not the right thing to do here... */ +extern cVideo *videoDecoder; +void CFrameBuffer::showFrame(const std::string & filename) +{ + std::string picture = ICONSDIR_VAR + filename; + if (access(picture.c_str(), F_OK)) + picture = iconBasePath + filename; + if (filename.find("/", 0) != std::string::npos) + picture = filename; + + videoDecoder->ShowPicture(picture.c_str()); +} + +void CFrameBuffer::stopFrame() +{ + videoDecoder->StopPicture(); +} + +#if HAVE_COOL_HARDWARE +void CFrameBuffer::paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col) +{ + accel->paintVLineRelInternal(x, y, dy, col); +} + +void CFrameBuffer::paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col) +{ + accel->paintHLineRelInternal(x, dx, y, col); +} +#endif diff --git a/src/driver/framebuffer_ng.h b/src/driver/framebuffer_ng.h new file mode 100644 index 000000000..2c796f574 --- /dev/null +++ b/src/driver/framebuffer_ng.h @@ -0,0 +1,330 @@ +/* + Neutrino-GUI - DBoxII-Project + + Copyright (C) 2001 Steffen Hehn 'McClean' + Homepage: http://dbox.cyberphoria.org/ + + Copyright (C) 2007-2015 Stefan Seyfried + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef __framebuffer_ng__ +#define __framebuffer_ng__ +#include + +#include +#include +#include + +#include +#include +#include +#include + +#define fb_pixel_t uint32_t + +typedef struct fb_var_screeninfo t_fb_var_screeninfo; + +typedef struct gradientData_t +{ + fb_pixel_t* gradientBuf; + fb_pixel_t* boxBuf; + bool direction; + int mode; + int x; + int dx; +} gradientData_struct_t; + +#define CORNER_NONE 0x0 +#define CORNER_TOP_LEFT 0x1 +#define CORNER_TOP_RIGHT 0x2 +#define CORNER_TOP 0x3 +#define CORNER_BOTTOM_RIGHT 0x4 +#define CORNER_RIGHT 0x6 +#define CORNER_BOTTOM_LEFT 0x8 +#define CORNER_LEFT 0x9 +#define CORNER_BOTTOM 0xC +#define CORNER_ALL 0xF + +#define FADE_TIME 10000 +#define FADE_STEP 5 +#define FADE_RESET 0xFFFF + +#define WINDOW_SIZE_MAX 100 // % +#define WINDOW_SIZE_MIN 50 // % +#define WINDOW_SIZE_MIN_FORCED 80 // % +#define ConnectLineBox_Width 16 // px + +#if HAVE_GENERIC_HARDWARE +#define USE_OPENGL 1 +#endif + +class CFbAccel; +/** Ausfuehrung als Singleton */ +class CFrameBuffer : public sigc::trackable +{ + friend class CFbAccel; + private: + CFrameBuffer(); + + struct rgbData + { + uint8_t r; + uint8_t g; + uint8_t b; + } __attribute__ ((packed)); + + struct rawHeader + { + uint8_t width_lo; + uint8_t width_hi; + uint8_t height_lo; + uint8_t height_hi; + uint8_t transp; + } __attribute__ ((packed)); + + struct rawIcon + { + uint16_t width; + uint16_t height; + uint8_t transp; + fb_pixel_t * data; + }; + + std::string iconBasePath; + + int fd, tty; + fb_pixel_t * lfb; + int available; + fb_pixel_t * background; + fb_pixel_t * backupBackground; + fb_pixel_t backgroundColor; + std::string backgroundFilename; + bool useBackgroundPaint; + unsigned int xRes, yRes, stride, bpp; + t_fb_var_screeninfo screeninfo, oldscreen; + fb_cmap cmap; + __u16 red[256], green[256], blue[256], trans[256]; + + void paletteFade(int i, __u32 rgb1, __u32 rgb2, int level); + + int kd_mode; + struct vt_mode vt_mode; + bool active; + static void switch_signal (int); + fb_fix_screeninfo fix; + bool locked; + std::map icon_cache; + int cache_size; + void * int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp, bool alpha); + int m_transparent_default, m_transparent; + CFbAccel *accel; + + inline void paintHLineRelInternal2Buf(const int& x, const int& dx, const int& y, const int& box_dx, const fb_pixel_t& col, fb_pixel_t* buf); + void paintShortHLineRelInternal(const int& x, const int& dx, const int& y, const fb_pixel_t& col); +#if 0 + int limitRadius(const int& dx, const int& dy, int& radius); + void setCornerFlags(const int& type); +#endif + public: + fb_pixel_t realcolor[256]; + + ~CFrameBuffer(); + + static CFrameBuffer* getInstance(); +#ifdef USE_NEVIS_GXA + void setupGXA(void); +#endif + + void init(const char * const fbDevice = "/dev/fb0"); + int setMode(unsigned int xRes, unsigned int yRes, unsigned int bpp); + + enum { + gradientHorizontal, + gradientVertical + }; + + enum { + pbrg_noOption = 0x00, + pbrg_noPaint = 0x01, + pbrg_noFree = 0x02 + }; + + int getFileHandle() const; //only used for plugins (games) !! + t_fb_var_screeninfo *getScreenInfo(); + + fb_pixel_t * getFrameBufferPointer() const; // pointer to framebuffer + fb_pixel_t * getBackBufferPointer() const; // pointer to backbuffer + unsigned int getStride() const; // size of a single line in the framebuffer (in bytes) + unsigned int getScreenWidth(bool real = false); + unsigned int getScreenHeight(bool real = false); + unsigned int getScreenWidthRel(bool force_small = false); + unsigned int getScreenHeightRel(bool force_small = false); + unsigned int getScreenX(); + unsigned int getScreenY(); + + bool getActive() const; // is framebuffer active? + void setActive(bool enable); // is framebuffer active? + + void setTransparency( int tr = 0 ); + void setBlendMode(uint8_t mode = 1); + void setBlendLevel(int level); + + //Palette stuff + void setAlphaFade(int in, int num, int tr); + void paletteGenFade(int in, __u32 rgb1, __u32 rgb2, int num, int tr=0); + void paletteSetColor(int i, __u32 rgb, int tr); + void paletteSet(struct fb_cmap *map = NULL); + + //paint functions + inline void paintPixel(fb_pixel_t * const dest, const uint8_t color) const + { + *dest = realcolor[color]; + }; + void paintPixel(int x, int y, const fb_pixel_t col); + + fb_pixel_t* paintBoxRel2Buf(const int dx, const int dy, const int w_align, const int offs_align, const fb_pixel_t col, fb_pixel_t* buf = NULL, int radius = 0, int type = CORNER_ALL); + fb_pixel_t* paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, gradientData_t *gradientData, int radius = 0, int type = CORNER_ALL); + + void paintBoxRel(const int x, const int y, const int dx, const int dy, const fb_pixel_t col, int radius = 0, int type = CORNER_ALL); + inline void paintBox(int xa, int ya, int xb, int yb, const fb_pixel_t col) { paintBoxRel(xa, ya, xb - xa, yb - ya, col); } + inline void paintBox(int xa, int ya, int xb, int yb, const fb_pixel_t col, int radius, int type) { paintBoxRel(xa, ya, xb - xa, yb - ya, col, radius, type); } + + void paintBoxFrame(const int x, const int y, const int dx, const int dy, const int px, const fb_pixel_t col, const int rad = 0, int type = CORNER_ALL); + void paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col); + + void paintVLine(int x, int ya, int yb, const fb_pixel_t col); + void paintVLineRel(int x, int y, int dy, const fb_pixel_t col); + + void paintHLine(int xa, int xb, int y, const fb_pixel_t col); + void paintHLineRel(int x, int dx, int y, const fb_pixel_t col); + + + void setIconBasePath(const std::string & iconPath); + std::string getIconBasePath(){return iconBasePath;}; + std::string getIconPath(std::string icon_name, std::string file_type = "png"); + + void getIconSize(const char * const filename, int* width, int *height); + /* h is the height of the target "window", if != 0 the icon gets centered in that window */ + bool paintIcon (const std::string & filename, const int x, const int y, + const int h = 0, const unsigned char offset = 1, bool paint = true, bool paintBg = false, const fb_pixel_t colBg = 0); + bool paintIcon8(const std::string & filename, const int x, const int y, const unsigned char offset = 0); + void loadPal (const std::string & filename, const unsigned char offset = 0, const unsigned char endidx = 255); + + bool loadPicture2Mem (const std::string & filename, fb_pixel_t * const memp); + bool loadPicture2FrameBuffer(const std::string & filename); + bool loadPictureToMem (const std::string & filename, const uint16_t width, const uint16_t height, const uint16_t stride, fb_pixel_t * const memp); + bool savePictureFromMem (const std::string & filename, const fb_pixel_t * const memp); + + int getBackgroundColor() { return backgroundColor;} + void setBackgroundColor(const fb_pixel_t color); + bool loadBackground(const std::string & filename, const unsigned char col = 0); + void useBackground(bool); + bool getuseBackground(void); + + void saveBackgroundImage(void); // <- implies useBackground(false); + void restoreBackgroundImage(void); + + void paintBackgroundBoxRel(int x, int y, int dx, int dy); + inline void paintBackgroundBox(int xa, int ya, int xb, int yb) { paintBackgroundBoxRel(xa, ya, xb - xa, yb - ya); } + + void paintBackground(); + + void SaveScreen(int x, int y, int dx, int dy, fb_pixel_t * const memp); + void RestoreScreen(int x, int y, int dx, int dy, fb_pixel_t * const memp); + + void Clear(); + void showFrame(const std::string & filename); + void stopFrame(); + bool loadBackgroundPic(const std::string & filename, bool show = true); + bool Lock(void); + void Unlock(void); + bool Locked(void) { return locked; }; + void waitForIdle(const char *func = NULL); + void* convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp = 0xFF); + void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y); + void displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb = true, int transp = 0xFF); + void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false); + void blitBox2FB(const fb_pixel_t* boxBuf, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff); + + void mark(int x, int y, int dx, int dy); + + enum + { + TM_EMPTY = 0, + TM_NONE = 1, + TM_BLACK = 2, + TM_INI = 3 + }; + void SetTransparent(int t){ m_transparent = t; } + void SetTransparentDefault(){ m_transparent = m_transparent_default; } + +// ## AudioMute / Clock ###################################### + private: + enum { + FB_PAINTAREA_MATCH_NO, + FB_PAINTAREA_MATCH_OK + }; + + typedef struct fb_area_t + { + int x; + int y; + int dx; + int dy; + int element; + } fb_area_struct_t; + + bool fbAreaActiv; + typedef std::vector v_fbarea_t; + typedef v_fbarea_t::iterator fbarea_iterator_t; + v_fbarea_t v_fbarea; + bool fb_no_check; + bool do_paint_mute_icon; + + bool _checkFbArea(int _x, int _y, int _dx, int _dy, bool prev); + int checkFbAreaElement(int _x, int _y, int _dx, int _dy, fb_area_t *area); + + public: + enum { + FB_PAINTAREA_INFOCLOCK, + FB_PAINTAREA_MUTEICON1, + FB_PAINTAREA_MUTEICON2, + + FB_PAINTAREA_MAX + }; + + inline bool checkFbArea(int _x, int _y, int _dx, int _dy, bool prev) { return (fbAreaActiv && !fb_no_check) ? _checkFbArea(_x, _y, _dx, _dy, prev) : true; } + + void setFbArea(int element, int _x=0, int _y=0, int _dx=0, int _dy=0); + void fbNoCheck(bool noCheck) { fb_no_check = noCheck; } + void doPaintMuteIcon(bool mode) { do_paint_mute_icon = mode; } + /* blit() is unnecessary, but here to avoid patches to the neutrino code */ + void blit(void) {} + bool calcCorners(int *ofs, int *ofl, int *ofr, const int& dy, const int& line, const int& radius, + const bool& tl, const bool& tr, const bool& bl, const bool& br); + int limitRadius(const int& dx, const int& dy, const int& radius); + +#if HAVE_COOL_HARDWARE + void paintVLineRelInternal(int x, int y, int dy, const fb_pixel_t col); + void paintHLineRelInternal(int x, int dx, int y, const fb_pixel_t col); +#endif + sigc::signal OnAfterSetPallette; +}; + +#endif diff --git a/src/driver/lcdd.cpp b/src/driver/lcdd.cpp index 74193ed4b..1b28ec365 100644 --- a/src/driver/lcdd.cpp +++ b/src/driver/lcdd.cpp @@ -5,7 +5,7 @@ Homepage: http://dbox.cyberphoria.org/ Copyright (C) 2008 Novell, Inc. Author: Stefan Seyfried - (C) 2009 Stefan Seyfried + (C) 2009-2013 Stefan Seyfried License: GPL @@ -50,6 +50,8 @@ #include extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */ +/* we get edvbstring.h included via from src/system/settings.h */ +#if 0 /* from edvbstring.cpp */ static bool isUTF8(const std::string &string) { @@ -81,6 +83,7 @@ static bool isUTF8(const std::string &string) } return true; // can be UTF8 (or pure ASCII, at least no non-UTF-8 8bit characters) } +#endif CLCD::CLCD() { @@ -106,6 +109,17 @@ CLCD::CLCD() */ has_lcd = false; clearClock = 0; + fontRenderer = NULL; + thread_started = false; +} + +CLCD::~CLCD() +{ + if (thread_started) { + thread_started = false; + pthread_join(thrTime, NULL); + } + delete fontRenderer; } CLCD* CLCD::getInstance() @@ -130,16 +144,18 @@ void CLCD::count_down() { } void CLCD::wake_up() { - if (atoi(g_settings.lcd_setting_dim_time) > 0) { - timeout_cnt = atoi(g_settings.lcd_setting_dim_time); + int tmp = atoi(g_settings.lcd_setting_dim_time.c_str()); + if (tmp > 0) { + timeout_cnt = (unsigned int)tmp; setlcdparameter(); } } #ifndef BOXMODEL_DM500 -void* CLCD::TimeThread(void *) +void* CLCD::TimeThread(void *p) { - while(1) + ((CLCD *)p)->thread_started = true; + while (((CLCD *)p)->thread_started) { sleep(1); struct stat buf; @@ -149,6 +165,7 @@ void* CLCD::TimeThread(void *) } else CLCD::getInstance()->wake_up(); } + printf("CLCD::TimeThread exit\n"); return NULL; } #else @@ -199,7 +216,7 @@ void CLCD::init(const char * fontfile, const char * fontname, #endif } - if (pthread_create (&thrTime, NULL, TimeThread, NULL) != 0 ) + if (pthread_create (&thrTime, NULL, TimeThread, this) != 0 ) { perror("[lcdd]: pthread_create(TimeThread)"); return ; @@ -371,7 +388,7 @@ void CLCD::setlcdparameter(int /*dimm*/, const int contrast, const int /*power*/ void CLCD::setlcdparameter(void) { last_toggle_state_power = g_settings.lcd_setting[SNeutrinoSettings::LCD_POWER]; - int dim_time = atoi(g_settings.lcd_setting_dim_time); + int dim_time = atoi(g_settings.lcd_setting_dim_time.c_str()); int dim_brightness = g_settings.lcd_setting_dim_brightness; bool timeouted = (dim_time > 0) && (timeout_cnt == 0); int brightness, power = 0; @@ -540,7 +557,7 @@ void CLCD::showTextScreen(const std::string & big, const std::string & small, co displayUpdate(); } -void CLCD::showServicename(const std::string name, const bool perform_wakeup) +void CLCD::showServicename(const std::string name, const bool clear_epg) { /* 1 = show servicename @@ -555,11 +572,13 @@ void CLCD::showServicename(const std::string name, const bool perform_wakeup) if (!name.empty()) servicename = name; + if (clear_epg) + epg_title.clear(); if (mode != MODE_TVRADIO) return; - showTextScreen(servicename, epg_title, showmode, perform_wakeup, true); + showTextScreen(servicename, epg_title, showmode, true, true); return; } @@ -602,7 +621,7 @@ void CLCD::setMovieAudio(const bool is_ac3) showPercentOver(percentOver, true, MODE_MOVIE); } -void CLCD::showTime() +void CLCD::showTime(bool) { if (showclock) { @@ -696,7 +715,8 @@ void CLCD::showVolume(const char vol, const bool perform_update) void CLCD::showPercentOver(const unsigned char perc, const bool perform_update, const MODES m) { if (mode != m) - return; + printf("CLCD::showPercentOver: mode (%d) != m (%d), please report\n", (int)mode, (int)m); + // return; int left, top, width, height = 5; bool draw = true; @@ -880,13 +900,14 @@ void CLCD::showAudioPlayMode(AUDIOMODES m) displayUpdate(); } -void CLCD::showAudioProgress(const char perc, bool isMuted) +void CLCD::showAudioProgress(const char perc) //, bool isMuted) { if (mode == MODE_AUDIO) { display.draw_fill_rect (11,53,73,61, CLCDDisplay::PIXEL_OFF); - int dp = int( perc/100.0*61.0+12.0); + int dp = perc * 61 / 100 + 12; display.draw_fill_rect (11,54,dp,60, CLCDDisplay::PIXEL_ON); +#if 0 if(isMuted) { if(dp > 12) @@ -897,6 +918,7 @@ void CLCD::showAudioProgress(const char perc, bool isMuted) else display.draw_line (12,55,72,59, CLCDDisplay::PIXEL_ON); } +#endif displayUpdate(); } } @@ -1115,7 +1137,7 @@ void CLCD::pause() display.pause(); } -void CLCD::ShowIcon(vfd_icon icon, bool show) +void CLCD::ShowIcon(fp_icon icon, bool show) { fprintf(stderr, "CLCD::ShowIcon(%d, %d)\n", icon, show); } diff --git a/src/driver/lcdd.h b/src/driver/lcdd.h index 92871e253..789c88cb3 100644 --- a/src/driver/lcdd.h +++ b/src/driver/lcdd.h @@ -4,7 +4,7 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ - + Copyright (C) 2008-2013 Stefan Seyfried License: GPL @@ -26,46 +26,43 @@ #ifndef __lcdd__ #define __lcdd__ -#ifndef LCD_UPDATE -#define LCD_UPDATE 1 -#endif - #define LCDDIR_VAR "/var/share/tuxbox/neutrino/lcdd" typedef enum { - VFD_ICON_BAR8 = 0x00000004, - VFD_ICON_BAR7 = 0x00000008, - VFD_ICON_BAR6 = 0x00000010, - VFD_ICON_BAR5 = 0x00000020, - VFD_ICON_BAR4 = 0x00000040, - VFD_ICON_BAR3 = 0x00000080, - VFD_ICON_BAR2 = 0x00000100, - VFD_ICON_BAR1 = 0x00000200, - VFD_ICON_FRAME = 0x00000400, - VFD_ICON_HDD = 0x00000800, - VFD_ICON_MUTE = 0x00001000, - VFD_ICON_DOLBY = 0x00002000, - VFD_ICON_POWER = 0x00004000, - VFD_ICON_TIMESHIFT = 0x00008000, - VFD_ICON_SIGNAL = 0x00010000, - VFD_ICON_TV = 0x00020000, - VFD_ICON_RADIO = 0x00040000, - VFD_ICON_HD = 0x01000001, - VFD_ICON_1080P = 0x02000001, - VFD_ICON_1080I = 0x03000001, - VFD_ICON_720P = 0x04000001, - VFD_ICON_480P = 0x05000001, - VFD_ICON_480I = 0x06000001, - VFD_ICON_USB = 0x07000001, - VFD_ICON_MP3 = 0x08000001, - VFD_ICON_PLAY = 0x09000001, - VFD_ICON_COL1 = 0x09000002, - VFD_ICON_PAUSE = 0x0A000001, - VFD_ICON_CAM1 = 0x0B000001, - VFD_ICON_COL2 = 0x0B000002, - VFD_ICON_CAM2 = 0x0C000001 -} vfd_icon; + FP_ICON_BAR8 = 0x00000004, + FP_ICON_BAR7 = 0x00000008, + FP_ICON_BAR6 = 0x00000010, + FP_ICON_BAR5 = 0x00000020, + FP_ICON_BAR4 = 0x00000040, + FP_ICON_BAR3 = 0x00000080, + FP_ICON_BAR2 = 0x00000100, + FP_ICON_BAR1 = 0x00000200, + FP_ICON_FRAME = 0x00000400, + FP_ICON_HDD = 0x00000800, + FP_ICON_MUTE = 0x00001000, + FP_ICON_DOLBY = 0x00002000, + FP_ICON_POWER = 0x00004000, + FP_ICON_TIMESHIFT = 0x00008000, + FP_ICON_SIGNAL = 0x00010000, + FP_ICON_TV = 0x00020000, + FP_ICON_RADIO = 0x00040000, + FP_ICON_HD = 0x01000001, + FP_ICON_1080P = 0x02000001, + FP_ICON_1080I = 0x03000001, + FP_ICON_720P = 0x04000001, + FP_ICON_480P = 0x05000001, + FP_ICON_480I = 0x06000001, + FP_ICON_USB = 0x07000001, + FP_ICON_MP3 = 0x08000001, + FP_ICON_PLAY = 0x09000001, + FP_ICON_COL1 = 0x09000002, + FP_ICON_PAUSE = 0x0A000001, + FP_ICON_CAM1 = 0x0B000001, + FP_ICON_COL2 = 0x0B000002, + FP_ICON_CAM2 = 0x0C000001 +} fp_icon; +#define CVFD CLCD #ifdef LCD_UPDATE #ifdef HAVE_CONFIG_H @@ -81,11 +78,13 @@ typedef enum #include #include +#ifdef HAVE_TRIPLEDRAGON #include class CLCDPainter; class LcdFontRenderClass; +#endif class CLCD { public: @@ -117,7 +116,7 @@ class CLCD private: - +#ifdef HAVE_TRIPLEDRAGON class FontsDef { public: @@ -149,6 +148,7 @@ class CLCD bool movie_centered; bool movie_is_ac3; pthread_t thrTime; + bool thread_started; int last_toggle_state_power; int clearClock; unsigned int timeout_cnt; @@ -164,12 +164,22 @@ class CLCD void setlcdparameter(int dimm, int contrast, int power, int inverse, int bias); void displayUpdate(); void showTextScreen(const std::string & big, const std::string & small, int showmode, bool perform_wakeup, bool centered = false); - +#else + CLCD(); + std::string menutitle; + std::string servicename; + MODES mode; + void setled(int red, int green); + static void *TimeThread(void *); + pthread_t thrTime; + bool thread_running; +#endif public: bool has_lcd; void wake_up(); void setled(void) { return; }; void setlcdparameter(void); + void setBacklight(bool) { return; }; static CLCD* getInstance(); void init(const char * fontfile, const char * fontname, @@ -180,12 +190,12 @@ class CLCD MODES getMode() { return mode; }; void setHddUsage(int perc); - void showServicename(const std::string name, const bool perform_wakeup = true); // UTF-8 + void showServicename(const std::string name, const bool clear_epg = false); void setEPGTitle(const std::string title); void setMovieInfo(const AUDIOMODES playmode, const std::string big, const std::string small, const bool centered = false); void setMovieAudio(const bool is_ac3); std::string getMenutitle() { return menutitle; }; - void showTime(); + void showTime(bool force = false); /** blocks for duration seconds */ void showRCLock(int duration = 2); void showVolume(const char vol, const bool perform_update = true); @@ -193,7 +203,7 @@ class CLCD void showMenuText(const int position, const char * text, const int highlight = -1, const bool utf_encoded = false); void showAudioTrack(const std::string & artist, const std::string & title, const std::string & album); void showAudioPlayMode(AUDIOMODES m=AUDIO_MODE_PLAY); - void showAudioProgress(const char perc, bool isMuted); + void showAudioProgress(const char perc); void setBrightness(int); int getBrightness(); @@ -224,8 +234,9 @@ class CLCD void Lock(); void Unlock(); void Clear(); - void ShowIcon(vfd_icon icon, bool show); - void ShowText(const char *s) { showServicename(std::string(s)); }; + void ShowIcon(fp_icon icon, bool show); + void ShowText(const char *s) { showServicename(std::string(s), true); }; + ~CLCD(); #ifdef LCD_UPDATE private: CFileList* m_fileList; diff --git a/src/driver/netfile.cpp b/src/driver/netfile.cpp index f7ac9658e..458e4dabf 100644 --- a/src/driver/netfile.cpp +++ b/src/driver/netfile.cpp @@ -423,9 +423,9 @@ int request_file(URL *url) if(meta_int) { - if (slot < 0){ + if (slot < 0) { dprintf(stderr, "error: meta_int != 0 && slot < 0"); - }else{ + } else { /* hook in the filter function if there is meta */ /* data present in the stream */ cache[slot].filter_arg = ShoutCAST_InitFilter(meta_int); diff --git a/src/driver/newclock.h b/src/driver/newclock.h index 08e96c932..966c4787a 100644 --- a/src/driver/newclock.h +++ b/src/driver/newclock.h @@ -23,7 +23,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#ifdef HAVE_SPARK_HARDWARE +#define HAVE_GENERIC_HARDWARE 1 +#endif #include void InitNewClock(); diff --git a/src/driver/pictureviewer/Makefile.am b/src/driver/pictureviewer/Makefile.am index bff7f879e..eac9fabea 100644 --- a/src/driver/pictureviewer/Makefile.am +++ b/src/driver/pictureviewer/Makefile.am @@ -11,7 +11,6 @@ AM_CPPFLAGS = \ @FREETYPE_CFLAGS@ \ @HWLIB_CFLAGS@ - noinst_LIBRARIES = libneutrino_pictureviewer.a libneutrino_pictureviewer_a_SOURCES = \ diff --git a/src/driver/pictureviewer/png.cpp b/src/driver/pictureviewer/png.cpp index 5e4009454..55f30613d 100644 --- a/src/driver/pictureviewer/png.cpp +++ b/src/driver/pictureviewer/png.cpp @@ -50,11 +50,7 @@ int int_png_load(const char *name, unsigned char **buffer, int* xp, int* yp, int fclose(fh); return(FH_ERROR_FORMAT); } -#if (PNG_LIBPNG_VER < 10500) - if (setjmp(png_ptr->jmpbuf)) -#else if (setjmp(png_jmpbuf(png_ptr))) -#endif { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); @@ -159,11 +155,7 @@ int fh_png_getsize(const char *name,int *x,int *y, int /*wanted_width*/, int /*w return(FH_ERROR_FORMAT); } -#if (PNG_LIBPNG_VER < 10500) - if (setjmp(png_ptr->jmpbuf)) -#else if (setjmp(png_jmpbuf(png_ptr))) -#endif { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); diff --git a/src/driver/pictureviewer/pv_config.h b/src/driver/pictureviewer/pv_config.h index 39009f012..7c7a98d6b 100644 --- a/src/driver/pictureviewer/pv_config.h +++ b/src/driver/pictureviewer/pv_config.h @@ -1,3 +1,8 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + #define FBV_SUPPORT_PNG #define FBV_SUPPORT_BMP #define FBV_SUPPORT_JPEG diff --git a/src/driver/radiotext.cpp b/src/driver/radiotext.cpp index 80eae7e1a..28f1c8186 100644 --- a/src/driver/radiotext.cpp +++ b/src/driver/radiotext.cpp @@ -79,6 +79,7 @@ #include #include +#include #include #include @@ -2369,6 +2370,7 @@ void CRadioText::setPid(uint inPid) void CRadioText::run() { + set_threadname("n:radiotext"); uint current_pid = 0; printf("CRadioText::run: ###################### Starting thread ######################\n"); diff --git a/src/driver/radiotools.h b/src/driver/radiotools.h index 24bf05c30..c13d7d3aa 100644 --- a/src/driver/radiotools.h +++ b/src/driver/radiotools.h @@ -24,13 +24,12 @@ #ifndef __RADIO_TOOLS_H #define __RADIO_TOOLS_H +#include unsigned short crc16_ccitt(unsigned char *daten, int len, bool skipfirst); char *rtrim(char *text); -typedef long long unsigned int uint64_t; - class cTimeMs { private: uint64_t begin; diff --git a/src/driver/rcinput.cpp b/src/driver/rcinput.cpp index 65856a9fe..d65043848 100644 --- a/src/driver/rcinput.cpp +++ b/src/driver/rcinput.cpp @@ -65,7 +65,17 @@ #define ENABLE_REPEAT_CHECK +#if HAVE_SPARK_HARDWARE +/* this relies on event0 being the AOTOM frontpanel driver device + * TODO: what if another input device is present? */ +const char * const RC_EVENT_DEVICE[NUMBER_OF_EVENT_DEVICES] = {"/dev/input/nevis_ir", "/dev/input/event0"}; +#elif HAVE_GENERIC_HARDWARE +/* the FIFO created by libstb-hal */ +const char * const RC_EVENT_DEVICE[NUMBER_OF_EVENT_DEVICES] = {"/tmp/neutrino.input"}; +#else +//const char * const RC_EVENT_DEVICE[NUMBER_OF_EVENT_DEVICES] = {"/dev/input/nevis_ir", "/dev/input/event0"}; const char * const RC_EVENT_DEVICE[NUMBER_OF_EVENT_DEVICES] = {"/dev/input/nevis_ir"}; +#endif typedef struct input_event t_input_event; #ifdef KEYBOARD_INSTEAD_OF_REMOTE_CONTROL @@ -543,7 +553,6 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6 uint64_t getKeyBegin = time_monotonic_us(); while(1) { - /* we later check for ev.type = EV_SYN which is 0x00, so set something invalid here... */ timer_id = 0; if ( !timers.empty() ) { @@ -1213,6 +1222,9 @@ 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))) { 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) { @@ -1231,8 +1243,8 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6 } uint32_t trkey = translate(ev.code); -#ifdef DEBUG - printf("%d key: %04x value %d, translate: %04x -%s-\n", ev.value, ev.code, ev.value, trkey, getKeyName(trkey).c_str()); +#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; @@ -1278,7 +1290,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6 if (trkey == rc_last_key) { /* only allow selected keys to be repeated */ if (mayRepeat(trkey, bAllowRepeatLR) || - (g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (cs_get_revision() > 7))) ) + (g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown)))) { #ifdef ENABLE_REPEAT_CHECK if (rc_last_repeat_key != trkey) { @@ -1597,6 +1609,16 @@ int CRCInput::translate(int code) return RC_up; case 0x101: // FIXME -- needed? return RC_down; +#ifdef HAVE_AZBOX_HARDWARE + case KEY_HOME: + return RC_favorites; + case KEY_TV: + return RC_stop; + case KEY_RADIO: + return RC_record; + case KEY_PLAY: + return RC_pause; +#endif default: break; } diff --git a/src/driver/rcinput.h b/src/driver/rcinput.h index a6d43e9db..7b020bb82 100644 --- a/src/driver/rcinput.h +++ b/src/driver/rcinput.h @@ -115,8 +115,8 @@ */ -typedef uint32_t neutrino_msg_t; -typedef uint32_t neutrino_msg_data_t; +typedef unsigned long neutrino_msg_t; +typedef unsigned long neutrino_msg_data_t; #define NEUTRINO_UDS_NAME "/tmp/neutrino.sock" @@ -147,7 +147,11 @@ class CRCInput int fd_pipe_high_priority[2]; int fd_pipe_low_priority[2]; int fd_gamerc; +#ifdef HAVE_SPARK_HARDWARE +#define NUMBER_OF_EVENT_DEVICES 2 +#else #define NUMBER_OF_EVENT_DEVICES 1 +#endif int fd_rc[NUMBER_OF_EVENT_DEVICES]; int fd_keyb; int fd_event; diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 0c36af20e..1c623307b 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -17,8 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include @@ -259,7 +258,7 @@ bool CRecordInstance::Stop(bool remove_event) } time_t end_time = time(0); - recMovieInfo->length = (int) round((double) (end_time - start_time) / (double) 60); + recMovieInfo->length = (end_time - start_time + 30) / 60; CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, rec_stop_msg.c_str()); if ((!(autoshift && g_settings.auto_timeshift)) && g_settings.recording_startstop_msg) diff --git a/src/driver/record.h b/src/driver/record.h index bbc93ce1f..8a9c2e3f6 100644 --- a/src/driver/record.h +++ b/src/driver/record.h @@ -35,8 +35,8 @@ #if HAVE_COOL_HARDWARE #include #endif -#if HAVE_TRIPLEDRAGON -#include +#if USE_STB_HAL +#include #endif #include @@ -48,7 +48,12 @@ extern "C" { #define REC_MAX_APIDS 10 #define FILENAMEBUFFERSIZE 1024 +#if HAVE_TRIPLEDRAGON +/* I'm not able to get it to work with more than 1 recording at a time :-( */ +#define RECORD_MAX_COUNT 1 +#else #define RECORD_MAX_COUNT 8 +#endif #define TSHIFT_MODE_OFF 0 #define TSHIFT_MODE_ON 1 diff --git a/src/driver/scanepg.cpp b/src/driver/scanepg.cpp index 39b9040d3..72e88218d 100644 --- a/src/driver/scanepg.cpp +++ b/src/driver/scanepg.cpp @@ -130,7 +130,7 @@ bool CEpgScan::AddFavorites() CChannelList * clist = TVfavList->Bouquets[j]->channelList; AddBouquet(clist); } - INFO("scan map size: %d -> %d\n", old_size, scanmap.size()); + INFO("scan map size: %d -> %zd\n", old_size, scanmap.size()); return (old_size != scanmap.size()); } @@ -154,7 +154,7 @@ bool CEpgScan::AddSelected() AddBouquet(clist); } } - INFO("scan map size: %d -> %d\n", old_size, scanmap.size()); + INFO("scan map size: %d -> %zd\n", old_size, scanmap.size()); return (old_size != scanmap.size()); } @@ -198,7 +198,7 @@ void CEpgScan::AddTransponders() scanmap.clear(); current_bnum = bouquetList->getActiveBouquetNumber(); AddBouquet(bouquetList->Bouquets[current_bnum]->channelList); - INFO("Added bouquet #%d, scan map size: %d", current_bnum, scanmap.size()); + INFO("Added bouquet #%d, scan map size: %zd", current_bnum, scanmap.size()); } } else if (g_settings.epg_scan == SCAN_FAV) { AddFavorites(); @@ -223,7 +223,7 @@ void CEpgScan::Start(bool instandby) standby = instandby; live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); AddTransponders(); - INFO("starting %s scan, scanning %d, scan map size: %d", standby ? "standby" : "live", scan_in_progress, scanmap.size()); + INFO("starting %s scan, scanning %d, scan map size: %zd", standby ? "standby" : "live", scan_in_progress, scanmap.size()); if (standby || !scan_in_progress) Next(); } @@ -272,7 +272,7 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data) /* live channel changed, block scan channel change by timer */ scan_in_progress = true; AddTransponders(); - INFO("EVT_ZAP_COMPLETE, scan map size: %d\n", scanmap.size()); + INFO("EVT_ZAP_COMPLETE, scan map size: %zd\n", scanmap.size()); #if 0 t_channel_id chid = *(t_channel_id *)data; if (IS_WEBTV(chid)) @@ -288,7 +288,7 @@ int CEpgScan::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data) scanned.insert(newchan->getTransponderId()); scanmap.erase(newchan->getTransponderId()); } - INFO("EIT read complete [" PRINTF_CHANNEL_ID_TYPE "], scan map size: %d", chid, scanmap.size()); + INFO("EIT read complete [" PRINTF_CHANNEL_ID_TYPE "], scan map size: %zd", chid, scanmap.size()); Next(); return messages_return::handled; diff --git a/src/driver/screenshot.cpp b/src/driver/screenshot.cpp index 5b32b1e7a..e7ecf24d5 100644 --- a/src/driver/screenshot.cpp +++ b/src/driver/screenshot.cpp @@ -45,6 +45,7 @@ #include #include #include +#include extern "C" { #include @@ -82,7 +83,7 @@ bool CScreenShot::GetData() #endif if (videoDecoder->getBlank()) get_video = false; -#if 1 // to enable after libcs/drivers update +#ifdef SCREENSHOT res = videoDecoder->GetScreenImage(pixel_data, xres, yres, get_video, get_osd, scale_to_video); #endif @@ -90,7 +91,7 @@ bool CScreenShot::GetData() /* sort of hack. GXA used to transfer/convert live image to RGB, * so setup GXA back */ CFrameBuffer::getInstance()->setupGXA(); - CFrameBuffer::getInstance()->add_gxa_sync_marker(); + //CFrameBuffer::getInstance()->add_gxa_sync_marker(); CFrameBuffer::getInstance()->setActive(true); #endif mutex.unlock(); @@ -106,6 +107,7 @@ bool CScreenShot::GetData() /* start ::run in new thread to save file in selected format */ bool CScreenShot::Start() { + set_threadname("n:screenshot"); bool ret = false; if(GetData()) ret = (start() == 0); @@ -192,11 +194,7 @@ bool CScreenShot::SavePng() png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); info_ptr = png_create_info_struct(png_ptr); -#if (PNG_LIBPNG_VER < 10500) - if (setjmp(png_ptr->jmpbuf)) -#else if (setjmp(png_jmpbuf(png_ptr))) -#endif { printf("CScreenShot::SavePng: %s save error\n", filename.c_str()); png_destroy_write_struct(&png_ptr, &info_ptr); diff --git a/src/driver/shutdown_count.cpp b/src/driver/shutdown_count.cpp index 0bd113656..43d55f22c 100644 --- a/src/driver/shutdown_count.cpp +++ b/src/driver/shutdown_count.cpp @@ -4,6 +4,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ + Copyright (C) 2012-2013 Stefan Seyfried + License: GPL This program is free software; you can redistribute it and/or modify @@ -39,10 +41,21 @@ SHTDCNT::SHTDCNT() { + thread_running = false; sleep_cnt = 0; shutdown_cnt = 0; } +SHTDCNT::~SHTDCNT() +{ + if (thread_running) + { + thread_running = false; + pthread_cancel(thrTime); + pthread_join(thrTime, NULL); + } +} + SHTDCNT* SHTDCNT::getInstance() { static SHTDCNT* shtdcnt = NULL; @@ -67,9 +80,11 @@ void SHTDCNT::init() { shutdown_cnt = g_settings.shutdown_count * 60; sleep_cnt = g_settings.shutdown_min * 60; + thread_running = true; if (pthread_create (&thrTime, NULL, TimeThread, NULL) != 0 ) { perror("[SHTDCNT]: pthread_create(TimeThread)"); + thread_running = false; return ; } } diff --git a/src/driver/shutdown_count.h b/src/driver/shutdown_count.h index 7fed38ba8..ed7cd0c29 100644 --- a/src/driver/shutdown_count.h +++ b/src/driver/shutdown_count.h @@ -4,6 +4,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ + Copyright (C) 2012-2013 Stefan Seyfried + License: GPL This program is free software; you can redistribute it and/or modify @@ -31,6 +33,7 @@ class SHTDCNT private: pthread_t thrTime; + bool thread_running; unsigned int shutdown_cnt; unsigned int sleep_cnt; @@ -38,9 +41,8 @@ class SHTDCNT SHTDCNT(); static void* TimeThread(void*); - public: - + ~SHTDCNT(); void setlcdparameter(void); static SHTDCNT* getInstance(); diff --git a/src/driver/simple_display.cpp b/src/driver/simple_display.cpp new file mode 100644 index 000000000..ac3f6323e --- /dev/null +++ b/src/driver/simple_display.cpp @@ -0,0 +1,502 @@ +/* + Routines to drive simple one-line text or SPARK's 4 digit LED display + + (C) 2012 Stefan Seyfried + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +//#include +#include +#if HAVE_SPARK_HARDWARE +#include +#define DISPLAY_DEV "/dev/vfd" +#endif +#if HAVE_AZBOX_HARDWARE +#define DISPLAY_DEV "/proc/vfd" +#define LED_DEV "/proc/led" +#endif +#if HAVE_GENERIC_HARDWARE +#define DISPLAY_DEV "/dev/null" +#endif + +static char volume = 0; +//static char percent = 0; +static bool power = true; +static bool muted = false; +static bool showclock = true; +static time_t last_display = 0; +static char display_text[64] = { 0 }; +static bool led_r = false; +static bool led_g = false; +static bool upd_display = false; +static bool vol_active = false; + +static inline int dev_open() +{ + int fd = open(DISPLAY_DEV, O_RDWR); + if (fd < 0) + fprintf(stderr, "[neutrino] simple_display: open " DISPLAY_DEV ": %m\n"); + return fd; +} + +#if HAVE_AZBOX_HARDWARE +static inline int led_open() +{ + int fd = open(LED_DEV, O_RDWR); + if (fd < 0) + fprintf(stderr, "[neutrino] simple_display: open " LED_DEV ": %m\n"); + return fd; +} +#endif + +static void replace_umlauts(std::string &s) +{ + /* this is crude, it just replaces ÄÖÜ with AOU since the display can't show them anyway */ + /* Ä ä Ö ö Ü ü */ + char tofind[][3] = { "\xc3\x84", "\xc3\xa4", "\xc3\x96", "\xc3\xb6", "\xc3\x9c", "\xc3\xbc" }; + char toreplace[] = { "AaOoUu" }; + char repl[2]; + repl[1] = '\0'; + int i = 0; + size_t pos; + // print("%s:>> '%s'\n", __func__, s.c_str()); + while (toreplace[i] != 0x0) { + pos = s.find(tofind[i]); + if (pos == std::string::npos) { + i++; + continue; + } + repl[0] = toreplace[i]; + s.replace(pos, 2, std::string(repl)); + } + // printf("%s:<< '%s'\n", __func__, s.c_str()); +} + +static void display(const char *s, bool update_timestamp = true) +{ + int fd = dev_open(); + int len = strlen(s); + if (fd < 0) + return; +printf("%s '%s'\n", __func__, s); + write(fd, s, len); + close(fd); + if (update_timestamp) + { + last_display = time(NULL); + /* increase timeout to ensure that everything is displayed + * the driver displays 5 characters per second */ + if (len > g_info.hw_caps->display_xres) + last_display += (len - g_info.hw_caps->display_xres) / 5; + } +} + +CLCD::CLCD() +{ + /* do not show menu in neutrino... */ + has_lcd = false; + servicename = ""; + thread_running = false; +} + +CLCD::~CLCD() +{ + if (thread_running) + { + thread_running = false; + pthread_cancel(thrTime); + pthread_join(thrTime, NULL); + } +} + +CLCD* CLCD::getInstance() +{ + static CLCD* lcdd = NULL; + if (lcdd == NULL) + lcdd = new CLCD(); + return lcdd; +} + +void CLCD::wake_up() +{ +} + +void* CLCD::TimeThread(void *) +{ + while (CLCD::getInstance()->thread_running) { + sleep(1); + CLCD::getInstance()->showTime(); + } + return NULL; +} + +void CLCD::init(const char *, const char *, const char *, const char *, const char *, const char *) +{ + setMode(MODE_TVRADIO); + thread_running = true; + if (pthread_create (&thrTime, NULL, TimeThread, NULL) != 0 ) { + perror("[neutino] CLCD::init pthread_create(TimeThread)"); + thread_running = false; + return ; + } +} + +void CLCD::setlcdparameter(void) +{ +} + +void CLCD::showServicename(std::string name, bool) +{ + if (g_info.hw_caps->display_type == HW_DISPLAY_LED_NUM) + return; + servicename = name; + if (mode != MODE_TVRADIO) + return; + replace_umlauts(servicename); + strncpy(display_text, servicename.c_str(), sizeof(display_text) - 1); + display_text[sizeof(display_text) - 1] = '\0'; + upd_display = true; +} + +#if HAVE_SPARK_HARDWARE +void CLCD::setled(int red, int green) +{ + struct aotom_ioctl_data d; + int leds[2] = { red, green }; + int i; + int fd = dev_open(); + if (fd < 0) + return; + + // printf("%s red:%d green:%d\n", __func__, red, green); + + for (i = 0; i < 2; i++) + { + if (leds[i] == -1) + continue; + d.u.led.led_nr = i; + d.u.led.on = leds[i]; + if (ioctl(fd, VFDSETLED, &d) < 0) + fprintf(stderr, "[neutrino] %s setled VFDSETLED: %m\n", __func__); + } + close(fd); +} +#elif HAVE_AZBOX_HARDWARE +void CLCD::setled(int red, int green) +{ + static unsigned char col = '0'; /* need to remember the state. 1 == blue, 2 == red */ + int leds[3] = { -1, green, red }; + int i; + char s[3]; + int fd = led_open(); + if (fd < 0) + return; + for (i = 1; i <= 2; i++) + { + if (leds[i] == -1) /* don't touch */ + continue; + col &= ~(i); /* clear the bit... */ + if (leds[i]) + col |= i; /* ...and set it again */ + } + sprintf(s, "%c\n", col); + write(fd, s, 3); + close(fd); + //printf("%s(%d, %d): %c\n", __func__, red, green, col); +} +#else +void CLCD::setled(int /*red*/, int /*green*/) +{ +} +#endif + +void CLCD::showTime(bool force) +{ + static bool blink = false; + int red = -1, green = -1; + + if (mode == MODE_SHUTDOWN) + { + setled(1, 1); + return; + } + + time_t now = time(NULL); + if (upd_display) + { + display(display_text); + upd_display = false; + } + else if (power && (force || (showclock && (now - last_display) > 4))) + { + char timestr[64]; /* todo: change if we have a simple display with 63+ chars ;) */ + struct tm *t; + static int hour = 0, minute = 0; + + t = localtime(&now); + if (force || last_display || (hour != t->tm_hour) || (minute != t->tm_min)) { + hour = t->tm_hour; + minute = t->tm_min; + int ret = -1; +#if HAVE_SPARK_HARDWARE + now += t->tm_gmtoff; + int fd = dev_open(); +#if 0 /* VFDSETTIME is broken and too complicated anyway -> use VFDSETTIME2 */ + int mjd = 40587 + now / 86400; /* 1970-01-01 is mjd 40587 */ + struct aotom_ioctl_data d; + d.u.time.time[0] = mjd >> 8; + d.u.time.time[1] = mjd & 0xff; + d.u.time.time[2] = hour; + d.u.time.time[3] = minute; + d.u.time.time[4] = t->tm_sec; + int ret = ioctl(fd, VFDSETTIME, &d); +#else + ret = ioctl(fd, VFDSETTIME2, &now); +#endif + close(fd); +#endif + if (ret < 0 && servicename.empty()) + { + if (g_info.hw_caps->display_xres < 5) + sprintf(timestr, "%02d%02d", hour, minute); + else /* pad with spaces on the left side to center the time string */ + sprintf(timestr, "%*s%02d:%02d",(g_info.hw_caps->display_xres - 5)/2, "", hour, minute); + display(timestr, false); + } + else + { + if (vol_active) + showServicename(servicename); + vol_active = false; + } + last_display = 0; + } + } + + if (led_r) + red = blink; + blink = !blink; + if (led_g) + green = blink; + + if (led_r || led_g) + setled(red, green); +} + +void CLCD::showRCLock(int) +{ +} + +/* update is default true, the mute code sets it to false + * to force an update => inverted logic! */ +void CLCD::showVolume(const char vol, const bool update) +{ + char s[32]; + const int type = (g_info.hw_caps->display_xres < 5); + const char *vol_fmt[] = { "Vol:%3d%%", "%4d" }; + const char *mutestr[] = { "Vol:MUTE", "mute" }; + if (vol == volume && update) + return; + volume = vol; + /* char is unsigned, so vol is never < 0 */ + if (volume > 100) + volume = 100; + + if (muted) + strcpy(s, mutestr[type]); + else + sprintf(s, vol_fmt[type], volume); + + display(s); + vol_active = true; +} + +void CLCD::showPercentOver(const unsigned char /*perc*/, const bool /*perform_update*/, const MODES) +{ +} + +void CLCD::showMenuText(const int, const char *text, const int, const bool) +{ + if (mode != MODE_MENU_UTF8) + return; + std::string tmp = text; + replace_umlauts(tmp); + strncpy(display_text, tmp.c_str(), sizeof(display_text) - 1); + display_text[sizeof(display_text) - 1] = '\0'; + upd_display = true; +} + +void CLCD::showAudioTrack(const std::string &, const std::string & /*title*/, const std::string &) +{ + if (mode != MODE_AUDIO) + return; +// ShowText(title.c_str()); +} + +void CLCD::showAudioPlayMode(AUDIOMODES) +{ +} + +void CLCD::showAudioProgress(const char) +{ +} + +void CLCD::setMode(const MODES m, const char * const) +{ + mode = m; + + switch (m) { + case MODE_TVRADIO: + setled(0, 0); + showclock = true; + power = true; + if (g_info.hw_caps->display_type != HW_DISPLAY_LED_NUM) { + strncpy(display_text, servicename.c_str(), sizeof(display_text) - 1); + display_text[sizeof(display_text) - 1] = '\0'; + upd_display = true; + } + showTime(); + break; + case MODE_SHUTDOWN: + showclock = false; + showTime(); + Clear(); + break; + case MODE_STANDBY: + setled(0, 1); + showclock = true; + showTime(true); + break; + default: + showclock = true; + showTime(); + } +} + +void CLCD::setBrightness(int) +{ +} + +int CLCD::getBrightness() +{ + return 0; +} + +void CLCD::setBrightnessStandby(int) +{ +} + +int CLCD::getBrightnessStandby() +{ + return 0; +} + +void CLCD::setPower(int) +{ +} + +int CLCD::getPower() +{ + return 0; +} + +void CLCD::togglePower(void) +{ + power = !power; + if (!power) + Clear(); + else + showTime(true); +} + +void CLCD::setMuted(bool mu) +{ +printf("spark_led:%s %d\n", __func__, mu); + muted = mu; + showVolume(volume, false); +} + +void CLCD::resume() +{ +} + +void CLCD::pause() +{ +} + +void CLCD::Lock() +{ +} + +void CLCD::Unlock() +{ +} + +#if HAVE_SPARK_HARDWARE +void CLCD::Clear() +{ + int fd = dev_open(); + if (fd < 0) + return; + int ret = ioctl(fd, VFDDISPLAYCLR); + if(ret < 0) + perror("[neutrino] spark_led Clear() VFDDISPLAYCLR"); + close(fd); + servicename.clear(); +printf("spark_led:%s\n", __func__); +} +#else +void CLCD::Clear() +{ + display(" ", false); +} +#endif + +void CLCD::ShowIcon(fp_icon i, bool on) +{ + switch (i) + { + case FP_ICON_CAM1: + led_r = on; + setled(led_r, -1); /* switch instant on / switch off if disabling */ + break; + case FP_ICON_PLAY: + led_g = on; + setled(-1, led_g); + break; + default: + break; + } +} + +void CLCD::setEPGTitle(const std::string) +{ +} + diff --git a/src/driver/spark_led.h b/src/driver/spark_led.h new file mode 100644 index 000000000..6908b0012 --- /dev/null +++ b/src/driver/spark_led.h @@ -0,0 +1,61 @@ +/* ugly: this is copied from frontcontroller utility, but the driver + * does not seem to provide userspace headers... :-( */ + + +/* this setups the mode temporarily (for one ioctl) + * to the desired mode. currently the "normal" mode + * is the compatible vfd mode + */ +struct set_mode_s { + int compat; /* 0 = compatibility mode to vfd driver; 1 = nuvoton mode */ +}; + +struct set_brightness_s { + int level; +}; + +struct set_icon_s { + int icon_nr; + int on; +}; + +struct set_led_s { + int led_nr; + int on; +}; + +/* time must be given as follows: + * time[0] & time[1] = mjd ??? + * time[2] = hour + * time[3] = min + * time[4] = sec + */ +struct set_standby_s { + char time[5]; +}; + +struct set_time_s { + char time[5]; +}; + +struct aotom_ioctl_data { + union + { + struct set_icon_s icon; + struct set_led_s led; + struct set_brightness_s brightness; + struct set_mode_s mode; + struct set_standby_s standby; + struct set_time_s time; + } u; +}; + +/* a strange way of defining ioctls... but anyway... */ +#define VFDGETTIME 0xc0425afa +#define VFDSETTIME 0xc0425afb +#define VFDSTANDBY 0xc0425afc +#define VFDSETLED 0xc0425afe +#define VFDDISPLAYCHARS 0xc0425a00 +#define VFDDISPLAYCLR 0xc0425b00 +#define VFDSETMODE 0xc0425aff + diff --git a/src/driver/stacktrace.h b/src/driver/stacktrace.h new file mode 100644 index 000000000..2db7ef096 --- /dev/null +++ b/src/driver/stacktrace.h @@ -0,0 +1,101 @@ +// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ +// published under the WTFPL v2.0 + +#ifndef _STACKTRACE_H_ +#define _STACKTRACE_H_ + +#ifdef HAVE_BACKTRACE + +#include +#include +#include +#include + +/** Print a demangled stack backtrace of the caller function to FILE* out. */ +static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) +{ + fprintf(out, "stack trace:\n"); + + // storage array for stack trace address data + void* addrlist[max_frames+1]; + + // retrieve current stack addresses + int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); + + if (addrlen == 0) { + fprintf(out, " \n"); + return; + } + + // resolve addresses into strings containing "filename(function+address)", + // this array must be free()-ed + char** symbollist = backtrace_symbols(addrlist, addrlen); + + // allocate string which will be filled with the demangled function name + size_t funcnamesize = 256; + char* funcname = (char*)malloc(funcnamesize); + + // iterate over the returned symbol lines. skip the first, it is the + // address of this function. + for (int i = 1; i < addrlen; i++) + { + char *begin_name = 0, *begin_offset = 0, *end_offset = 0; + + // find parentheses and +address offset surrounding the mangled name: + // ./module(function+0x15c) [0x8048a6d] + for (char *p = symbollist[i]; *p; ++p) + { + if (*p == '(') + begin_name = p; + else if (*p == '+') + begin_offset = p; + else if (*p == ')' && begin_offset) { + end_offset = p; + break; + } + } + + if (begin_name && begin_offset && end_offset + && begin_name < begin_offset) + { + *begin_name++ = '\0'; + *begin_offset++ = '\0'; + *end_offset = '\0'; + + // mangled name is now in [begin_name, begin_offset) and caller + // offset in [begin_offset, end_offset). now apply + // __cxa_demangle(): + + int status; + char* ret = abi::__cxa_demangle(begin_name, + funcname, &funcnamesize, &status); + if (status == 0) { + funcname = ret; // use possibly realloc()-ed string + fprintf(out, " %s : %s+%s\n", + symbollist[i], funcname, begin_offset); + } + else { + // demangling failed. Output function name as a C function with + // no arguments. + fprintf(out, " %s : %s()+%s\n", + symbollist[i], begin_name, begin_offset); + } + } + else + { + // couldn't parse the line? print the whole line. + fprintf(out, " %s\n", symbollist[i]); + } + } + + free(funcname); + free(symbollist); +} +#else + +static inline void print_stacktrace(FILE*, unsigned int) {}; +static inline void print_stacktrace() {}; + +#endif + +#endif // _STACKTRACE_H_ diff --git a/src/driver/streamts.cpp b/src/driver/streamts.cpp index f34de80e3..684eeabba 100644 --- a/src/driver/streamts.cpp +++ b/src/driver/streamts.cpp @@ -56,6 +56,10 @@ #include #include #include +/* merge conflict */ +#if 0 +#include +#endif #include #include @@ -73,7 +77,7 @@ CStreamInstance::CStreamInstance(int clientfd, t_channel_id chid, stream_pids_t &_pids) { - printf("CStreamInstance:: new channel %llx fd %d\n", chid, clientfd); + printf("CStreamInstance:: new channel %" PRIx64 " fd %d\n", chid, clientfd); fds.insert(clientfd); pids = _pids; channel_id = chid; @@ -99,7 +103,7 @@ bool CStreamInstance::Start() return false; } running = true; - printf("CStreamInstance::Start: %llx\n", channel_id); + printf("CStreamInstance::Start: %" PRIx64 "\n", channel_id); return (OpenThreads::Thread::start() == 0); } @@ -108,7 +112,7 @@ bool CStreamInstance::Stop() if (!running) return false; - printf("CStreamInstance::Stop: %llx\n", channel_id); + printf("CStreamInstance::Stop: %" PRIx64 "\n", channel_id); running = false; return (OpenThreads::Thread::join() == 0); } @@ -135,7 +139,7 @@ bool CStreamInstance::Send(ssize_t r, unsigned char * _buf) } } while ((count > 0) && (i-- > 0)); if (count) - printf("send err, fd %d: (%d from %d)\n", *it, r-count, r); + printf("send err, fd %d: (%zd from %zd)\n", *it, r-count, r); } return true; } @@ -151,7 +155,7 @@ void CStreamInstance::AddClient(int clientfd) { OpenThreads::ScopedLock m_lock(mutex); fds.insert(clientfd); - printf("CStreamInstance::AddClient: %d (count %d)\n", clientfd, fds.size()); + printf("CStreamInstance::AddClient: %d (count %d)\n", clientfd, (int)fds.size()); } void CStreamInstance::RemoveClient(int clientfd) @@ -159,11 +163,18 @@ void CStreamInstance::RemoveClient(int clientfd) OpenThreads::ScopedLock m_lock(mutex); fds.erase(clientfd); close(clientfd); - printf("CStreamInstance::RemoveClient: %d (count %d)\n", clientfd, fds.size()); + printf("CStreamInstance::RemoveClient: %d (count %d)\n", clientfd, (int)fds.size()); } bool CStreamInstance::Open() { +/* merge conflict */ +#if 0 + printf("CStreamInstance::run: %" PRIx64 "\n", channel_id); + set_threadname("n:streaminstance"); + +#endif + CZapitChannel * tmpchan = CServiceManager::getInstance()->FindChannel(channel_id); if (!tmpchan) return false; @@ -203,7 +214,7 @@ void CStreamInstance::run() CCamManager::getInstance()->Stop(channel_id, CCamManager::STREAM); - printf("CStreamInstance::run: exiting %llx (%d fds)\n", channel_id, fds.size()); + printf("CStreamInstance::run: exiting %" PRIx64 " (%d fds)\n", channel_id, (int)fds.size()); Close(); delete dmx; @@ -289,7 +300,7 @@ CFrontend * CStreamManager::FindFrontend(CZapitChannel * channel) t_channel_id chid = channel->getChannelID(); if (CRecordManager::getInstance()->RecordingStatus(chid)) { - printf("CStreamManager::FindFrontend: channel %llx recorded, aborting..\n", chid); + printf("CStreamManager::%s: channel %" PRIx64 " recorded, aborting..\n", __func__, chid); return frontend; } @@ -411,7 +422,7 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFro #else t_channel_id tmpid; bp = &cbuf[5]; - if (sscanf(bp, "id=%llx", &tmpid) == 1) { + if (sscanf(bp, "id=%" SCNx64, &tmpid) == 1) { channel = CServiceManager::getInstance()->FindChannel(tmpid); chid = tmpid; } @@ -419,7 +430,7 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFro if (!channel) return false; - printf("CStreamManager::Parse: channel_id %llx [%s]\n", chid, channel->getName().c_str()); + printf("CStreamManager::Parse: channel_id %" PRIx64 " [%s]\n", chid, channel->getName().c_str()); if (IS_WEBTV(chid)) return true; @@ -437,7 +448,7 @@ bool CStreamManager::Parse(int fd, stream_pids_t &pids, t_channel_id &chid, CFro 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()); + printf("CStreamManager::AddPids: no pids in url, using channel %" PRIx64 " pids\n", channel->getChannelID()); if (channel->getVideoPid()) pids.insert(channel->getVideoPid()); for (int i = 0; i < channel->getAudioChannelCount(); i++) @@ -551,6 +562,10 @@ void CStreamManager::run() int poll_timeout = -1; printf("Starting STREAM thread keeper, tid %ld\n", syscall(__NR_gettid)); +/* merge conflict */ +#if 0 + set_threadname("n:streammanager"); +#endif while (running) { mutex.lock(); diff --git a/src/driver/vfd.cpp b/src/driver/vfd.cpp index 5134d562e..d5a410bb0 100644 --- a/src/driver/vfd.cpp +++ b/src/driver/vfd.cpp @@ -104,7 +104,7 @@ CVFD::CVFD() support_numbers = true; #endif - text[0] = 0; + text.clear(); clearClock = 0; mode = MODE_TVRADIO; switch_name_time_cnt = 0; @@ -438,7 +438,7 @@ void CVFD::showVolume(const char vol, const bool force_update) if (g_settings.lcd_setting[SNeutrinoSettings::LCD_SHOW_VOLUME] == 1) { wake_up(); ShowIcon(FP_ICON_FRAME, true); - int pp = (int) round((double) vol * (double) 8 / (double) 100); + int pp = (vol * 8 + 50) / 100; if(pp > 8) pp = 8; if(force_update || oldpp != pp) { @@ -481,7 +481,7 @@ void CVFD::showPercentOver(const unsigned char perc, const bool /*perform_update if(perc == 255) pp = 0; else - pp = (int) round((double) perc * (double) 8 / (double) 100); + pp = (perc * 8 + 50) / 100; if(pp > 8) pp = 8; if(pp != ppold) { @@ -773,7 +773,7 @@ void CVFD::Clear() if(ret < 0) perror("IOC_FP_SET_TEXT"); else - text[0] = 0; + text.clear(); } void CVFD::ShowIcon(fp_icon icon, bool show) @@ -791,13 +791,17 @@ void CVFD::ShowText(const char * str) return; char flags[2] = { FP_FLAG_ALIGN_LEFT, 0 }; + if (! str) { + printf("CVFD::ShowText: str is NULL!\n"); + return; + } - if (g_settings.lcd_scroll) + if (g_settings.lcd_scroll && ((int)strlen(str) > g_info.hw_caps->display_xres)) flags[0] |= FP_FLAG_SCROLL_ON | FP_FLAG_SCROLL_SIO | FP_FLAG_SCROLL_DELAY; std::string txt = std::string(flags) + str; txt = trim(txt); - printf("CVFD::ShowText: [%s]\n", txt.c_str() + 1); + printf("CVFD::ShowText: [0x%02x][%s]\n", flags[0], txt.c_str() + 1); size_t len = txt.length(); if (txt == text || len > 255) diff --git a/src/driver/vfd.h b/src/driver/vfd.h index 5f1c374a7..9664f1aa0 100644 --- a/src/driver/vfd.h +++ b/src/driver/vfd.h @@ -120,6 +120,7 @@ class CVFD void setMode(const MODES m, const char * const title = ""); void showServicename(const std::string & name, int number = -1); // UTF-8 + void setEPGTitle(const std::string) { return; }; void showTime(bool force = false); /** blocks for duration seconds */ void showRCLock(int duration = 2); diff --git a/src/driver/volume.cpp b/src/driver/volume.cpp index 4a3112c52..c7c6c4a77 100644 --- a/src/driver/volume.cpp +++ b/src/driver/volume.cpp @@ -4,6 +4,7 @@ volume bar - Neutrino-GUI Copyright (C) 2011-2013 M. Liebmann (micha-bbg) + Copyright (C) 2012,2013 Stefan Seyfried License: GPL @@ -31,16 +32,21 @@ #include #include #include -#include +/* compat header from zapit/include */ +#include #include +#include #include #include #include +#include #include #include #include +#define VOLUME_SCRIPT CONFIGDIR "/volume.sh" + extern CRemoteControl * g_RemoteControl; extern cAudio * audioDecoder; @@ -86,7 +92,10 @@ void CVolume::setVolumeExt(int vol) void CVolume::setVolume(const neutrino_msg_t key) { + if (!g_RCInput) /* don't die... */ + return; neutrino_msg_t msg = key; + static bool do_vol = true; /* false if volume is handled by external script */ int mode = CNeutrinoApp::getInstance()->getMode(); if (msg <= CRCInput::RC_MaxRC) { @@ -112,14 +121,27 @@ void CVolume::setVolume(const neutrino_msg_t key) if ((msg == (neutrino_msg_t) g_settings.key_volumeup || msg == (neutrino_msg_t) g_settings.key_volumedown) || (sub_chan_keybind && (msg == CRCInput::RC_right || msg == CRCInput::RC_left))) { int dir = (msg == (neutrino_msg_t) g_settings.key_volumeup || msg == CRCInput::RC_right) ? 1 : -1; + if (my_system(2, VOLUME_SCRIPT, dir > 0 ? "up" : "down") == 0) + { + do_vol = false; + /* clear all repeated events */ + neutrino_msg_t tmp = msg; + while (msg == tmp) + g_RCInput->getMsg(&tmp, &data, 0); + if (tmp != CRCInput::RC_timeout) + g_RCInput->postMsg(tmp, data); + } else + do_vol = true; if (CNeutrinoApp::getInstance()->isMuted() && (dir > 0 || g_settings.current_volume > 0)) { hideVolscale(); - CAudioMute::getInstance()->AudioMute(false, true); - setVolume(msg); - return; + if (do_vol) { + CAudioMute::getInstance()->AudioMute(false, true); + setVolume(msg); + return; + } } - if (!CNeutrinoApp::getInstance()->isMuted()) { + if (do_vol && !CNeutrinoApp::getInstance()->isMuted()) { /* current_volume is char, we need signed to catch v < 0 */ int v = g_settings.current_volume; v += dir * g_settings.current_volume_step; @@ -145,7 +167,8 @@ void CVolume::setVolume(const neutrino_msg_t key) break; } - setvol(g_settings.current_volume); + if (do_vol) + setvol(g_settings.current_volume); timeoutEnd = CRCInput::calcTimeoutEnd (g_settings.timing[SNeutrinoSettings::TIMING_VOLUMEBAR] == 0 ? 0xFFFF : g_settings.timing[SNeutrinoSettings::TIMING_VOLUMEBAR]); } else if (msg == NeutrinoMessages::EVT_VOLCHANGED) { diff --git a/src/drivertool.c b/src/drivertool.c index 80432d776..c36e681bc 100644 --- a/src/drivertool.c +++ b/src/drivertool.c @@ -138,8 +138,8 @@ static struct ioctl_list n[] = { static const char *devices[2] = { - "/dev/cs_display", - "/dev/cs_ir" + "/dev/display", + "/dev/input/nevis_ir" }; void usage(void) @@ -235,7 +235,9 @@ int main(int argc, char **argv) } ret = 0; - while (n[i].text != NULL && strcmp(n[i].text, argv[1]) != 0) + /* allow the old VFD_ names for backwards compatibility */ + while (n[i].text != NULL && strcmp(n[i].text, argv[1]) != 0 && + !(strncmp(argv[1], "VFD_", 4) == 0 && strcmp(n[i].text + 2, argv[1] + 3) == 0)) i++; if (!n[i].text || (n[i].type != TYPE_UINT_GET && argc < 3)) diff --git a/src/eitd/SIevents.cpp b/src/eitd/SIevents.cpp index 32ef385d5..e57e96ee9 100644 --- a/src/eitd/SIevents.cpp +++ b/src/eitd/SIevents.cpp @@ -359,12 +359,12 @@ void SIevent::parseShortEventDescriptor(const uint8_t *buf, unsigned maxlen) int tsidonid = (transport_stream_id << 16) | original_network_id; - char lang[] = {'\0','\0','\0','\0'}; + char lang[4]; lang[0] = tolower(evt->language_code_hi); lang[1] = tolower(evt->language_code_mid); lang[2] = tolower(evt->language_code_lo); - - std::string language(lang); + lang[3] = '\0'; + std::string language(lang); int table = getCountryCodeDefaultMapping(language); unsigned int _language = getLangIndex(language); @@ -387,11 +387,11 @@ void SIevent::parseExtendedEventDescriptor(const uint8_t *buf, unsigned maxlen) int tsidonid = (transport_stream_id << 16) | original_network_id; - char lang[] = {'\0','\0','\0','\0'}; + char lang[4]; lang[0] = tolower(evt->iso_639_2_language_code_hi); lang[1] = tolower(evt->iso_639_2_language_code_mid); lang[2] = tolower(evt->iso_639_2_language_code_lo); - + lang[3] = '\0'; std::string language(lang); int table = getCountryCodeDefaultMapping(language); unsigned int _language = getLangIndex(language); diff --git a/src/eitd/dmx.cpp b/src/eitd/dmx.cpp index 6bd9871ad..a95713807 100644 --- a/src/eitd/dmx.cpp +++ b/src/eitd/dmx.cpp @@ -47,7 +47,8 @@ //#define DEBUG_DEMUX 1 // debug start/close/change //#define DEBUG_CACHED_SECTIONS 1 //#define DEBUG_COMPLETE_SECTIONS 1 -#define DEBUG_COMPLETE 1 +//#define DEBUG_COMPLETE 1 +//#define DEBUG_SKIP_LOOPED 1 //static MyDMXOrderUniqueKey myDMXOrderUniqueKey; @@ -120,9 +121,13 @@ void DMX::closefd(void) #endif if (isOpen()) { - //dmx->Stop(); +#if HAVE_TRIPLEDRAGON + /* not sure why, but we lose CN events if we do delete / new :-( */ + dmx->Stop(); +#else delete dmx; dmx = NULL; +#endif } } @@ -462,9 +467,11 @@ int DMX::getSection(uint8_t *buf, const unsigned timeoutInMSeconds, int &timeout #endif } //debug +#ifdef DEBUG_SKIP_LOOPED if(timeouts == -1) { xcprintf(" %s: skipped looped", name.c_str()); } +#endif if(complete) { seenSections.clear(); diff --git a/src/eitd/dmx.h b/src/eitd/dmx.h index abecc1d7b..5444b3bf9 100644 --- a/src/eitd/dmx.h +++ b/src/eitd/dmx.h @@ -32,8 +32,8 @@ #if HAVE_COOL_HARDWARE #include #endif -#if HAVE_TRIPLEDRAGON -#include +#if USE_STB_HAL +#include #endif #include @@ -68,7 +68,16 @@ protected: bool seen_section; inline bool isOpen(void) { +#if HAVE_TRIPLEDRAGON + /* unfortunately, this is a bit complicated on TD :-( */ + if (dmx == NULL) + return false; + if (dmx->getBuffer() != NULL) /* getBuffer() is a dummy to indicate that demux is running */ + return true; + return false; +#else return (dmx != NULL); +#endif } int immediate_start(void); /* mutex must be locked before and unlocked after this method */ diff --git a/src/eitd/eitd.h b/src/eitd/eitd.h index 9018b4b2c..8d2c579c9 100644 --- a/src/eitd/eitd.h +++ b/src/eitd/eitd.h @@ -114,6 +114,8 @@ class CSectionThread : public OpenThreads::Thread, public DMX int skipTime; bool sendToSleepNow; + std::string threadName; + /* should thread wait for time set before process loop */ bool wait_for_time; /* time in seconds to sleep when requested, wait forever if 0 */ @@ -296,7 +298,7 @@ class CTimeThread : public CSectionThread OpenThreads::Condition time_cond; void sendTimeEvent(bool dvb, time_t tim = 0); - void setSystemTime(time_t tim); + bool setSystemTime(time_t tim, bool force = false); void run(); public: CTimeThread(); diff --git a/src/eitd/sectionsd.cpp b/src/eitd/sectionsd.cpp index 532b61a0c..53b43bcae 100644 --- a/src/eitd/sectionsd.cpp +++ b/src/eitd/sectionsd.cpp @@ -5,7 +5,7 @@ * Copyright (C) 2001 by fnbrd (fnbrd@gmx.de) * Homepage: http://dbox2.elxsi.de * - * Copyright (C) 2008-2013 Stefan Seyfried + * Copyright (C) 2008-2016 Stefan Seyfried * * Copyright (C) 2011-2012 CoolStream International Ltd * @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "eitd.h" @@ -59,7 +60,7 @@ //#define DEBUG_SDT_THREAD //#define DEBUG_TIME_THREAD -#define DEBUG_SECTION_THREADS +//#define DEBUG_SECTION_THREADS //#define DEBUG_CN_THREAD /*static*/ bool reader_ready = true; @@ -149,10 +150,15 @@ static CFreeSatThread threadFSEIT; CSdtThread threadSDT; #endif +#ifdef DEBUG_EVENT_LOCK +static time_t lockstart = 0; +#endif + static int sectionsd_stop = 0; static bool slow_addevent = true; + inline void readLockServices(void) { pthread_rwlock_rdlock(&servicesLock); @@ -191,10 +197,21 @@ inline void readLockEvents(void) inline void writeLockEvents(void) { pthread_rwlock_wrlock(&eventsLock); +#ifdef DEBUG_EVENT_LOCK + lockstart = time_monotonic_ms(); +#endif } inline void unlockEvents(void) { +#ifdef DEBUG_EVENT_LOCK + if (lockstart) { + time_t tmp = time_monotonic_ms() - lockstart; + if (tmp > 50) + xprintf("locked ms %d\n", tmp); + lockstart = 0; + } +#endif pthread_rwlock_unlock(&eventsLock); } @@ -215,10 +232,11 @@ static MySIeventUniqueKeysMetaOrderServiceUniqueKey mySIeventUniqueKeysMetaOrder static MySIservicesOrderUniqueKey mySIservicesOrderUniqueKey; static MySIservicesNVODorderUniqueKey mySIservicesNVODorderUniqueKey; +/* needs write lock held! */ static bool deleteEvent(const event_id_t uniqueKey) { bool ret = false; - writeLockEvents(); + // writeLockEvents(); MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(uniqueKey); if (e != mySIeventsOrderUniqueKey.end()) { @@ -234,7 +252,7 @@ static bool deleteEvent(const event_id_t uniqueKey) mySIeventsNVODorderUniqueKey.erase(uniqueKey); ret = true; } - unlockEvents(); + // unlockEvents(); return ret; } @@ -321,7 +339,7 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann unlockMessaging(); } - readLockEvents(); + writeLockEvents(); MySIeventsOrderUniqueKey::iterator si = mySIeventsOrderUniqueKey.find(evt.uniqueKey()); bool already_exists = (si != mySIeventsOrderUniqueKey.end()); if (already_exists && (evt.table_id < si->second->table_id)) @@ -444,26 +462,29 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann delete eptr; return; } + /* SRF special case: advertising is inserted with start time of + * an existing event. Duration may differ. To avoid holes in EPG caused + * by the (not useful) advertising event, don't delete the (useful) + * original event */ + if ((*x)->table_id == e->table_id && (e->table_id & 0xFE) == 0x4e && + (*x)->times.begin()->startzeit == start_time) + continue; /* here we have an overlapping event */ dprintf("%s: delete 0x%012" PRIx64 ".%02x time = 0x%012" PRIx64 ".%02x\n", __func__, x_key, (*x)->table_id, e_key, e->table_id); to_delete.push_back(x_key); } } - unlockEvents(); while (! to_delete.empty()) { deleteEvent(to_delete.back()); to_delete.pop_back(); } - } else { - // Damit in den nicht nach Event-ID sortierten Mengen - // Mehrere Events mit gleicher ID sind, diese vorher loeschen - unlockEvents(); } + // Damit in den nicht nach Event-ID sortierten Mengen + // Mehrere Events mit gleicher ID sind, diese vorher loeschen deleteEvent(e->uniqueKey()); - readLockEvents(); if ( !mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) { MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); @@ -498,12 +519,8 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann } event_id_t uniqueKey = (*lastEvent)->uniqueKey(); // else fprintf(stderr, ">"); - unlockEvents(); deleteEvent(uniqueKey); } - else - unlockEvents(); - readLockEvents(); // Pruefen ob es ein Meta-Event ist MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator i = mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(e->get_channel_id()); @@ -523,9 +540,6 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann // Falls das Event in den beiden Mengen mit Zeiten nicht vorhanden // ist, dieses dort einfuegen MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator i2 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(ie->second); - unlockEvents(); - writeLockEvents(); - if (i2 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) { // nicht vorhanden -> einfuegen @@ -538,8 +552,6 @@ xprintf("addEvent: ch %012" PRIx64 " running %d (%s) got_CN %d\n", evt.get_chann } } } - unlockEvents(); - writeLockEvents(); // printf("Adding: %04x\n", (int) e->uniqueKey()); // normales Event @@ -567,22 +579,18 @@ static void addNVODevent(const SIevent &evt) SIeventPtr e(eptr); - readLockEvents(); + writeLockEvents(); MySIeventsOrderUniqueKey::iterator e2 = mySIeventsOrderUniqueKey.find(e->uniqueKey()); if (e2 != mySIeventsOrderUniqueKey.end()) { // bisher gespeicherte Zeiten retten - unlockEvents(); - writeLockEvents(); e->times.insert(e2->second->times.begin(), e2->second->times.end()); } - unlockEvents(); // Damit in den nicht nach Event-ID sortierten Mengen // mehrere Events mit gleicher ID sind, diese vorher loeschen deleteEvent(e->uniqueKey()); - readLockEvents(); if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) { //TODO: Set Old Events to 0 if limit is reached... MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = @@ -596,24 +604,18 @@ static void addNVODevent(const SIevent &evt) --lastEvent; } unlockMessaging(); - unlockEvents(); deleteEvent((*lastEvent)->uniqueKey()); } - else - unlockEvents(); - writeLockEvents(); mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); mySIeventsNVODorderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); - unlockEvents(); if (!e->times.empty()) { // diese beiden Mengen enthalten nur Events mit Zeiten - writeLockEvents(); mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e); mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e); - unlockEvents(); } + unlockEvents(); } static void removeOldEvents(const long seconds) @@ -623,7 +625,7 @@ static void removeOldEvents(const long seconds) // Alte events loeschen time_t zeit = time(NULL); - readLockEvents(); + writeLockEvents(); unsigned total_events = mySIeventsOrderUniqueKey.size(); MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); @@ -642,10 +644,9 @@ static void removeOldEvents(const long seconds) to_delete.push_back((*e)->uniqueKey()); ++e; } - unlockEvents(); - for (std::vector::iterator i = to_delete.begin(); i != to_delete.end(); ++i) deleteEvent(*i); + unlockEvents(); readLockEvents(); xprintf("[sectionsd] Removed %d old events (%d left), zap detected %d.\n", (int)(total_events - mySIeventsOrderUniqueKey.size()), (int)mySIeventsOrderUniqueKey.size(), messaging_zap_detected); @@ -1381,7 +1382,7 @@ void CTimeThread::waitForTimeset(void) time_mutex.unlock(); } -void CTimeThread::setSystemTime(time_t tim) +bool CTimeThread::setSystemTime(time_t tim, bool force) { struct timeval tv; struct tm t; @@ -1389,6 +1390,7 @@ void CTimeThread::setSystemTime(time_t tim) gettimeofday(&tv, NULL); timediff = int64_t(tim * 1000000 - (tv.tv_usec + tv.tv_sec * 1000000)); localtime_r(&tv.tv_sec, &t); + int absdiff = abs(tim - tv.tv_sec); xprintf("%s: timediff %" PRId64 ", current: %02d.%02d.%04d %02d:%02d:%02d, dvb: %s", name.c_str(), timediff, @@ -1400,9 +1402,9 @@ void CTimeThread::setSystemTime(time_t tim) return; } #endif - if (timediff == 0) /* very unlikely... :-) */ - return; - if (timeset && abs(tim - tv.tv_sec) < 120) { /* abs() is int */ + if (absdiff < 1) /* do not bother for differences less than one second */ + return true; + if (absdiff < 120) { struct timeval oldd; tv.tv_sec = time_t(timediff / 1000000LL); tv.tv_usec = suseconds_t(timediff % 1000000LL); @@ -1412,14 +1414,21 @@ void CTimeThread::setSystemTime(time_t tim) xprintf("difference is < 120s, using adjtime(%d, %d). oldd(%d, %d)\n", (int)tv.tv_sec, (int)tv.tv_usec, (int)oldd.tv_sec, (int)oldd.tv_usec); timediff = 0; - return; + return true; } + } else if (timeset && ! force) { + xprintf("difference is > 120s, try again and set 'force=true'\n"); + return false; } + /* still fall through if adjtime() failed */ tv.tv_sec = tim; tv.tv_usec = 0; - if (settimeofday(&tv, NULL) < 0) - perror("[sectionsd] settimeofday"); + if (settimeofday(&tv, NULL) == 0) + return true; + + perror("[sectionsd] settimeofday"); + return false; } void CTimeThread::addFilters() @@ -1431,8 +1440,10 @@ void CTimeThread::addFilters() void CTimeThread::run() { time_t dvb_time = 0; + bool retry = false; /* if time seems fishy, set to true and try again */ xprintf("%s::run:: starting, pid %d (%lu)\n", name.c_str(), getpid(), pthread_self()); - + threadName = "sd:" + name; + set_threadname(threadName.c_str()); addFilters(); DMX::start(); @@ -1474,7 +1485,21 @@ void CTimeThread::run() xprintf("%s: get DVB time ch 0x%012" PRIx64 " (isOpen %d)\n", name.c_str(), current_service, isOpen()); - int rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds); + int rc; +#if HAVE_COOL_HARDWARE + /* libcoolstream does not like the repeated read if the dmx is not yet running + * (e.g. during neutrino start) and causes strange openthreads errors which in + * turn cause complete malfunction of the dmx, so we cannot use the "speed up + * shutdown" hack on with libcoolstream... :-( */ + rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds); +#else + time_t start = time_monotonic_ms(); + /* speed up shutdown by looping around Read() */ + do { + rc = dmx->Read(static_buf, MAX_SECTION_LENGTH, timeoutInMSeconds / 12); + } while (running && rc == 0 + && (time_monotonic_ms() - start) < (time_t)timeoutInMSeconds); +#endif xprintf("%s: get DVB time ch 0x%012" PRIx64 " rc: %d neutrino_sets_time %d\n", name.c_str(), current_service, rc, messaging_neutrino_sets_time); if (rc > 0) { @@ -1489,7 +1514,14 @@ void CTimeThread::run() sleep_time = ntprefresh * 60; if(success) { if(dvb_time) { - setSystemTime(dvb_time); + bool ret = setSystemTime(dvb_time, retry); + if (! ret) { + xprintf("%s: time looks wrong, trying again\n", name.c_str()); + sendToSleepNow = false; + retry = true; + continue; + } + retry = false; /* retry a second time immediately after start, to get TOT ? */ if(first_time) sleep_time = 5; @@ -1546,6 +1578,8 @@ int CSectionThread::Sleep() void CSectionThread::run() { xprintf("%s::run:: starting, pid %d (%lu)\n", name.c_str(), getpid(), pthread_self()); + threadName = "sd:" + name; + set_threadname(threadName.c_str()); if (sections_debug) dump_sched_info(name); @@ -2078,10 +2112,14 @@ static void *houseKeepingThread(void *) count = 0; } - int rc = HOUSEKEEPING_SLEEP; + int i = HOUSEKEEPING_SLEEP; - while (rc) - rc = sleep(rc); + while (i > 0 && !sectionsd_stop) { + sleep(1); + i--; + } + if (sectionsd_stop) + break; if (!scanning) { scount++; @@ -2210,6 +2248,7 @@ void CEitManager::run() int rc; xprintf("[sectionsd] starting\n"); + set_threadname("sd:eitmanager"); printf("SIevent size: %d\n", (int)sizeof(SIevent)); /* "export NO_SLOW_ADDEVENT=true" to disable this */ @@ -2292,7 +2331,12 @@ printf("SIevent size: %d\n", (int)sizeof(SIevent)); xprintf("pausing...\n"); + /* sometimes, pthread_cancel seems to not work, maybe it is a bad idea to mix + * plain pthread and OpenThreads? */ + sectionsd_stop = 1; pthread_cancel(threadHouseKeeping); + xprintf("join Housekeeping\n"); + pthread_join(threadHouseKeeping, NULL); xprintf("join TOT\n"); threadTIME.Stop(); @@ -2789,7 +2833,7 @@ void CEitManager::getChannelEvents(CChannelEventList &eList, t_channel_id *chidl bool found_already = true; time_t azeit = time(NULL); -showProfiling("sectionsd_getChannelEvents start"); + // showProfiling("sectionsd_getChannelEvents start"); readLockEvents(); /* !!! FIX ME: if the box starts on a channel where there is no EPG sent, it hangs!!! */ @@ -2833,7 +2877,7 @@ showProfiling("sectionsd_getChannelEvents start"); } } -showProfiling("sectionsd_getChannelEvents end"); + // showProfiling("sectionsd_getChannelEvents end"); unlockEvents(); } diff --git a/src/eitd/xmlutil.cpp b/src/eitd/xmlutil.cpp index 23a73d4ff..adfcebb08 100644 --- a/src/eitd/xmlutil.cpp +++ b/src/eitd/xmlutil.cpp @@ -621,7 +621,7 @@ _done: filename = (std::string)epgdir + "/index.xml"; rename(tmpname.c_str(), filename.c_str()); - sync(); + // sync(); printf("[sectionsd] Writing Information finished\n"); return ; } diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 3126b8156..1a2377152 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -108,7 +108,6 @@ libneutrino_gui_a_SOURCES = \ timeosd.cpp \ tmdb.cpp \ update.cpp \ - update_ext.cpp \ update_menue.cpp \ update_settings.cpp \ user_menue.cpp \ @@ -119,6 +118,11 @@ libneutrino_gui_a_SOURCES = \ webtv_setup.cpp \ zapit_setup.cpp +if ENABLE_EXTUPDATE +libneutrino_gui_a_SOURCES += \ + update_ext.cpp +endif + if ENABLE_TESTING libneutrino_gui_a_SOURCES += \ test_menu.cpp diff --git a/src/gui/audio_setup.cpp b/src/gui/audio_setup.cpp index 27f8cb3a4..48d4f8637 100644 --- a/src/gui/audio_setup.cpp +++ b/src/gui/audio_setup.cpp @@ -116,11 +116,17 @@ const CMenuOptionChooser::keyval AUDIOMENU_AVSYNC_OPTIONS[AUDIOMENU_AVSYNC_OPTIO { 2, LOCALE_AUDIOMENU_AVSYNC_AM } }; +#ifdef HAVE_SPARK_HARDWARE +#define AUDIOMENU_HDMI_DD_OPTION_COUNT 2 +#else #define AUDIOMENU_HDMI_DD_OPTION_COUNT 3 +#endif const CMenuOptionChooser::keyval AUDIOMENU_HDMI_DD_OPTIONS[AUDIOMENU_HDMI_DD_OPTION_COUNT] = { { HDMI_ENCODED_OFF, LOCALE_OPTIONS_OFF }, +#ifndef HAVE_SPARK_HARDWARE { HDMI_ENCODED_AUTO, LOCALE_AUDIOMENU_HDMI_DD_AUTO }, +#endif { HDMI_ENCODED_FORCED, LOCALE_AUDIOMENU_HDMI_DD_FORCE } }; @@ -148,8 +154,11 @@ int CAudioSetup::showAudioSetup() as_oj_ddsubchn->setHint("", LOCALE_MENU_HINT_AUDIO_DD); //dd via hdmi - CMenuOptionChooser * as_oj_dd_hdmi = new CMenuOptionChooser(LOCALE_AUDIOMENU_HDMI_DD, &g_settings.hdmi_dd, AUDIOMENU_HDMI_DD_OPTIONS, AUDIOMENU_HDMI_DD_OPTION_COUNT, true, audioSetupNotifier); - as_oj_dd_hdmi->setHint("", LOCALE_MENU_HINT_AUDIO_HDMI_DD); + CMenuOptionChooser *as_oj_dd_hdmi = NULL; + if (g_info.hw_caps->has_HDMI) { + as_oj_dd_hdmi = new CMenuOptionChooser(LOCALE_AUDIOMENU_HDMI_DD, &g_settings.hdmi_dd, AUDIOMENU_HDMI_DD_OPTIONS, AUDIOMENU_HDMI_DD_OPTION_COUNT, true, audioSetupNotifier); + as_oj_dd_hdmi->setHint("", LOCALE_MENU_HINT_AUDIO_HDMI_DD); + } //dd via spdif CMenuOptionChooser * as_oj_dd_spdif = new CMenuOptionChooser(LOCALE_AUDIOMENU_SPDIF_DD, &g_settings.spdif_dd, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, audioSetupNotifier); @@ -173,6 +182,8 @@ int CAudioSetup::showAudioSetup() //CMenuOptionChooser * as_oj_clockrec new CMenuOptionChooser(LOCALE_AUDIOMENU_CLOCKREC, &g_settings.clockrec, AUDIOMENU_CLOCKREC_OPTIONS, AUDIOMENU_CLOCKREC_OPTION_COUNT, true, audioSetupNotifier); } +#if HAVE_COOL_HARDWARE + /* only coolstream has SRS stuff, so only compile it there */ //SRS //SRS algo CMenuOptionChooser * as_oj_algo = new CMenuOptionChooser(LOCALE_AUDIO_SRS_ALGO, &g_settings.srs_algo, AUDIOMENU_SRS_OPTIONS, AUDIOMENU_SRS_OPTION_COUNT, g_settings.srs_enable, audioSetupNotifier); @@ -190,6 +201,7 @@ int CAudioSetup::showAudioSetup() CTruVolumeNotifier truevolSetupNotifier(as_oj_algo, as_oj_noise, as_oj_volrev); CMenuOptionChooser * as_oj_srsonoff = new CMenuOptionChooser(LOCALE_AUDIO_SRS_IQ, &g_settings.srs_enable, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, &truevolSetupNotifier); as_oj_srsonoff->setHint("", LOCALE_MENU_HINT_AUDIO_SRS); +#endif // ac3,pcm and clear volume adjustment CMenuOptionNumberChooser *adj_ac3 = NULL, *adj_pcm = NULL; @@ -214,7 +226,8 @@ int CAudioSetup::showAudioSetup() audioSettings->addItem(as_oj_analogmode); audioSettings->addItem(GenericMenuSeparatorLine); //--------------------------------------------------------- - audioSettings->addItem(as_oj_dd_hdmi); + if (g_info.hw_caps->has_HDMI) + audioSettings->addItem(as_oj_dd_hdmi); audioSettings->addItem(as_oj_dd_spdif); audioSettings->addItem(as_oj_ddsubchn); //--------------------------------------------------------- @@ -226,6 +239,8 @@ int CAudioSetup::showAudioSetup() //audioSettings->addItem(as_clockrec); } //--------------------------------------------------------- +#if HAVE_COOL_HARDWARE + /* only coolstream has SRS stuff, so only compile it there */ audioSettings->addItem(GenericMenuSeparatorLine); audioSettings->addItem(as_oj_srsonoff); audioSettings->addItem(as_oj_algo); @@ -233,6 +248,7 @@ int CAudioSetup::showAudioSetup() audioSettings->addItem(as_oj_noise); #endif audioSettings->addItem(as_oj_volrev); +#endif #if 0 audioSettings->addItem(mf); #endif diff --git a/src/gui/audiomute.cpp b/src/gui/audiomute.cpp index fbc68e88e..d1c1885bf 100644 --- a/src/gui/audiomute.cpp +++ b/src/gui/audiomute.cpp @@ -35,6 +35,8 @@ #include #include +#include + CAudioMute::CAudioMute():CComponentsPicture(0, 0, NEUTRINO_ICON_BUTTON_MUTE) { y_old = -1; diff --git a/src/gui/audioplayer.cpp b/src/gui/audioplayer.cpp index 9ca823595..31b358c84 100644 --- a/src/gui/audioplayer.cpp +++ b/src/gui/audioplayer.cpp @@ -5,6 +5,7 @@ (C) 2002-2008 the tuxbox project contributors (C) 2008 Novell, Inc. Author: Stefan Seyfried + (C) 2011-2013 Stefan Seyfried Homepage: http://dbox.cyberphoria.org/ @@ -29,8 +30,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #ifdef HAVE_CONFIG_H @@ -47,6 +47,7 @@ #include #include #include +#include #include diff --git a/src/gui/bedit/bouqueteditor_channels.cpp b/src/gui/bedit/bouqueteditor_channels.cpp index 88ae91ab2..68a612493 100644 --- a/src/gui/bedit/bouqueteditor_channels.cpp +++ b/src/gui/bedit/bouqueteditor_channels.cpp @@ -160,14 +160,14 @@ void CBEChannelWidget::paint() frameBuffer->paintBoxRel(x+ width- 15,ypos, 15, sb, COL_MENUCONTENT_PLUS_1); int sbc= ((Channels->size()- 1)/ listmaxshow)+ 1; + int sbs= (selected/listmaxshow); if (sbc < 1) sbc = 1; - int sbh= (sb- 4)/ sbc; - int sbs= (selected/listmaxshow); - if (sbh) - frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ int(sbs* sbh) , 11, int(sbh), COL_MENUCONTENT_PLUS_3); + if (sbh == 0) + return; + frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ sbs * sbh, 11, sbh, COL_MENUCONTENT_PLUS_3); } void CBEChannelWidget::paintHead() @@ -271,7 +271,7 @@ void CBEChannelWidget::clearItem2DetailsLine() void CBEChannelWidget::hide() { frameBuffer->paintBackgroundBoxRel(x,y, width,height+footerHeight); - clearItem2DetailsLine (); + clearItem2DetailsLine (); } void CBEChannelWidget::updateSelection(unsigned int newpos) diff --git a/src/gui/bookmarkmanager.cpp b/src/gui/bookmarkmanager.cpp index bcbe278cb..93f7abbc8 100644 --- a/src/gui/bookmarkmanager.cpp +++ b/src/gui/bookmarkmanager.cpp @@ -37,7 +37,7 @@ #include #include #include - +#include #include #include #include @@ -252,8 +252,8 @@ const CBookmark * CBookmarkManager::getBookmark(CMenuTarget* parent) int res = -1; uint64_t timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_MENU] == 0 ? 0xFFFF : g_settings.timing[SNeutrinoSettings::TIMING_MENU]); - uint32_t msg; - uint32_t data; + neutrino_msg_t msg; + neutrino_msg_data_t data; bool loop=true; bool update=true; diff --git a/src/gui/bouquetlist.cpp b/src/gui/bouquetlist.cpp index 53cdf23b1..d49efbd89 100644 --- a/src/gui/bouquetlist.cpp +++ b/src/gui/bouquetlist.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include diff --git a/src/gui/buildinfo.cpp b/src/gui/buildinfo.cpp index ca8a31e6d..a568eb140 100644 --- a/src/gui/buildinfo.cpp +++ b/src/gui/buildinfo.cpp @@ -33,6 +33,8 @@ #include #include +#include + using namespace std; CBuildInfo::CBuildInfo() : CComponentsWindow(0, 0, 700, 500, LOCALE_BUILDINFO_MENU, NEUTRINO_ICON_INFO) diff --git a/src/gui/cam_menu.cpp b/src/gui/cam_menu.cpp index 2ba4d8a19..ad93c60ba 100644 --- a/src/gui/cam_menu.cpp +++ b/src/gui/cam_menu.cpp @@ -374,7 +374,7 @@ int CCAMMenuHandler::handleCamMsg(const neutrino_msg_t msg, neutrino_msg_data_t char * tptr = sptr; int bpos = 0; for(int li = 0; li < slen; li++) { - if((tptr[li] == 0x8A) || ((bpos > 38) && (tptr[li] == 0x20)) ) { + if(((unsigned char)tptr[li] == 0x8A) || ((bpos > 38) && (tptr[li] == 0x20)) ) { bpos = 0; tptr[li] = 0; printf("CCAMMenuHandler::handleCamMsg: subtitle: %s\n", sptr); @@ -528,7 +528,7 @@ int CCAMMenuHandler::doMenu(int slot, CA_SLOT_TYPE slotType) g_Locale->getText(slotType == CA_SLOT_TYPE_CI ? LOCALE_CI_WAITING : LOCALE_SC_WAITING)); g_RCInput->getMsgAbsoluteTimeout (&msg, &data, &timeoutEnd); - printf("CCAMMenuHandler::doMenu: msg %x data %x\n", msg, data); + printf("CCAMMenuHandler::doMenu: msg %lx data %lx\n", msg, data); if (msg == CRCInput::RC_timeout) { printf("CCAMMenuHandler::doMenu: menu timeout\n"); hideHintBox(); diff --git a/src/gui/channellist.cpp b/src/gui/channellist.cpp index afa4586c4..5f6f355ae 100644 --- a/src/gui/channellist.cpp +++ b/src/gui/channellist.cpp @@ -482,7 +482,11 @@ void CChannelList::calcSize() if (g_settings.channellist_additional) width = full_width / 3 * 2; else + { + /* don't use 100% of screen if additional info / minitv is not used */ + full_width = full_width * 76 / 99; /* same width as the old code with my settings :-) */ width = full_width; + } // calculate height (the infobox below mainbox is handled outside height) if (g_settings.channellist_show_infobox) @@ -1083,10 +1087,12 @@ bool CChannelList::checkLockStatus(neutrino_msg_data_t data, bool pip) out: if (startvideo) { if(pip) { +#ifdef ENABLE_PIP if (CNeutrinoApp::getInstance()->StartPip((*chanlist)[selected]->getChannelID())) { calcSize(); paintBody(); } +#endif } else g_RemoteControl->startvideo(); return true; @@ -1159,7 +1165,9 @@ bool CChannelList::zapTo_ChannelID(const t_channel_id channel_id, bool force) bool CChannelList::showEmptyError() { if ((*chanlist).empty()) { - DisplayErrorMessage(g_Locale->getText(LOCALE_CHANNELLIST_NONEFOUND)); // UTF-8 + /* No error message when the frontend is only simulated */ + if (!getenv("SIMULATE_FE")) + DisplayErrorMessage(g_Locale->getText(LOCALE_CHANNELLIST_NONEFOUND)); // UTF-8 return true; } return false; @@ -1429,8 +1437,8 @@ CZapitChannel* CChannelList::getPrevNextChannel(int key, unsigned int &sl) } sl = cactive; channel = bouquetList->Bouquets[bactive]->channelList->getChannelFromIndex(cactive); - printf("CChannelList::getPrevNextChannel: selected %u total %d active bouquet %d total %d channel %x (%s)\n", - cactive, (*chanlist).size(), bactive, bsize, (int) channel, channel ? channel->getName().c_str(): ""); + printf("CChannelList::getPrevNextChannel: selected %d total %d active bouquet %d total %d channel %p (%s)\n", + (int)cactive, (int)(*chanlist).size(), bactive, bsize, channel, channel ? channel->getName().c_str(): ""); } else { if ((key == g_settings.key_quickzap_down) || (key == CRCInput::RC_left)) { if(sl == 0) diff --git a/src/gui/components/cc_frm.cpp b/src/gui/components/cc_frm.cpp index 6e2fc8920..82b214568 100644 --- a/src/gui/components/cc_frm.cpp +++ b/src/gui/components/cc_frm.cpp @@ -255,7 +255,7 @@ int CComponentsForm::genIndex() CComponentsItem* CComponentsForm::getCCItem(const uint& cc_item_id) { if (cc_item_id >= size()){ - dprintf(DEBUG_NORMAL, "[CComponentsForm] [%s - %d] Error: parameter cc_item_id = %u, out of range (size = %" PRIx32")...\n", __func__, __LINE__, cc_item_id, size()); + dprintf(DEBUG_NORMAL, "[CComponentsForm] [%s - %d] Error: parameter cc_item_id = %u, out of range (size = %zx)...\n", __func__, __LINE__, cc_item_id, size()); return NULL; } @@ -577,7 +577,7 @@ void CComponentsForm::setSelectedItem(int item_id) int id = item_id; if (id > (int)(count-1) || id < 0 || (count == 0)){ - dprintf(DEBUG_NORMAL, "[CComponentsForm] [%s - %d] invalid parameter item_id = %u, available items = %u, allowed values are: 0...%u! \n", __func__, + dprintf(DEBUG_NORMAL, "[CComponentsForm] [%s - %d] invalid parameter item_id = %u, available items = %zu, allowed values are: 0...%zu! \n", __func__, __LINE__, item_id, count, diff --git a/src/gui/components/cc_frm_footer.cpp b/src/gui/components/cc_frm_footer.cpp index a02d999b2..b40b4afba 100644 --- a/src/gui/components/cc_frm_footer.cpp +++ b/src/gui/components/cc_frm_footer.cpp @@ -137,7 +137,7 @@ void CComponentsFooter::setButtonLabels(const struct button_label_s * const cont //ignore item, if no text and icon are defined; if (txt.empty() && btn_name.empty()){ - dprintf(DEBUG_INFO, "[CComponentsFooter] [%s - %d] ignore item [%d], no icon and text defined!\n", __func__, __LINE__, i); + dprintf(DEBUG_INFO, "[CComponentsFooter] [%s - %d] ignore item [%zu], no icon and text defined!\n", __func__, __LINE__, i); continue; } @@ -178,7 +178,7 @@ void CComponentsFooter::setButtonLabels(const struct button_label_s * const cont int w_rest = max(w_chain - w_used, 0); int btn_offset = w_rest / chain->size(); chain->setAppendOffset(btn_offset, 0); - dprintf(DEBUG_INFO, "[CComponentsFooter] [%s - %d] btn_offset = %d, w_rest = %d, w_chain = %d, w_used = %d, chain->size() = %u\n", __func__, __LINE__, btn_offset, w_rest, w_chain, w_used, chain->size()); + dprintf(DEBUG_INFO, "[CComponentsFooter] [%s - %d] btn_offset = %d, w_rest = %d, w_chain = %d, w_used = %d, chain->size() = %zu\n", __func__, __LINE__, btn_offset, w_rest, w_chain, w_used, chain->size()); //set x position of 1st button object inside chain, this is centering button objects inside chain int x_1st_btn = btn_offset/2; diff --git a/src/gui/components/cc_frm_header.cpp b/src/gui/components/cc_frm_header.cpp index 3da54166d..3494c9c7c 100644 --- a/src/gui/components/cc_frm_header.cpp +++ b/src/gui/components/cc_frm_header.cpp @@ -302,7 +302,7 @@ void CComponentsHeader::addContextButton(const int& buttons) void CComponentsHeader::removeContextButtons() { - dprintf(DEBUG_DEBUG, "[CComponentsHeader]\t [%s - %d] removing %u context buttons...\n", __func__, __LINE__, v_cch_btn.size()); + dprintf(DEBUG_DEBUG, "[CComponentsHeader]\t [%s - %d] removing %zu context buttons...\n", __func__, __LINE__, v_cch_btn.size()); v_cch_btn.clear(); if (cch_btn_obj) cch_btn_obj->clear(); diff --git a/src/gui/components/cc_item_progressbar.cpp b/src/gui/components/cc_item_progressbar.cpp index fe41988fb..f676372e5 100644 --- a/src/gui/components/cc_item_progressbar.cpp +++ b/src/gui/components/cc_item_progressbar.cpp @@ -255,6 +255,7 @@ void CProgressBarCache::pbcPaint(int x, int y, int pbc_active_width, int pbc_pas ap += pbc_passive_width; p += off; } + frameBuffer->mark(x, y, x + pbc_width, y + pbc_height); } void CProgressBarCache::pbcPaintBoxRel(int x, int y, int dx, int dy, fb_pixel_t *pixbuf, fb_pixel_t col) diff --git a/src/gui/dboxinfo.cpp b/src/gui/dboxinfo.cpp index b909a5e05..2b5894f68 100644 --- a/src/gui/dboxinfo.cpp +++ b/src/gui/dboxinfo.cpp @@ -4,13 +4,7 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ - Kommentar: - - Diese GUI wurde von Grund auf neu programmiert und sollte nun vom - Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert - auf der Client-Server Idee, diese GUI ist also von der direkten DBox- - Steuerung getrennt. Diese wird dann von Daemons uebernommen. - + (C) 2009-2011, 2013-2014 Stefan Seyfried License: GPL @@ -339,6 +333,7 @@ void CDBoxInfoWidget::paint() //paint head std::string title(g_Locale->getText(LOCALE_EXTRA_DBOXINFO)); +#if 0 std::map cpuinfo; in.open("/proc/cpuinfo"); if (in.is_open()) { @@ -366,6 +361,17 @@ void CDBoxInfoWidget::paint() sprintf(ss, "%016llx", cs_get_serial()); title += ", S/N "; title += ss; +#endif + title += ": "; + title += g_info.hw_caps->boxvendor; + title += " "; + title += g_info.hw_caps->boxname; +#if HAVE_COOL_HARDWARE + title += " ("; + title += g_info.hw_caps->boxarch; + title += ") - "; + title += g_info.hw_caps->frontend; +#endif width = max(width, g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->getRenderWidth(title, true) + 50); #endif x = getScreenStartX(width); @@ -495,7 +501,6 @@ void CDBoxInfoWidget::paint() const int headSize = 5; int maxWidth[headSize]; memset(maxWidth, 0, headSize * sizeof(int)); - int ypos_mem_head = ypos; ypos += mheight; @@ -571,7 +576,7 @@ void CDBoxInfoWidget::paint() tmp = basename((char *)mnt); _w = nameWidth - mpOffset; if ((*it).second) - _w -= icon_w + 10; + _w -= icon_w; _w += width_i/2; break; case 1: diff --git a/src/gui/dboxinfo.h b/src/gui/dboxinfo.h index a78878570..5d92fa138 100644 --- a/src/gui/dboxinfo.h +++ b/src/gui/dboxinfo.h @@ -50,7 +50,7 @@ class CDBoxInfoWidget : public CMenuTarget int height; int hheight,mheight; // head/menu font height int fontWidth; - int sizeWidth; + int sizeWidth; // width of mem / disk sizes int percWidth; int nameWidth; diff --git a/src/gui/epgplus.cpp b/src/gui/epgplus.cpp index 94ab4af35..d84232a78 100644 --- a/src/gui/epgplus.cpp +++ b/src/gui/epgplus.cpp @@ -1239,11 +1239,10 @@ void EpgPlus::paint() this->frameBuffer->paintBoxRel (this->sliderX, this->sliderY, this->sliderWidth, this->sliderHeight, COL_MENUCONTENT_PLUS_0); int tmp = ((this->channelList->getSize() - 1) / this->maxNumberOfDisplayableEntries) + 1; - float sliderKnobHeight = float((sliderHeight - 4) / tmp); int sliderKnobPosition = this->selectedChannelEntry == NULL ? 0 : (this->selectedChannelEntry->index / this->maxNumberOfDisplayableEntries); - this->frameBuffer->paintBoxRel (this->sliderX + 2, this->sliderY + (int(sliderKnobPosition * sliderKnobHeight)) - , this->sliderWidth - 4, int (sliderKnobHeight) , COL_MENUCONTENT_PLUS_3); + this->frameBuffer->paintBoxRel(this->sliderX + 2, this->sliderY + sliderKnobPosition * (sliderHeight-4)/tmp + , this->sliderWidth - 4, (sliderHeight-4)/tmp, COL_MENUCONTENT_PLUS_3); } // -- EPG+ Menue Handler Class diff --git a/src/gui/epgview.cpp b/src/gui/epgview.cpp index aa78a4396..92977a507 100644 --- a/src/gui/epgview.cpp +++ b/src/gui/epgview.cpp @@ -898,9 +898,21 @@ int CEpgData::show(const t_channel_id channel_id, uint64_t a_id, time_t* a_start has_follow_screenings = true; } +/* merge conflict */ +#if 0 + /* neat for debugging duplicate event issues etc. */ + char *epgid; + if (asprintf(&epgid, "EPG ID:%04X.%02X", (int)((epgData.eventID)&0x0FFFF), epgData.table_id) >= 0) + { + processTextToArray(""); // UTF-8 + processTextToArray(epgid); + free(epgid); + } +#else // show extended movie info if (mp_info && !extMovieInfo.empty()) processTextToArray(extMovieInfo); +#endif COSDFader fader(g_settings.theme.menu_Content_alpha); fader.StartFadeIn(); @@ -1629,7 +1641,7 @@ void CEpgData::showTimerEventBar (bool pshow, bool adzap, bool mp_info) h = std::max(fh, icol_h+4); // hide only? - if (! pshow){ + if (! pshow) { frameBuffer->paintBackgroundBoxRel(sx,y,ox,h); return; } diff --git a/src/gui/filebrowser.cpp b/src/gui/filebrowser.cpp index a763d136f..8742295ff 100644 --- a/src/gui/filebrowser.cpp +++ b/src/gui/filebrowser.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -60,7 +61,7 @@ #include #ifndef __USE_FILE_OFFSET64 -#error not using 64 bit file offsets +//#error not using 64 bit file offsets #endif #define SMSKEY_TIMEOUT 2000 @@ -1436,7 +1437,7 @@ void CFileBrowser::paintSMSKey() if(m_SMSKeyInput.getOldKey()!=0) { - char cKey[2] = {m_SMSKeyInput.getOldKey(), 0}; + char cKey[2] = {(char)m_SMSKeyInput.getOldKey(), 0}; cKey[0] = toupper(cKey[0]); int len = fnt_foot->getRenderWidth(cKey); fnt_foot->RenderString(x + width - skwidth, y + height - foheight + foheight/2 + skheight/2, len, cKey, COL_MENUHEAD_TEXT); diff --git a/src/gui/hdd_menu.cpp b/src/gui/hdd_menu.cpp index f83812966..8c5dd1fb0 100644 --- a/src/gui/hdd_menu.cpp +++ b/src/gui/hdd_menu.cpp @@ -26,6 +26,7 @@ #include #endif +#include #include #include #include @@ -34,10 +35,12 @@ #include #include #include +#include +#include +#include #include #include #include -#include #include #include @@ -130,12 +133,20 @@ CHDDMenuHandler* CHDDMenuHandler::getInstance() int CHDDMenuHandler::filterDevName(const char * name) { - if ((name[0] == 's' && (name[1] == 'd' || name[1] == 'r')) || + if (((name[0] == 's' || name[0] == 'h') && (name[1] == 'd' || name[1] == 'r')) || !strncmp(name, "mmcblk", 6)) return 1; return 0; } +static string readlink(const char *path) +{ + char link[PATH_MAX + 1]; + if (realpath(path, link)) + return string(link); + return ""; +} + bool CHDDMenuHandler::is_mounted(const char *dev) { bool res = false; @@ -145,14 +156,25 @@ bool CHDDMenuHandler::is_mounted(const char *dev) else snprintf(devpath, sizeof(devpath), "/dev/%s", dev); - int devpathlen = strlen(devpath); char buffer[255]; + string realdev = readlink(devpath); + realdev = trim(realdev); FILE *f = fopen("/proc/mounts", "r"); if(f) { - while (!res && fgets(buffer, sizeof(buffer), f)) - if (!strncmp(buffer, devpath, devpathlen) - && (buffer[devpathlen] == ' ' || buffer[devpathlen] == '\t')) + while (!res && fgets(buffer, sizeof(buffer), f)) { + if (buffer[0] != '/') + continue; /* only "real" devices are interesting */ + char *p = strchr(buffer, ' '); + if (p) + *p = 0; /* terminate at first space, kernel-user ABI is fixed */ + if (!strcmp(buffer, devpath)) /* default '/dev/sda1' mount */ res = true; + else { /* now the case of '/dev/disk/by-label/myharddrive' mounts */ + string realmount = readlink(buffer); + if (realdev == trim(realmount)) + res = true; + } + } fclose(f); } printf("CHDDMenuHandler::is_mounted: dev [%s] is %s\n", devpath, res ? "mounted" : "not mounted"); @@ -162,7 +184,10 @@ bool CHDDMenuHandler::is_mounted(const char *dev) void CHDDMenuHandler::getBlkIds() { pid_t pid; - std::string pcmd = BLKID_BIN + (std::string)" -s TYPE"; + std::string blkid = find_executable("blkid"); + if (blkid.empty()) + return; + std::string pcmd = blkid + (std::string)" -s TYPE"; FILE* f = my_popen(pid, pcmd.c_str(), "r"); if (!f) { @@ -223,9 +248,36 @@ std::string CHDDMenuHandler::getFmtType(std::string name, std::string part) return ret; } +void CHDDMenuHandler::check_kernel_fs() +{ + char line[128]; /* /proc/filesystems lines are shorter */ + kernel_fs_list.clear(); + FILE *f = fopen("/proc/filesystems", "r"); + if (! f) { + fprintf(stderr, "CHDDMenuHandler::%s: opening /proc/filesystems failed: %m\n", __func__); + return; + } + while (fgets(line, sizeof(line), f)) { + size_t l = strlen(line); + if (l > 0) + line[l - 1] = 0; /* remove \n */ + char *tab = strchr(line, '\t'); + if (! tab) /* should not happen in any kernel I have seen */ + continue; + tab++; + kernel_fs_list.insert(string(tab)); + } + fclose(f); +} + void CHDDMenuHandler::check_dev_tools() { for (unsigned i = 0; i < FS_MAX; i++) { + if (kernel_fs_list.find(devtools[i].fmt) == kernel_fs_list.end()) { + printf("%s: filesystem '%s' not supported by kernel\n", + __func__, devtools[i].fmt.c_str()); + continue; + } if (!access(devtools[i].fsck.c_str(), X_OK)) devtools[i].fsck_supported = true; if (!access(devtools[i].mkfs.c_str(), X_OK)) @@ -372,7 +424,7 @@ void CHDDMenuHandler::setRecordPath(std::string &dev) return; } /* don't annoy if the recordingdir is a symlink pointing to the 'right' location */ - string readl = backtick("readlink -f " + g_settings.network_nfs_recordingdir); + string readl = readlink(g_settings.network_nfs_recordingdir.c_str()); readl = trim(readl); if (newpath.compare(readl) == 0) { printf("CHDDMenuHandler::%s: recordingdir is a symlink to %s\n", @@ -605,8 +657,14 @@ bool CHDDMenuHandler::scanDevices() perror("CHDDMenuHandler::scanDevices: scandir(\"/sys/block\") failed"); return false; } + + int drive_mask = 0xfff0; if (stat("/", &s) != -1) - root_dev = (s.st_dev & 0x0ffc0); /* hda = 0x0300, hdb = 0x0340 */ + { + if ((s.st_dev & drive_mask) == 0x0300) /* hda, hdb,... has max 63 partitions */ + drive_mask = 0xffc0; /* hda: 0x0300, hdb: 0x0340, sda: 0x0800, sdb: 0x0810 */ + root_dev = (s.st_dev & drive_mask); + } printf("HDD: root_dev: 0x%04x\n", root_dev); for(int i = 0; i < n;i++) { @@ -615,6 +673,7 @@ bool CHDDMenuHandler::scanDevices() char model[128] = { 0 }; int64_t bytes = 0; int64_t megabytes; + bool oldkernel = false; bool isroot = false; printf("HDD: checking /sys/block/%s\n", namelist[i]->d_name); @@ -626,7 +685,7 @@ bool CHDDMenuHandler::scanDevices() int ret = fstat(fd, &s); if (ret != -1) { - if ((int)(s.st_rdev & 0x0ffc0) == root_dev) { + if ((int)(s.st_rdev & drive_mask) == root_dev) { isroot = true; /* dev_t is different sized on different architectures :-( */ printf("-> root device is on this disk 0x%04x, skipping\n", (int)s.st_rdev); @@ -651,9 +710,16 @@ bool CHDDMenuHandler::scanDevices() if (f) { fscanf(f, "%s", vendor); fclose(f); + } else { + oldkernel = true; + strcpy(vendor, ""); } - snprintf(str, sizeof(str), "/sys/block/%s/device/model", namelist[i]->d_name); + /* the Tripledragon only has kernel 2.6.12 available.... :-( */ + if (oldkernel) + snprintf(str, sizeof(str), "/proc/ide/%s/model", namelist[i]->d_name); + else + snprintf(str, sizeof(str), "/sys/block/%s/device/model", namelist[i]->d_name); f = fopen(str, "r"); if(!f) { printf("Cant open %s\n", str); @@ -703,6 +769,7 @@ int CHDDMenuHandler::doMenu() show_menu = false; in_menu = true; + check_kernel_fs(); check_dev_tools(); _show_menu: @@ -776,9 +843,11 @@ _show_menu: } if (!hdd_list.empty()) { - struct stat rec_st; + struct stat rec_st, root_st, dev_st; memset(&rec_st, 0, sizeof(rec_st)); + memset(&root_st, 0, sizeof(root_st)); stat(g_settings.network_nfs_recordingdir.c_str(), &rec_st); + stat("/", &root_st); sort(hdd_list.begin(), hdd_list.end(), cmp_hdd_by_name()); mount = g_Locale->getText(LOCALE_HDD_MOUNT); @@ -794,6 +863,13 @@ _show_menu: } std::string key = "m" + it->devname; bool enabled = !rec_icon || !CNeutrinoApp::getInstance()->recordingstatus; + /* do not allow to unmount the rootfs, and skip filesystems without kernel support */ + memset(&dev_st, 0, sizeof(dev_st)); + if (stat(("/dev/" + it->devname).c_str(), &dev_st) != -1 + && dev_st.st_rdev == root_st.st_dev) + enabled = false; + else if (kernel_fs_list.find(it->fmt) == kernel_fs_list.end()) + enabled = false; it->cmf = new CMenuForwarder(it->desc, enabled, it->mounted ? umount : mount , this, key.c_str(), CRCInput::convertDigitToKey(shortcut++), NULL, rec_icon); hddmenu->addItem(it->cmf); @@ -813,6 +889,133 @@ _show_menu: return ret; } +#if 0 +static int dev_umount(char *dev) +{ + char buffer[255]; + FILE *f = fopen("/proc/mounts", "r"); + if(f == NULL) + return -1; + while (fgets (buffer, 255, f) != NULL) { + char *p = buffer + strlen(dev); + if (strstr(buffer, dev) == buffer && *p == ' ') { + p++; + char *q = strchr(p, ' '); + if (q == NULL) + continue; + *q = 0x0; + fclose(f); + printf("dev_umount %s: umounting %s\n", dev, p); + return umount(p); + } + } +#ifndef ASSUME_MDEV + /* with mdev, we hopefully don't have to umount anything here... */ + printf("dev_umount %s: not found\n", dev); +#endif + errno = ENOENT; + fclose(f); + return -1; +} + +/* unmounts all partitions of a given block device, dev can be /dev/sda, sda or sda4 */ +static int umount_all(const char *dev) +{ + char buffer[255]; + int i; + char *d = strdupa(dev); + char *p = d + strlen(d) - 1; + while (isdigit(*p)) + p--; + *++p = 0x0; + if (strstr(d, "/dev/") == d) + d += strlen("/dev/"); + printf("HDD: %s dev = '%s' d = '%s'\n", __func__, dev, d); + for (i = 1; i < 16; i++) + { + sprintf(buffer, "/dev/%s%d", d, i); + // printf("checking for '%s'\n", buffer); + if (access(buffer, R_OK)) + continue; /* device does not exist? */ +#ifdef ASSUME_MDEV + /* we can't use a 'remove' uevent, as that would also remove the device node + * which we certainly need for formatting :-) */ + if (! access("/etc/mdev/mdev-mount.sh", X_OK)) { + sprintf(buffer, "MDEV=%s%d ACTION=remove /etc/mdev/mdev-mount.sh block", d, i); + printf("-> running '%s'\n", buffer); + my_system(3, "/bin/sh", "-c", buffer); + } +#endif + sprintf(buffer, "/dev/%s%d", d, i); + /* just to make sure */ + swapoff(buffer); + if (dev_umount(buffer) && errno != ENOENT) + fprintf(stderr, "could not umount %s: %m\n", buffer); + } + return 0; +} + +/* triggers a uevent for all partitions of a given blockdev, dev can be /dev/sda, sda or sda4 */ +static int mount_all(const char *dev) +{ + char buffer[255]; + int i, ret = -1; + char *d = strdupa(dev); + char *p = d + strlen(d) - 1; + while (isdigit(*p)) + p--; + if (strstr(d, "/dev/") == d) + d += strlen("/dev/"); + *++p = 0x0; + printf("HDD: %s dev = '%s' d = '%s'\n", __func__, dev, d); + for (i = 1; i < 16; i++) + { +#ifdef ASSUME_MDEV + sprintf(buffer, "/sys/block/%s/%s%d/uevent", d, d, i); + if (!access(buffer, W_OK)) { + FILE *f = fopen(buffer, "w"); + if (!f) + fprintf(stderr, "HDD: %s could not open %s: %m\n", __func__, buffer); + else { + printf("-> triggering add uevent in %s\n", buffer); + fprintf(f, "add\n"); + fclose(f); + ret = 0; + } + } +#endif + } + return ret; +} + +#ifdef ASSUME_MDEV +static void waitfordev(const char *src, int maxwait) +{ + int waitcount = 0; + /* wait for the device to show up... */ + while (access(src, W_OK)) { + if (!waitcount) + printf("CHDDFmtExec: waiting for %s", src); + else + printf("."); + fflush(stdout); + waitcount++; + if (waitcount > maxwait) { + fprintf(stderr, "CHDDFmtExec: device %s did not appear!\n", src); + break; + } + sleep(1); + } + if (waitcount && waitcount <= maxwait) + printf("\n"); +} +#else +static void waitfordev(const char *, int) +{ +} +#endif +#endif + void CHDDMenuHandler::showError(neutrino_locale_t err) { ShowMsg(LOCALE_MESSAGEBOX_ERROR, g_Locale->getText(err), CMessageBox::mbrOk, CMessageBox::mbOk); @@ -825,6 +1028,7 @@ int CHDDMenuHandler::formatDevice(std::string dev) int res; FILE * f; CProgressWindow * progress; + std::string fdisk, sfdisk, tune2fs; printf("CHDDMenuHandler::formatDevice: dev %s hdd_fs %d\n", dev.c_str(), g_settings.hdd_fs); @@ -860,27 +1064,34 @@ int CHDDMenuHandler::formatDevice(std::string dev) goto _return; } -#ifdef ASSUME_MDEV - creat("/tmp/.nomdevmount", 00660); -#else +#ifndef ASSUME_MDEV f = fopen("/proc/sys/kernel/hotplug", "w"); if(f) { fprintf(f, "none\n"); fclose(f); } #endif + creat("/tmp/.nomdevmount", 00660); progress = new CProgressWindow(); progress->setTitle(LOCALE_HDD_FORMAT); progress->exec(NULL,""); progress->showGlobalStatus(0); - if (access("/sbin/sfdisk", X_OK) == 0) { - snprintf(cmd, sizeof(cmd), "/sbin/sfdisk -f -uM %s", devname.c_str()); + fdisk = find_executable("fdisk"); + sfdisk = find_executable("sfdisk"); + tune2fs = find_executable("tune2fs"); + if (! sfdisk.empty()) { + snprintf(cmd, sizeof(cmd), "%s -f -uM %s", sfdisk.c_str(), devname.c_str()); strcpy(cmd2, "0,\n;\n;\n;\ny\n"); + } else if (! fdisk.empty()) { + snprintf(cmd, sizeof(cmd), "%s -u %s", fdisk.c_str(), devname.c_str()); + strcpy(cmd2, "o\nn\np\n1\n2048\n\nw\n"); } else { - snprintf(cmd, sizeof(cmd), "/sbin/fdisk %s", devname.c_str()); - strcpy(cmd2, "o\nn\np\n1\n\n\nw\n"); + /* cannot do anything */ + fprintf(stderr, "CHDDFmtExec: neither fdisk nor sfdisk found in $PATH :-(\n"); + showError(LOCALE_HDD_FORMAT_FAILED); + goto _remount; } progress->showStatusMessageUTF(cmd); @@ -990,20 +1201,19 @@ int CHDDMenuHandler::formatDevice(std::string dev) } sleep(2); - if (devtool->fmt.substr(0, 3) == "ext") { + if (devtool->fmt.substr(0, 3) == "ext" && ! tune2fs.empty()) { std::string d = "/dev/" + devpart; - printf("CHDDMenuHandler::formatDevice: executing %s %s\n","/sbin/tune2fs -r 0 -c 0 -i 0", d.c_str()); - my_system(8, "/sbin/tune2fs", "-r", "0", "-c", "0", "-i", "0", d.c_str()); + printf("CHDDMenuHandler::formatDevice: executing %s %s %s\n", tune2fs.c_str(), "-r 0 -c 0 -i 0", d.c_str()); + my_system(8, tune2fs.c_str(), "-r", "0", "-c", "0", "-i", "0", d.c_str()); } show_menu = true; _remount: + unlink("/tmp/.nomdevmount"); progress->hide(); delete progress; -#ifdef ASSUME_MDEV - unlink("/tmp/.nomdevmount"); -#else +#ifndef ASSUME_MDEV f = fopen("/proc/sys/kernel/hotplug", "w"); if(f) { fprintf(f, "/sbin/hotplug\n"); @@ -1027,7 +1237,40 @@ _remount: safe_mkdir(cmd); snprintf(cmd, sizeof(cmd), "%s/plugins", dst.c_str()); safe_mkdir(cmd); - sync(); + // sync(); +#if HAVE_TRIPLEDRAGON + /* on the tripledragon, we mount via fstab, so we need to add an + fstab entry for dst */ + FILE *g; + char *line = NULL; + unlink("/etc/fstab.new"); + g = fopen("/etc/fstab.new", "w"); + f = fopen("/etc/fstab", "r"); + if (!g) + perror("open /etc/fstab.new"); + else { + if (f) { + int ret; + while (true) { + size_t dummy; + ret = getline(&line, &dummy, f); + if (ret < 0) + break; + /* remove lines that start with the same disk we formatted + devname is /dev/xda" */ + if (strncmp(line, devname.c_str(), devname.length()) != 0) + fprintf(g, "%s", line); + } + free(line); + fclose(f); + } + /* now add our new entry */ + fprintf(g, "%s %s auto defaults 0 0\n", partname.c_str(), dst.c_str()); + fclose(g); + rename("/etc/fstab", "/etc/fstab.old"); + rename("/etc/fstab.new", "/etc/fstab"); + } +#endif } } _return: diff --git a/src/gui/hdd_menu.h b/src/gui/hdd_menu.h index 13a320e62..617a7cb11 100644 --- a/src/gui/hdd_menu.h +++ b/src/gui/hdd_menu.h @@ -64,6 +64,7 @@ class CHDDMenuHandler : public CMenuTarget bool mounted; }; std::vector hdd_list; + std::set kernel_fs_list; struct cmp_hdd_by_name: public binary_function { bool operator() (const struct hdd_s &c1, const struct hdd_s &c2) @@ -84,6 +85,7 @@ class CHDDMenuHandler : public CMenuTarget bool add_dev(std::string dev, std::string part); bool waitfordev(std::string dev, int maxwait); void check_dev_tools(); + void check_kernel_fs(); devtool_s * get_dev_tool(std::string fmt); int showDeviceMenu(std::string dev); diff --git a/src/gui/infoviewer.cpp b/src/gui/infoviewer.cpp index ae4aba522..07b22e80e 100644 --- a/src/gui/infoviewer.cpp +++ b/src/gui/infoviewer.cpp @@ -109,6 +109,9 @@ CInfoViewer::CInfoViewer () txt_cur_start = txt_cur_event = txt_cur_event_rest = txt_next_start = txt_next_event = txt_next_in = NULL; timescale = NULL; clock = NULL; + info_CurrentNext.current_zeit.startzeit = 0; + info_CurrentNext.current_zeit.dauer = 0; + info_CurrentNext.flags = 0; frameBuffer = CFrameBuffer::getInstance(); infoViewerBB = CInfoViewerBB::getInstance(); @@ -826,7 +829,7 @@ void CInfoViewer::showTitle(CZapitChannel * channel, const bool calledFromNumZap const int channel_number_width =(g_settings.infobar_show_channellogo == 6) ? 5 + g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_CHANNAME]->getRenderWidth (strChanNum) : 0; ChannelLogoMode = showChannelLogo(current_channel_id,channel_number_width); // get logo mode, paint channel logo if adjusted logo_ok = ( g_settings.infobar_show_channellogo != 0 && ChannelLogoMode != 0); - fprintf(stderr, "after showchannellogo, mode = %d ret = %d logo_ok = %d\n",g_settings.infobar_show_channellogo, ChannelLogoMode, logo_ok); + //fprintf(stderr, "after showchannellogo, mode = %d ret = %d logo_ok = %d\n",g_settings.infobar_show_channellogo, ChannelLogoMode, logo_ok); if (g_settings.infobar_sat_display) { std::string name = (IS_WEBTV(current_channel_id))? "WebTV" : CServiceManager::getInstance()->GetSatelliteName(satellitePosition); @@ -1607,6 +1610,8 @@ int CInfoViewer::handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data) show_Data (true); } showLcdPercentOver (); + eventname = info_CurrentNext.current_name; + CVFD::getInstance()->setEPGTitle(eventname); return messages_return::handled; } else if (msg == NeutrinoMessages::EVT_ZAP_SUB_FAILED) { //chanready = 1; @@ -1669,43 +1674,41 @@ void CInfoViewer::sendNoEpg(const t_channel_id for_channel_id) } } -CSectionsdClient::CurrentNextInfo CInfoViewer::getEPG (const t_channel_id for_channel_id, CSectionsdClient::CurrentNextInfo &info) +void CInfoViewer::getEPG(const t_channel_id for_channel_id, CSectionsdClient::CurrentNextInfo &info) { /* to clear the oldinfo for channels without epg, call getEPG() with for_channel_id = 0 */ if (for_channel_id == 0 || IS_WEBTV(for_channel_id)) { oldinfo.current_uniqueKey = 0; - return info; + return; } CEitManager::getInstance()->getCurrentNextServiceKey(current_epg_id, info); -//printf("CInfoViewer::getEPG: old uniqueKey %llx new %llx\n", oldinfo.current_uniqueKey, info.current_uniqueKey); - /* of there is no EPG, send an event so that parental lock can work */ if (info.current_uniqueKey == 0 && info.next_uniqueKey == 0) { + memcpy(&oldinfo, &info, sizeof(CSectionsdClient::CurrentNextInfo)); sendNoEpg(for_channel_id); - oldinfo = info; - return info; + return; } - if (info.current_uniqueKey != oldinfo.current_uniqueKey || info.next_uniqueKey != oldinfo.next_uniqueKey) { - if (info.flags & (CSectionsdClient::epgflags::has_current | CSectionsdClient::epgflags::has_next)) { - char *_info = new char[sizeof(CSectionsdClient::CurrentNextInfo)]; - memcpy(_info, &info, sizeof(CSectionsdClient::CurrentNextInfo)); - neutrino_msg_t msg; + if (info.current_uniqueKey != oldinfo.current_uniqueKey || info.next_uniqueKey != oldinfo.next_uniqueKey) + { + char *p = new char[sizeof(t_channel_id)]; + memcpy(p, &for_channel_id, sizeof(t_channel_id)); + neutrino_msg_t msg; + if (info.flags & (CSectionsdClient::epgflags::has_current | CSectionsdClient::epgflags::has_next)) + { if (info.flags & CSectionsdClient::epgflags::has_current) msg = NeutrinoMessages::EVT_CURRENTEPG; else msg = NeutrinoMessages::EVT_NEXTEPG; - g_RCInput->postMsg(msg, (unsigned) _info, false ); - } else { - sendNoEpg(for_channel_id); } - oldinfo = info; + else + msg = NeutrinoMessages::EVT_NOEPG_YET; + g_RCInput->postMsg(msg, (const neutrino_msg_data_t)p, false); // data is pointer to allocated memory + memcpy(&oldinfo, &info, sizeof(CSectionsdClient::CurrentNextInfo)); } - - return info; } void CInfoViewer::showSNR () @@ -1954,11 +1957,15 @@ void CInfoViewer::show_Data (bool calledFromEvent) info_CurrentNext.current_zeit.startzeit = g_RemoteControl->subChannels[g_RemoteControl->selected_subchannel].startzeit; info_CurrentNext.current_zeit.dauer = g_RemoteControl->subChannels[g_RemoteControl->selected_subchannel].dauer; } else { +#if 0 +/* this triggers false positives on some channels. + * TODO: test on real NVOD channels, if this was even necessary at all */ if ((info_CurrentNext.flags & CSectionsdClient::epgflags::has_current) && (info_CurrentNext.flags & CSectionsdClient::epgflags::has_next) && (showButtonBar)) { if ((uint) info_CurrentNext.next_zeit.startzeit < (info_CurrentNext.current_zeit.startzeit + info_CurrentNext.current_zeit.dauer)) { is_nvod = true; } } +#endif } time_t jetzt = time (NULL); @@ -2310,7 +2317,7 @@ int CInfoViewer::showChannelLogo(const t_channel_id logo_channel_id, const int c bool logo_available = g_PicViewer->GetLogoName(logo_channel_id, ChannelName, strAbsIconPath, &logo_w, &logo_h); - fprintf(stderr, "%s: logo_available: %d file: %s\n", __FUNCTION__, logo_available, strAbsIconPath.c_str()); + //fprintf(stderr, "%s: logo_available: %d file: %s\n", __FUNCTION__, logo_available, strAbsIconPath.c_str()); if (! logo_available) return 0; @@ -2384,6 +2391,49 @@ int CInfoViewer::showChannelLogo(const t_channel_id logo_channel_id, const int c return res; } +#if HAVE_TRIPLEDRAGON +/* the cheap COOLSTREAM display cannot do this, so keep the routines separate */ +void CInfoViewer::showLcdPercentOver() +{ + if (g_settings.lcd_setting[SNeutrinoSettings::LCD_SHOW_VOLUME] != 1) + { + if (fileplay || NeutrinoMessages::mode_ts == CNeutrinoApp::getInstance()->getMode()) { + CVFD::getInstance()->showPercentOver(CMoviePlayerGui::getInstance().file_prozent); + return; + } + static long long old_interval = 0; + int runningPercent = -1; + time_t jetzt = time(NULL); + long long interval = 60000000; /* 60 seconds default update time */ + if (info_CurrentNext.flags & CSectionsdClient::epgflags::has_current) { + if (jetzt < info_CurrentNext.current_zeit.startzeit) + runningPercent = 0; + else if (jetzt > (int)(info_CurrentNext.current_zeit.startzeit + + info_CurrentNext.current_zeit.dauer)) + runningPercent = -2; /* overtime */ + else { + runningPercent = MIN((jetzt-info_CurrentNext.current_zeit.startzeit) * 100 / + info_CurrentNext.current_zeit.dauer, 100); + interval = info_CurrentNext.current_zeit.dauer * 1000LL * (1000/100); // update every percent + if (is_visible && interval > 60000000) // if infobar visible, update at + interval = 60000000; // least once per minute (radio mode) + if (interval < 5000000) + interval = 5000000; // but update only every 5 seconds + } + } + if (interval != old_interval) { + g_RCInput->killTimer(lcdUpdateTimer); + lcdUpdateTimer = g_RCInput->addTimer(interval, false); + //printf("lcdUpdateTimer: interval %lld old %lld\n",interval/1000000,old_interval/1000000); + old_interval = interval; + } + CLCD::getInstance()->showPercentOver(runningPercent); + int mode = CNeutrinoApp::getInstance()->getMode(); + if ((mode == NeutrinoMessages::mode_radio || mode == NeutrinoMessages::mode_tv)) + CVFD::getInstance()->setEPGTitle(info_CurrentNext.current_name); + } +} +#else void CInfoViewer::showLcdPercentOver () { if (g_settings.lcd_setting[SNeutrinoSettings::LCD_SHOW_VOLUME] != 1) { @@ -2402,11 +2452,12 @@ void CInfoViewer::showLcdPercentOver () if (jetzt < info_CurrentNext.current_zeit.startzeit) runningPercent = 0; else - runningPercent = MIN ((unsigned) ((float) (jetzt - info_CurrentNext.current_zeit.startzeit) / (float) info_CurrentNext.current_zeit.dauer * 100.), 100); + runningPercent = MIN ((jetzt - info_CurrentNext.current_zeit.startzeit) * 100 / info_CurrentNext.current_zeit.dauer, 100); } CVFD::getInstance ()->showPercentOver (runningPercent); } } +#endif void CInfoViewer::showEpgInfo() //message on event change { diff --git a/src/gui/infoviewer.h b/src/gui/infoviewer.h index b8ffeb794..25f1f0d3d 100644 --- a/src/gui/infoviewer.h +++ b/src/gui/infoviewer.h @@ -189,7 +189,8 @@ class CInfoViewer void showTitle(t_channel_id channel_id, const bool calledFromNumZap = false, int epgpos = 0); void lookAheadEPG(const int ChanNum, const std::string & Channel, const t_channel_id new_channel_id = 0, const bool calledFromNumZap = false); //alpha: fix for nvod subchannel update void killTitle(); - CSectionsdClient::CurrentNextInfo getEPG(const t_channel_id for_channel_id, CSectionsdClient::CurrentNextInfo &info); + void getEPG(const t_channel_id for_channel_id, CSectionsdClient::CurrentNextInfo &info); + CSectionsdClient::CurrentNextInfo getCurrentNextInfo() const { return info_CurrentNext; } void showSubchan(); //void Set_CA_Status(int Status); diff --git a/src/gui/infoviewer_bb.cpp b/src/gui/infoviewer_bb.cpp index ee550a384..1c2afd544 100644 --- a/src/gui/infoviewer_bb.cpp +++ b/src/gui/infoviewer_bb.cpp @@ -609,8 +609,8 @@ void CInfoViewerBB::showIcon_Resolution() case 1920: icon_name = NEUTRINO_ICON_RESOLUTION_1920; break; - case 1080: case 1088: + case 1080: icon_name = NEUTRINO_ICON_RESOLUTION_1080; break; case 1440: @@ -653,9 +653,9 @@ void CInfoViewerBB::showIcon_Resolution() } if (g_settings.infobar_show_res == 1) {//show simple resolution icon on infobar videoDecoder->getPictureInfo(xres, yres, framerate); - if (yres > 704) + if (yres > 576) icon_name = NEUTRINO_ICON_RESOLUTION_HD; - else if (yres >= 288) + else if (yres > 0) icon_name = NEUTRINO_ICON_RESOLUTION_SD; else icon_name = NEUTRINO_ICON_RESOLUTION_000; diff --git a/src/gui/keybind_setup.cpp b/src/gui/keybind_setup.cpp index 3db50e64c..dd3167db7 100644 --- a/src/gui/keybind_setup.cpp +++ b/src/gui/keybind_setup.cpp @@ -286,7 +286,7 @@ int CKeybindSetup::showKeySetup() cc->setHint("", LOCALE_MENU_HINT_LONGKEYPRESS_DURATION); keySettings->addItem(cc); -#if HAVE_SPARK_HARDWARE +#if 0 g_settings.accept_other_remotes = access("/etc/lircd_predata_lock", R_OK) ? 1 : 0; CMenuOptionChooser *mc = new CMenuOptionChooser(LOCALE_KEYBINDINGMENU_ACCEPT_OTHER_REMOTES, &g_settings.accept_other_remotes, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, this, @@ -433,9 +433,11 @@ void CKeybindSetup::showKeyBindSetup(CMenuWidget *bindSettings) mf->setHint("", key_settings[NKEY_UNLOCK].hint); bindSettings->addItem(mf); // screenshot +#ifdef SCREENSHOT mf = new CMenuForwarder(key_settings[NKEY_SCREENSHOT].keydescription, true, keychooser[NKEY_SCREENSHOT]->getKeyName(), keychooser[NKEY_SCREENSHOT]); mf->setHint("", key_settings[NKEY_SCREENSHOT].hint); bindSettings->addItem(mf); +#endif #ifdef ENABLE_PIP // pip mf = new CMenuForwarder(key_settings[NKEY_PIP_CLOSE].keydescription, true, keychooser[NKEY_PIP_CLOSE]->getKeyName(), keychooser[NKEY_PIP_CLOSE]); @@ -542,7 +544,7 @@ void CKeybindSetup::showKeyBindSpecialSetup(CMenuWidget *bindSettings_special) bool CKeybindSetup::changeNotify(const neutrino_locale_t OptionName, void * /* data */) { -#if HAVE_SPARK_HARDWARE +#if 0 if (ARE_LOCALES_EQUAL(OptionName, LOCALE_KEYBINDINGMENU_ACCEPT_OTHER_REMOTES)) { struct sockaddr_un sun; memset(&sun, 0, sizeof(sun)); diff --git a/src/gui/lua/lua_misc.cpp b/src/gui/lua/lua_misc.cpp index 52f01e7ce..aa6c7aded 100644 --- a/src/gui/lua/lua_misc.cpp +++ b/src/gui/lua/lua_misc.cpp @@ -285,6 +285,10 @@ int CLuaInstMisc::GetRevision(lua_State *L) std::string hw = ""; #if HAVE_COOL_HARDWARE hw = "Coolstream"; +#else + hw = g_info.hw_caps->boxvendor; + hw += "_"; + hw += g_info.hw_caps->boxname; #endif rev = cs_get_revision(); lua_pushinteger(L, rev); diff --git a/src/gui/miscsettings_menu.cpp b/src/gui/miscsettings_menu.cpp index b76adc465..fd49866b0 100644 --- a/src/gui/miscsettings_menu.cpp +++ b/src/gui/miscsettings_menu.cpp @@ -55,7 +55,6 @@ #include #include -#include #include extern CPlugins * g_PluginList; @@ -235,7 +234,7 @@ int CMiscMenue::showMiscSettingsMenu() misc_menue.addItem(mf); //energy, shutdown - if(cs_get_revision() > 7) + if (g_info.hw_caps->can_shutdown) { mf = new CMenuForwarder(LOCALE_MISCSETTINGS_ENERGY, true, NULL, this, "energy", CRCInput::RC_green); mf->setHint("", LOCALE_MENU_HINT_MISC_ENERGY); @@ -260,10 +259,18 @@ int CMiscMenue::showMiscSettingsMenu() //cec settings CCECSetup cecsetup; - mf = new CMenuForwarder(LOCALE_VIDEOMENU_HDMI_CEC, true, NULL, &cecsetup, NULL, CRCInput::RC_1); - mf->setHint("", LOCALE_MENU_HINT_MISC_CEC); - misc_menue.addItem(mf); + if (g_info.hw_caps->can_cec) { + mf = new CMenuForwarder(LOCALE_VIDEOMENU_HDMI_CEC, true, NULL, &cecsetup, NULL, CRCInput::RC_1); + mf->setHint("", LOCALE_MENU_HINT_MISC_CEC); + misc_menue.addItem(mf); + } + if (!g_info.hw_caps->can_shutdown) { + /* we don't have the energy menu, but put the sleeptimer directly here */ + mf = new CMenuDForwarder(LOCALE_MISCSETTINGS_SLEEPTIMER, true, NULL, new CSleepTimerWidget(true)); + mf->setHint("", LOCALE_MENU_HINT_INACT_TIMER); + misc_menue.addItem(mf); + } //channellist mf = new CMenuForwarder(LOCALE_MISCSETTINGS_CHANNELLIST, true, NULL, this, "channellist", CRCInput::RC_2); mf->setHint("", LOCALE_MENU_HINT_MISC_CHANNELLIST); @@ -447,7 +454,8 @@ void CMiscMenue::showMiscSettingsMenuEpg(CMenuWidget *ms_epg) mf3->setHint("", LOCALE_MENU_HINT_EPG_MAX_EVENTS); epg_scan = new CMenuOptionChooser(LOCALE_MISCSETTINGS_EPG_SCAN_BOUQUETS, &g_settings.epg_scan, EPG_SCAN_OPTIONS, EPG_SCAN_OPTION_COUNT, - g_settings.epg_scan_mode != CEpgScan::MODE_OFF && g_settings.epg_save_mode == 0); + true); + //(g_settings.epg_scan_mode != CEpgScan::MODE_OFF && g_settings.epg_save_mode == 0); epg_scan->setHint("", LOCALE_MENU_HINT_EPG_SCAN); CMenuOptionChooser * mc3 = new CMenuOptionChooser(LOCALE_MISCSETTINGS_EPG_SCAN, &g_settings.epg_scan_mode, EPG_SCAN_MODE_OPTIONS, @@ -639,14 +647,16 @@ bool CMiscMenue::changeNotify(const neutrino_locale_t OptionName, void * /*data* } else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_MISCSETTINGS_EPG_SCAN)) { - epg_scan->setActive(g_settings.epg_scan_mode != CEpgScan::MODE_OFF && g_settings.epg_save_mode == 0); + epg_scan->setActive(g_settings.epg_scan_mode != CEpgScan::MODE_OFF /*&& g_settings.epg_save_mode == 0*/); } +#if 0 else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_MISCSETTINGS_EPG_SAVE_MODE)) { g_settings.epg_scan = CEpgScan::SCAN_FAV; epg_scan->setActive(g_settings.epg_scan_mode != CEpgScan::MODE_OFF && g_settings.epg_save_mode == 0); ret = menu_return::RETURN_REPAINT; } +#endif else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_TMDB_API_KEY)) { g_settings.tmdb_enabled = check_tmdb_api_key(); diff --git a/src/gui/moviebrowser.cpp b/src/gui/moviebrowser.cpp index 71457cd5f..ddbf4dfc0 100644 --- a/src/gui/moviebrowser.cpp +++ b/src/gui/moviebrowser.cpp @@ -30,7 +30,7 @@ Author: Günther@tuxbox.berlios.org based on code of Steffen Hehn 'McClean' - (C) 2009-2014 Stefan Seyfried + (C) 2009-2015 Stefan Seyfried ****************************************************************************/ @@ -1442,7 +1442,7 @@ std::string CMovieBrowser::getScreenshotName(std::string movie, bool is_dir) void CMovieBrowser::refreshMovieInfo(void) { - TRACE("[mb]->%s m_vMovieInfo.size %d\n", __func__, m_vMovieInfo.size()); + TRACE("[mb]->%s m_vMovieInfo.size %d\n", __func__, (int)m_vMovieInfo.size()); //reset text before new init, m_pcInfo must be clean std::string emptytext = " "; m_pcInfo->setText(&emptytext); @@ -1562,7 +1562,7 @@ void CMovieBrowser::info_hdd_level(bool paint_hdd) if (getSelectedFile() != NULL) { if (::statfs(getSelectedFile()->Name.c_str(), &s) == 0) { long blocks_used = s.f_blocks - s.f_bfree; - blocks_percent_used = (long)(blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5); + blocks_percent_used = (blocks_used * 1000 / (blocks_used + s.f_bavail) + 5)/10; } } diff --git a/src/gui/movieinfo.cpp b/src/gui/movieinfo.cpp index b29fb74cb..c4559df14 100644 --- a/src/gui/movieinfo.cpp +++ b/src/gui/movieinfo.cpp @@ -327,7 +327,7 @@ bool CMovieInfo::parseXmlTree(std::string &_text, MI_MOVIE_INFO *movie_info) pos2 = -1; ptr = strstr(&text[pos], MI_XML_TAG_PID); if (ptr) - pos2 = (int)ptr - (int)&text[pos]; + pos2 = (int)(ptr - &text[pos]); //pos2 = strcspn(&text[pos],MI_XML_TAG_PID); if (pos2 >= 0) { pos2 += sizeof(MI_XML_TAG_PID); @@ -342,7 +342,7 @@ bool CMovieInfo::parseXmlTree(std::string &_text, MI_MOVIE_INFO *movie_info) pos2 = -1; ptr = strstr(&text[pos], MI_XML_TAG_ATYPE); if (ptr) - pos2 = (int)ptr - (int)&text[pos]; + pos2 = (int)(ptr - &text[pos]); //pos2 = strcspn(&text[pos],MI_XML_TAG_ATYPE); if (pos2 >= 0) { pos2 += sizeof(MI_XML_TAG_ATYPE); @@ -356,7 +356,7 @@ bool CMovieInfo::parseXmlTree(std::string &_text, MI_MOVIE_INFO *movie_info) pos2 = -1; ptr = strstr(&text[pos], MI_XML_TAG_SELECTED); if (ptr) - pos2 = (int)ptr - (int)&text[pos]; + pos2 = (int)(ptr - &text[pos]); //pos2 = strcspn(&text[pos],MI_XML_TAG_SELECTED); if (pos2 >= 0) { pos2 += sizeof(MI_XML_TAG_SELECTED); @@ -371,7 +371,7 @@ bool CMovieInfo::parseXmlTree(std::string &_text, MI_MOVIE_INFO *movie_info) pos2 = -1; ptr = strstr(&text[pos], MI_XML_TAG_NAME); if (ptr) - pos2 = (int)ptr - (int)&text[pos]; + pos2 = (int)(ptr - &text[pos]); if (pos2 >= 0) { pos2 += sizeof(MI_XML_TAG_PID); while (text[pos + pos2] != '\"' && text[pos + pos2] != 0 && text[pos + pos2] != '/') diff --git a/src/gui/movieplayer.cpp b/src/gui/movieplayer.cpp index 5fa3c3d52..344f4db14 100644 --- a/src/gui/movieplayer.cpp +++ b/src/gui/movieplayer.cpp @@ -3,6 +3,7 @@ Movieplayer (c) 2003, 2004 by gagga Based on code by Dirch, obi and the Metzler Bros. Thanks. + (C) 2010-2014 Stefan Seyfried Copyright (C) 2011 CoolStream International Ltd @@ -76,6 +77,12 @@ #include #include +#ifndef HAVE_COOL_HARDWARE +#define LCD_MODE CVFD::MODE_MOVIE +#else +#define LCD_MODE CVFD::MODE_MENU_UTF8 +#endif + //NI InfoIcons #include extern CInfoIcons *InfoIcons; @@ -151,22 +158,31 @@ void CMoviePlayerGui::Init(void) bookmarkmanager = new CBookmarkManager(); tsfilefilter.addFilter("ts"); +#if HAVE_TRIPLEDRAGON + tsfilefilter.addFilter("vdr"); +#else tsfilefilter.addFilter("avi"); tsfilefilter.addFilter("mkv"); tsfilefilter.addFilter("wav"); tsfilefilter.addFilter("asf"); tsfilefilter.addFilter("aiff"); + tsfilefilter.addFilter("mp4"); + tsfilefilter.addFilter("mov"); +#endif tsfilefilter.addFilter("mpg"); tsfilefilter.addFilter("mpeg"); tsfilefilter.addFilter("m2p"); tsfilefilter.addFilter("mpv"); tsfilefilter.addFilter("vob"); tsfilefilter.addFilter("m2ts"); - tsfilefilter.addFilter("mp4"); - tsfilefilter.addFilter("mov"); tsfilefilter.addFilter("m3u"); tsfilefilter.addFilter("m3u8"); tsfilefilter.addFilter("pls"); + tsfilefilter.addFilter("vdr"); +#ifdef HAVE_SPARK_HARDWARE + tsfilefilter.addFilter("flv"); + tsfilefilter.addFilter("wmv"); +#endif tsfilefilter.addFilter("iso"); if (g_settings.network_nfs_moviedir.empty()) @@ -228,6 +244,14 @@ void CMoviePlayerGui::cutNeutrino() //NI if (!isWebTV) //NI g_Sectionsd->setPauseScanning(true); +#ifdef HAVE_AZBOX_HARDWARE + /* we need sectionsd to get idle and zapit to release the demuxes + * and decoders so that the external player can do its work + * TODO: what about timeshift? */ + g_Sectionsd->setServiceChanged(0, false); + g_Zapit->setStandby(true); +#endif + m_LastMode = (CNeutrinoApp::getInstance()->getMode() /*| NeutrinoMessages::norezap*/); if (isWebTV) m_LastMode |= NeutrinoMessages::norezap; @@ -243,6 +267,10 @@ void CMoviePlayerGui::restoreNeutrino() return; playing = false; +#ifdef HAVE_AZBOX_HARDWARE + g_Zapit->setStandby(false); + CZapit::getInstance()->SetVolume(CZapit::getInstance()->GetVolume()); +#endif if (isUPNP) return; @@ -406,7 +434,7 @@ void CMoviePlayerGui::updateLcd() break; } lcd += name; - CVFD::getInstance()->setMode(CVFD::MODE_MENU_UTF8); + CVFD::getInstance()->setMode(LCD_MODE); CVFD::getInstance()->showMenuText(0, lcd.c_str(), -1, true); } @@ -1300,6 +1328,7 @@ void CMoviePlayerGui::PlayFileLoop(void) bool first_start = true; bool update_lcd = true; int eof = 0; + int lastpos = 0; bool at_eof = !(playstate >= CMoviePlayerGui::PLAY);; keyPressed = CMoviePlayerGui::PLUGIN_PLAYSTATE_NORMAL; while (playstate >= CMoviePlayerGui::PLAY) @@ -1332,7 +1361,10 @@ void CMoviePlayerGui::PlayFileLoop(void) update_lcd = true; } #ifdef DEBUG - printf("CMoviePlayerGui::%s: spd %d pos %d/%d (%d, %d%%)\n", __func__, speed, position, duration, duration-position, file_prozent); + if (msg < CRCInput::RC_Events || eof > 0 || position - lastpos >= 10000) { + lastpos = position; + printf("CMoviePlayerGui::%s: spd %d pos %d/%d (%d, %d%%)\n", __func__, speed, position, duration, duration-position, file_prozent); + } #endif /* in case ffmpeg report incorrect values */ int posdiff = duration - position; @@ -1779,9 +1811,10 @@ void CMoviePlayerGui::addAudioFormat(int count, std::string &apidtitle, bool& en apidtitle.append(" (AAC)"); break; case 6: /*DTS*/ + apidtitle.append(" (DTS)"); if (apidtitle.find("DTS") == std::string::npos) apidtitle.append(" (DTS)"); -#ifndef BOXMODEL_APOLLO +#if ! defined(HAVE_SPARK_HARDWARE) && ! defined (BOXMODEL_APOLLO) enabled = false; #endif break; @@ -1955,7 +1988,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/) } else if ((msg == (neutrino_msg_t) g_settings.mpkey_stop) || msg == CRCInput::RC_home) { //NI // if we have a movie information, try to save the stop position - printf("CMoviePlayerGui::handleMovieBrowser: stop, isMovieBrowser %d p_movie_info %x\n", isMovieBrowser, (int) p_movie_info); + printf("CMoviePlayerGui::handleMovieBrowser: stop, isMovieBrowser %d p_movie_info %p\n", isMovieBrowser, p_movie_info); if (isMovieBrowser && p_movie_info) { timeb current_time; ftime(¤t_time); @@ -2695,12 +2728,16 @@ bool CMoviePlayerGui::mountIso(CFile *file) } return false; } - -void CMoviePlayerGui::makeScreenShot(bool autoshot, bool forcover) +void CMoviePlayerGui::makeScreenShot(bool autoshot, bool +#ifdef SCREENSHOT + forcover +#endif + ) { if (autoshot && (autoshot_done || !g_settings.auto_cover)) return; +#ifdef SCREENSHOT bool cover = autoshot || g_settings.screenshot_cover || forcover; char ending[(sizeof(int)*2) + 6] = ".jpg"; if (!cover) @@ -2751,6 +2788,7 @@ void CMoviePlayerGui::makeScreenShot(bool autoshot, bool forcover) } } sc->Start(); +#endif if (autoshot) autoshot_done = true; } diff --git a/src/gui/network_service.cpp b/src/gui/network_service.cpp index fd14d9318..51bba476e 100644 --- a/src/gui/network_service.cpp +++ b/src/gui/network_service.cpp @@ -24,6 +24,7 @@ #include #endif +#include #include #include diff --git a/src/gui/opkg_manager.cpp b/src/gui/opkg_manager.cpp index 91e6320ef..ac423ea37 100644 --- a/src/gui/opkg_manager.cpp +++ b/src/gui/opkg_manager.cpp @@ -66,10 +66,18 @@ #define OPKG_TMP_DIR "/tmp/.opkg" #define OPKG_TEST_DIR OPKG_TMP_DIR "/test" +#if 0 #define OPKG_CL_CONFIG_OPTIONS " -V2 --tmp-dir=/tmp --cache=" OPKG_TMP_DIR +#else +#define OPKG_CL_CONFIG_OPTIONS "" +#endif #define OPKG_BAD_PATTERN_LIST_FILE CONFIGDIR "/bad_package_pattern.list" +#if 0 #define OPKG_CONFIG_FILE "/etc/opkg/opkg.conf" +#else +#define OPKG_CONFIG_FILE "/etc/opkg/opkg.conf.borken" +#endif using namespace std; diff --git a/src/gui/osd_setup.cpp b/src/gui/osd_setup.cpp index 357dda379..37da5fe37 100644 --- a/src/gui/osd_setup.cpp +++ b/src/gui/osd_setup.cpp @@ -10,6 +10,7 @@ Copyright (C) 2010 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2010, 2012-2013 Stefan Seyfried License: GPL @@ -63,6 +64,7 @@ #include #include #include +#include "cs_api.h" extern CRemoteControl * g_RemoteControl; @@ -633,12 +635,14 @@ int COsdSetup::showOsdSetup() mf->setHint("", LOCALE_MENU_HINT_INFOCLOCK_SETUP); osd_menu->addItem(mf); +#ifdef SCREENSHOT //screenshot CMenuWidget osd_menu_screenshot(LOCALE_MAINMENU_SETTINGS, NEUTRINO_ICON_SETTINGS, width, MN_WIDGET_ID_OSDSETUP_SCREENSHOT); showOsdScreenShotSetup(&osd_menu_screenshot); mf = new CMenuForwarder(LOCALE_SCREENSHOT_MENU, true, NULL, &osd_menu_screenshot, NULL, CRCInput::convertDigitToKey(shortcut++)); mf->setHint("", LOCALE_MENU_HINT_SCREENSHOT_SETUP); osd_menu->addItem(mf); +#endif //screensaver CMenuWidget osd_menu_screensaver(LOCALE_MAINMENU_SETTINGS, NEUTRINO_ICON_SETTINGS, width, MN_WIDGET_ID_OSDSETUP_SCREENSAVER); @@ -650,9 +654,12 @@ int COsdSetup::showOsdSetup() osd_menu->addItem(GenericMenuSeparatorLine); //monitor - CMenuOptionChooser * mc = new CMenuOptionChooser(LOCALE_COLORMENU_OSD_PRESET, &g_settings.screen_preset, OSD_PRESET_OPTIONS, OSD_PRESET_OPTIONS_COUNT, true, this); - mc->setHint("", LOCALE_MENU_HINT_OSD_PRESET); - osd_menu->addItem(mc); + CMenuOptionChooser *mc; + if (cs_get_revision() != 1) { /* 1 == Tripledragon */ + mc = new CMenuOptionChooser(LOCALE_COLORMENU_OSD_PRESET, &g_settings.screen_preset, OSD_PRESET_OPTIONS, OSD_PRESET_OPTIONS_COUNT, true, this); + mc->setHint("", LOCALE_MENU_HINT_OSD_PRESET); + osd_menu->addItem(mc); + } //NI #if !defined BOXMODEL_APOLLO @@ -1088,6 +1095,14 @@ const CMenuOptionChooser::keyval PROGRESSBAR_INFOBAR_POSITION_OPTIONS[PROGRESSBA { 2 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_2 }, { 3 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_3 } }; +#define LOCALE_MISCSETTINGS_INFOBAR_PROGRESSBAR_COUNT 4 +const CMenuOptionChooser::keyval LOCALE_MISCSETTINGS_INFOBAR_PROGRESSBAR_OPTIONS[LOCALE_MISCSETTINGS_INFOBAR_PROGRESSBAR_COUNT]= +{ + { 0 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_0 }, + { 1 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_1 }, + { 2 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_2 }, + { 3 , LOCALE_MISCSETTINGS_PROGRESSBAR_INFOBAR_POSITION_3 } +}; //menus void COsdSetup::showOsdMenusSetup(CMenuWidget *menu_menus) @@ -1558,6 +1573,7 @@ int COsdSetup::showContextChanlistMenu(CChannelList *parent_channellist) return res; } +#ifdef SCREENSHOT //screenshot #define SCREENSHOT_FMT_OPTION_COUNT 3 const CMenuOptionChooser::keyval_ext SCREENSHOT_FMT_OPTIONS[SCREENSHOT_FMT_OPTION_COUNT] = @@ -1607,6 +1623,7 @@ void COsdSetup::showOsdScreenShotSetup(CMenuWidget *menu_screenshot) mc->setHint("", LOCALE_MENU_HINT_SCREENSHOT_COVER); menu_screenshot->addItem(mc); } +#endif #define SCREENSAVER_MODE_OPTION_COUNT 3 const CMenuOptionChooser::keyval SCREENSAVER_MODE_OPTIONS[SCREENSAVER_MODE_OPTION_COUNT] = diff --git a/src/gui/osdlang_setup.cpp b/src/gui/osdlang_setup.cpp index dbf05ff02..36dba32d2 100644 --- a/src/gui/osdlang_setup.cpp +++ b/src/gui/osdlang_setup.cpp @@ -33,6 +33,7 @@ #include #endif +#include #include "osdlang_setup.h" diff --git a/src/gui/personalize.cpp b/src/gui/personalize.cpp index 778587212..06ad6771f 100644 --- a/src/gui/personalize.cpp +++ b/src/gui/personalize.cpp @@ -9,6 +9,8 @@ Reworked by dbt (Thilo Graf) Copyright (C) 2010, 2011 dbt + Copyright (C) 2014 Stefan Seyfried + Comment: This is the customization menu, as originally showcased in diff --git a/src/gui/pictureviewer.cpp b/src/gui/pictureviewer.cpp index 8459dcdfe..f9f8398f0 100644 --- a/src/gui/pictureviewer.cpp +++ b/src/gui/pictureviewer.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include diff --git a/src/gui/plugins.cpp b/src/gui/plugins.cpp index 2113282ef..2b7e4f4d4 100644 --- a/src/gui/plugins.cpp +++ b/src/gui/plugins.cpp @@ -4,13 +4,7 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ - Kommentar: - - Diese GUI wurde von Grund auf neu programmiert und sollte nun vom - Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert - auf der Client-Server Idee, diese GUI ist also von der direkten DBox- - Steuerung getrennt. Diese wird dann von Daemons uebernommen. - + Copyright (C) 2011-2014 Stefan Seyfried License: GPL @@ -128,7 +122,7 @@ void CPlugins::scanDir(const char *dir) new_plugin.pluginfile.append(".sh"); else if (new_plugin.type == CPlugins::P_TYPE_LUA) new_plugin.pluginfile.append(".lua"); - else + else // CPlugins::P_TYPE_GAME or CPlugins::P_TYPE_TOOL new_plugin.pluginfile.append(".so"); // We do not check if new_plugin.pluginfile exists since .cfg in // PLUGINDIR_VAR can overwrite settings in read only dir @@ -137,7 +131,6 @@ void CPlugins::scanDir(const char *dir) // already exists in the list. // This behavior is used to make sure plugins can be disabled // by creating a .cfg in PLUGINDIR_VAR (PLUGINDIR often is read only). - if (!plugin_exists(new_plugin.filename)) { plugin_list.push_back(new_plugin); @@ -430,7 +423,7 @@ void CPlugins::startLuaPlugin(int number) CLuaInstance *lua = new CLuaInstance(); lua->runScript(script); delete lua; -#if HAVE_SPARK_HARDWARE +#if 0 frameBuffer->ClearFB(); #endif videoDecoder->Pig(-1, -1, -1, -1); @@ -443,25 +436,25 @@ void CPlugins::startPlugin(int number) delScriptOutput(); /* export neutrino settings to the environment */ char tmp[32]; -#if HAVE_SPARK_HARDWARE +#if 0 sprintf(tmp, "%d", g_settings.screen_StartX_int); #else sprintf(tmp, "%d", g_settings.screen_StartX); #endif setenv("SCREEN_OFF_X", tmp, 1); -#if HAVE_SPARK_HARDWARE +#if 0 sprintf(tmp, "%d", g_settings.screen_StartY_int); #else sprintf(tmp, "%d", g_settings.screen_StartY); #endif setenv("SCREEN_OFF_Y", tmp, 1); -#if HAVE_SPARK_HARDWARE +#if 0 sprintf(tmp, "%d", g_settings.screen_EndX_int); #else sprintf(tmp, "%d", g_settings.screen_EndX); #endif setenv("SCREEN_END_X", tmp, 1); -#if HAVE_SPARK_HARDWARE +#if 0 sprintf(tmp, "%d", g_settings.screen_EndY_int); #else sprintf(tmp, "%d", g_settings.screen_EndY); @@ -503,7 +496,7 @@ void CPlugins::startPlugin(int number) my_system(2, plugin_list[number].pluginfile.c_str(), NULL); //frameBuffer->setMode(720, 576, 8 * sizeof(fb_pixel_t)); frameBuffer->Unlock(); -#if HAVE_SPARK_HARDWARE +#if 0 frameBuffer->ClearFB(); #endif videoDecoder->Pig(-1, -1, -1, -1); @@ -517,7 +510,7 @@ bool CPlugins::hasPlugin(CPlugins::p_type_t type) for (std::vector::iterator it=plugin_list.begin(); it!=plugin_list.end(); ++it) { - if (it->type == type && !it->hide) + if ((it->type & type) && !it->hide) return true; } return false; diff --git a/src/gui/plugins.h b/src/gui/plugins.h index d12fd06d6..76f50adda 100644 --- a/src/gui/plugins.h +++ b/src/gui/plugins.h @@ -50,7 +50,8 @@ class CPlugins P_TYPE_GAME = 0x2, P_TYPE_TOOL = 0x4, P_TYPE_SCRIPT = 0x8, - P_TYPE_LUA = 0x10 + P_TYPE_LUA = 0x10, + P_TYPE_NO_GAME = P_TYPE_TOOL|P_TYPE_SCRIPT|P_TYPE_LUA } p_type_t; diff --git a/src/gui/rc_lock.cpp b/src/gui/rc_lock.cpp index 354a89caa..a7db6be1d 100644 --- a/src/gui/rc_lock.cpp +++ b/src/gui/rc_lock.cpp @@ -27,6 +27,7 @@ #include #include +#include #include diff --git a/src/gui/scan.cpp b/src/gui/scan.cpp index 4fddbaa3f..574a91100 100644 --- a/src/gui/scan.cpp +++ b/src/gui/scan.cpp @@ -2,8 +2,6 @@ Neutrino-GUI - DBoxII-Project Copyright (C) 2001 Steffen Hehn 'McClean' - Homepage: http://dbox.cyberphoria.org/ - Copyright (C) 2011-2012 Stefan Seyfried License: GPL @@ -19,8 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #ifdef HAVE_CONFIG_H @@ -108,7 +105,8 @@ void CScanTs::prev_next_TP( bool up) } } } else { - for ( tI=select_transponders.end() ; tI != select_transponders.begin(); --tI ) { + for (tI = select_transponders.end(); tI != select_transponders.begin();) { + --tI; if(tI->second.feparams.frequency < TP.feparams.frequency) { next_tp = true; break; @@ -126,7 +124,7 @@ void CScanTs::testFunc() { int w = x + width - xpos2; char buffer[128]; - char *f, *s, *m, *f2; + const char *f, *s, *m, *f2; if (CFrontend::isSat(delsys)) { CFrontend::getDelSys(TP.feparams.delsys, TP.feparams.fec_inner, TP.feparams.modulation, f, s, m); @@ -143,6 +141,7 @@ void CScanTs::testFunc() printf("CScanTs::testFunc: %s\n", buffer); paintLine(xpos2, ypos_cur_satellite, w - 95, pname.c_str()); paintLine(xpos2, ypos_frequency, w, buffer); + paintRadar(); success = g_Zapit->tune_TP(TP); } @@ -188,10 +187,13 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) mheight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight(); fw = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getWidth(); width = w_max(fw * 42, 0); + int tmp = (BAR_WIDTH + 4 + 7 * fw) * 2 + fw + 40; /* that's from the crazy calculation in showSNR() */ + if (width < tmp) + width = w_max(tmp, 0); height = h_max(hheight + (12 * mheight), 0); //9 lines x = frameBuffer->getScreenX() + (frameBuffer->getScreenWidth() - width) / 2; y = frameBuffer->getScreenY() + (frameBuffer->getScreenHeight() - height) / 2; - xpos_radar = x + 36 * fw; + xpos_radar = x + width - 20 - 64; /* TODO: don't assume radar is 64x64... */ ypos_radar = y + hheight + (mheight >> 1); xpos1 = x + 10; @@ -292,6 +294,7 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) tuned = -1; paint(test); + /* go */ if(test) { testFunc(); @@ -375,7 +378,10 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) return menu_return::RETURN_REPAINT; } -int CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) +/* this is not type "int", because it does not return a code indicating success but + * instead returns altered "msg". This is different ot all other "handleMsg" functions + * and should probably be fixed somewhen... */ +neutrino_msg_t CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) { int w = x + width - xpos2; //printf("CScanTs::handleMsg: x %d xpos2 %d width %d w %d\n", x, xpos2, width, w); @@ -387,7 +393,7 @@ int CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) break; case NeutrinoMessages::EVT_SCAN_NUM_TRANSPONDERS: - sprintf(buffer, "%u", data); + sprintf(buffer, "%ld", data); paintLine(xpos2, ypos_transponder, w - (8*fw), buffer); total = data; snprintf(str, sizeof(buffer), "scan: %d/%d", done, total); @@ -406,7 +412,7 @@ int CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) case NeutrinoMessages::EVT_SCAN_REPORT_FREQUENCYP: { FrontendParameters *feparams = (FrontendParameters*) data; - char * f, *s, *m; + const char *f, *s, *m; CFrontend::getDelSys(feparams->delsys, feparams->fec_inner, feparams->modulation, f, s, m); uint32_t freq = feparams->frequency/1000; @@ -427,22 +433,22 @@ int CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) break; case NeutrinoMessages::EVT_SCAN_NUM_CHANNELS: - sprintf(buffer, " = %u", data); + sprintf(buffer, " = %ld", data); paintLine(xpos1 + 3 * (6*fw), ypos_service_numbers + mheight, width - 3 * (6*fw) - 10, buffer); break; case NeutrinoMessages::EVT_SCAN_FOUND_TV_CHAN: - sprintf(buffer, "%u", data); + sprintf(buffer, "%ld", data); paintLine(xpos1, ypos_service_numbers + mheight, (6*fw), buffer); break; case NeutrinoMessages::EVT_SCAN_FOUND_RADIO_CHAN: - sprintf(buffer, "%u", data); + sprintf(buffer, "%ld", data); paintLine(xpos1 + (6*fw), ypos_service_numbers + mheight, (6*fw), buffer); break; case NeutrinoMessages::EVT_SCAN_FOUND_DATA_CHAN: - sprintf(buffer, "%u", data); + sprintf(buffer, "%ld", data); paintLine(xpos1 + 2 * (6*fw), ypos_service_numbers + mheight, (6*fw), buffer); break; diff --git a/src/gui/scan.h b/src/gui/scan.h index a9441dcda..f5610a2c5 100644 --- a/src/gui/scan.h +++ b/src/gui/scan.h @@ -71,7 +71,7 @@ class CScanTs : public CMenuTarget void paintLineLocale(int x, int * y, int width, const neutrino_locale_t l); void paintLine(int x, int y, int width, const char * const txt); void paintRadar(void); - int handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data); + neutrino_msg_t handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data); int greater_xpos(int xpos, const neutrino_locale_t txt); void showSNR(); void testFunc(); diff --git a/src/gui/scan_setup.cpp b/src/gui/scan_setup.cpp index 5ad95d794..516d873b9 100644 --- a/src/gui/scan_setup.cpp +++ b/src/gui/scan_setup.cpp @@ -9,6 +9,7 @@ Copyright (C) 2011 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2011-2015 Stefan Seyfried Copyright (C) 2011-2014 CoolStream International Ltd License: GPL @@ -158,7 +159,11 @@ const CMenuOptionChooser::keyval CABLESETUP_SCANTP_FEC[CABLESETUP_SCANTP_FEC_COU }; #endif +#if _HAVE_DVB57 #define TERRSETUP_SCANTP_FEC_COUNT 9 +#else +#define TERRSETUP_SCANTP_FEC_COUNT 8 +#endif const CMenuOptionChooser::keyval TERRSETUP_SCANTP_FEC[TERRSETUP_SCANTP_FEC_COUNT] = { // DVB-T @@ -169,37 +174,51 @@ const CMenuOptionChooser::keyval TERRSETUP_SCANTP_FEC[TERRSETUP_SCANTP_FEC_COUNT { FEC_7_8, LOCALE_EXTRA_FEC_7_8 }, { FEC_AUTO, LOCALE_EXTRA_FEC_AUTO }, // DTMB ie +#if _HAVE_DVB57 { FEC_2_5, LOCALE_EXTRA_FEC_2_5 }, +#endif { FEC_3_5, LOCALE_EXTRA_FEC_3_5 }, { FEC_4_5, LOCALE_EXTRA_FEC_4_5 }, }; +#if _HAVE_DVB57 #define TERRSETUP_SCANTP_BW_COUNT 7 +#else +#define TERRSETUP_SCANTP_BW_COUNT 4 +#endif const CMenuOptionChooser::keyval TERRSETUP_SCANTP_BW[TERRSETUP_SCANTP_BW_COUNT] = { { BANDWIDTH_8_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_8MHZ }, { BANDWIDTH_7_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_7MHZ }, { BANDWIDTH_6_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_6MHZ }, +#if _HAVE_DVB57 { BANDWIDTH_5_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_5MHZ }, { BANDWIDTH_10_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_10MHZ }, { BANDWIDTH_1_712_MHZ, LOCALE_EXTRA_TP_BANDWIDTH_1_712MHZ }, +#endif { BANDWIDTH_AUTO, LOCALE_EXTRA_TP_BANDWIDTH_AUTO } }; +#if _HAVE_DVB57 #define TERRSETUP_SCANTP_GI_COUNT 11 +#else +#define TERRSETUP_SCANTP_GI_COUNT 5 +#endif const CMenuOptionChooser::keyval TERRSETUP_SCANTP_GI[TERRSETUP_SCANTP_GI_COUNT] = { { GUARD_INTERVAL_1_4, LOCALE_EXTRA_TP_GI_1_4 }, { GUARD_INTERVAL_1_8, LOCALE_EXTRA_TP_GI_1_8 }, { GUARD_INTERVAL_1_16, LOCALE_EXTRA_TP_GI_1_16 }, { GUARD_INTERVAL_1_32, LOCALE_EXTRA_TP_GI_1_32 }, +#if _HAVE_DVB57 { GUARD_INTERVAL_1_128, LOCALE_EXTRA_TP_GI_1_128 }, { GUARD_INTERVAL_19_128, LOCALE_EXTRA_TP_GI_19_128 }, { GUARD_INTERVAL_19_256, LOCALE_EXTRA_TP_GI_19_256 }, { GUARD_INTERVAL_PN420, LOCALE_EXTRA_TP_GI_PN420 }, { GUARD_INTERVAL_PN595, LOCALE_EXTRA_TP_GI_PN595 }, { GUARD_INTERVAL_PN945, LOCALE_EXTRA_TP_GI_PN945 }, +#endif { GUARD_INTERVAL_AUTO, LOCALE_EXTRA_TP_GI_AUTO } }; @@ -213,17 +232,25 @@ const CMenuOptionChooser::keyval TERRSETUP_SCANTP_HIERARCHY[TERRSETUP_SCANTP_HIE { HIERARCHY_AUTO, LOCALE_EXTRA_TP_HIERARCHY_AUTO } }; +#if _HAVE_DVB57 #define TERRSETUP_SCANTP_TRANSMIT_MODE_COUNT 9 +#else +#define TERRSETUP_SCANTP_TRANSMIT_MODE_COUNT 4 +#endif const CMenuOptionChooser::keyval TERRSETUP_SCANTP_TRANSMIT_MODE[TERRSETUP_SCANTP_TRANSMIT_MODE_COUNT] = { +#if _HAVE_DVB57 { TRANSMISSION_MODE_1K, LOCALE_EXTRA_TP_TRANSMIT_MODE_1K }, +#endif { TRANSMISSION_MODE_2K, LOCALE_EXTRA_TP_TRANSMIT_MODE_2K }, { TRANSMISSION_MODE_4K, LOCALE_EXTRA_TP_TRANSMIT_MODE_4K }, { TRANSMISSION_MODE_8K, LOCALE_EXTRA_TP_TRANSMIT_MODE_8K }, +#if _HAVE_DVB57 { TRANSMISSION_MODE_16K, LOCALE_EXTRA_TP_TRANSMIT_MODE_16K }, { TRANSMISSION_MODE_32K, LOCALE_EXTRA_TP_TRANSMIT_MODE_32K }, { TRANSMISSION_MODE_C1, LOCALE_EXTRA_TP_TRANSMIT_MODE_C1 }, { TRANSMISSION_MODE_C3780, LOCALE_EXTRA_TP_TRANSMIT_MODE_C3780 }, +#endif { TRANSMISSION_MODE_AUTO, LOCALE_EXTRA_TP_TRANSMIT_MODE_AUTO } }; @@ -246,14 +273,20 @@ const CMenuOptionChooser::keyval CABLESETUP_SCANTP_MOD[CABLESETUP_SCANTP_MOD_COU { QAM_AUTO, LOCALE_EXTRA_TP_MOD_AUTO } }; +#if _HAVE_DVB57 #define TERRSETUP_SCANTP_MOD_COUNT 6 +#else +#define TERRSETUP_SCANTP_MOD_COUNT 5 +#endif const CMenuOptionChooser::keyval TERRSETUP_SCANTP_MOD[TERRSETUP_SCANTP_MOD_COUNT] = { { QPSK, LOCALE_EXTRA_TP_MOD_4 }, { QAM_16, LOCALE_EXTRA_TP_MOD_16 }, { QAM_32, LOCALE_EXTRA_TP_MOD_32 }, { QAM_64, LOCALE_EXTRA_TP_MOD_64 }, +#if _HAVE_DVB57 { QAM_4_NR, LOCALE_EXTRA_TP_MOD_4_NR }, +#endif { QAM_AUTO, LOCALE_EXTRA_TP_MOD_AUTO } }; @@ -1298,14 +1331,16 @@ int CScanSetup::showScanMenuSatFind() //init tempsat menu void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t & satconfig) { + bool unicable = (dmode == DISEQC_UNICABLE); temp_sat->addIntroItems(); + CMenuOptionNumberChooser *diseqc = NULL; - CMenuOptionNumberChooser *comm = NULL; + CMenuOptionNumberChooser *comm = NULL; CMenuOptionNumberChooser *uncomm = NULL; CMenuOptionNumberChooser *unilnb = NULL; - CMenuOptionNumberChooser *motor = NULL; - CMenuOptionChooser *usals = NULL; - bool unicable = (dmode == DISEQC_UNICABLE); + CMenuOptionNumberChooser *motor = NULL; + CMenuOptionChooser *usals = NULL; + CMenuForwarder *mf; if (!unicable) { diseqc = new CMenuOptionNumberChooser(LOCALE_SATSETUP_DISEQC_INPUT, &satconfig.diseqc, ((dmode != NO_DISEQC) && (dmode != DISEQC_ADVANCED)), -1, 15, this, CRCInput::RC_nokey, NULL, 1, -1, LOCALE_OPTIONS_OFF); @@ -1316,7 +1351,7 @@ void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t & satcon uncomm->setHint("", LOCALE_MENU_HINT_SCAN_UNCOMMITED); motor = new CMenuOptionNumberChooser(LOCALE_SATSETUP_MOTOR_POS, &satconfig.motor_position, true /*dmode == DISEQC_ADVANCED*/, 0, 64, this, CRCInput::RC_nokey, NULL, 0, 0, LOCALE_OPTIONS_OFF); motor->setHint("", LOCALE_MENU_HINT_SCAN_MOTORPOS); - usals = new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, &satconfig.use_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true /*dmode == DISEQC_ADVANCED*/); + usals = new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, &satconfig.use_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true /*dmode == DISEQC_ADVANCED*/); usals->setHint("", LOCALE_MENU_HINT_SCAN_USEUSALS); } else { if (satconfig.diseqc < 0) @@ -1338,7 +1373,7 @@ void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t & satcon temp_sat->addItem(unilnb); } - CMenuForwarder * mf = new CMenuDForwarder(LOCALE_SATSETUP_LOFL, true, lofL->getValue(), lofL); + mf = new CMenuDForwarder(LOCALE_SATSETUP_LOFL, true, lofL->getValue(), lofL); mf->setHint("", LOCALE_MENU_HINT_SCAN_LOFL); temp_sat->addItem(mf); mf = new CMenuDForwarder(LOCALE_SATSETUP_LOFH, true, lofH->getValue(), lofH); diff --git a/src/gui/scan_setup.h b/src/gui/scan_setup.h index bb1432de8..f7110ccb9 100644 --- a/src/gui/scan_setup.h +++ b/src/gui/scan_setup.h @@ -42,7 +42,7 @@ #define scansettings CNeutrinoApp::getInstance()->getScanSettings() -#define ENABLE_FASTSCAN //don't define this to remove fast scan menu +//#define ENABLE_FASTSCAN //don't define this to remove fast scan menu class CScanSetup : public CMenuTarget, public CChangeObserver { diff --git a/src/gui/settings_manager.cpp b/src/gui/settings_manager.cpp index d2e574eaf..dfc342e41 100644 --- a/src/gui/settings_manager.cpp +++ b/src/gui/settings_manager.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include diff --git a/src/gui/start_wizard.cpp b/src/gui/start_wizard.cpp index 993c5a80d..ee8e55b2d 100644 --- a/src/gui/start_wizard.cpp +++ b/src/gui/start_wizard.cpp @@ -93,11 +93,17 @@ int CStartUpWizard::exec(CMenuTarget* parent, const string & /*actionKey*/) languageSettings.showLanguageSetup(&osdl_setup); osdl_setup.exec(NULL, ""); + /* hack to ensure system's view of timezone is the same as neutrino's */ + CTZChangeNotifier tzn; + tzn.changeNotify(NONEXISTANT_LOCALE, (void *)"dummy"); + //restore backup CSettingsManager settingsManager(SNeutrinoSettings::WIZARD_START); settingsManager.exec(NULL, ""); +#if 0 if(ShowMsg (LOCALE_WIZARD_WELCOME_HEAD, g_Locale->getText(LOCALE_WIZARD_WELCOME_TEXT), CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbrCancel) == CMessageBox::mbrYes) +#endif { int advanced = 1; #ifdef ENABLE_FASTSCAN diff --git a/src/gui/streaminfo2.cpp b/src/gui/streaminfo2.cpp index 6e62aba60..a410be4e8 100644 --- a/src/gui/streaminfo2.cpp +++ b/src/gui/streaminfo2.cpp @@ -1,6 +1,9 @@ /* Neutrino-GUI - DBoxII-Project + (C) 2004-2009 tuxbox project contributors + + (C) 2011-2012,2015 Stefan Seyfried License: GPL @@ -33,6 +36,7 @@ #include #include +#include #include #include #include @@ -135,15 +139,17 @@ int CStreamInfo2::doSignalStrengthLoop () neutrino_msg_t msg; uint64_t maxb, minb, lastb, tmp_rate; - unsigned int current_pmt_version= pmt_version; + unsigned int current_pmt_version = (unsigned int)-1; int cnt = 0; - char tmp_str[150]; int delay_counter = 0; const int delay = 15; - int offset = g_Font[font_info]->getRenderWidth(g_Locale->getText (LOCALE_STREAMINFO_BITRATE)); int sw = g_Font[font_info]->getRenderWidth ("99999.999"); - int dheight = g_Font[font_info]->getHeight (); //NI maxb = minb = lastb = tmp_rate = 0; + string br_str = string(g_Locale->getText(LOCALE_STREAMINFO_BITRATE)) + ":"; + string avg_str = "(" + string(g_Locale->getText(LOCALE_STREAMINFO_AVERAGE_BITRATE)) + ")"; + int offset = g_Font[font_info]->getRenderWidth(avg_str); + int dheight = g_Font[font_info]->getHeight (); + int dx1 = x + 10; ts_setup (); while (1) { neutrino_msg_data_t data; @@ -182,26 +188,25 @@ int CStreamInfo2::doSignalStrengthLoop () rate.min_short_average = minb = bit_s; char currate[150]; - snprintf(tmp_str,sizeof(tmp_str), "%s:",g_Locale->getText(LOCALE_STREAMINFO_BITRATE)); - g_Font[font_info]->RenderString(dx1 , average_bitrate_pos, offset+10, tmp_str, COL_MENUCONTENT_TEXT); - - sprintf(currate, "%5llu.%02llu", rate.short_average / 1000ULL, rate.short_average % 1000ULL); + sprintf(currate, "%u", rate.short_average / 1000); + g_Font[font_info]->RenderString(dx1, average_bitrate_pos, width/2, br_str, COL_MENUCONTENT_TEXT); + g_Font[font_info]->RenderString(dx1+average_bitrate_offset+sw+10 , average_bitrate_pos, offset, avg_str, COL_MENUCONTENT_TEXT); frameBuffer->paintBoxRel (dx1 + average_bitrate_offset , average_bitrate_pos -dheight, sw, dheight, COL_MENUCONTENT_PLUS_0); - - g_Font[font_info]->RenderString (dx1 + average_bitrate_offset , average_bitrate_pos, sw - 10, currate, COL_MENUCONTENT_TEXT); - - snprintf(tmp_str,sizeof(tmp_str), "(%s)",g_Locale->getText(LOCALE_STREAMINFO_AVERAGE_BITRATE)); - g_Font[font_info]->RenderString (dx1 + average_bitrate_offset + sw , average_bitrate_pos, sw *2, tmp_str, COL_MENUCONTENT_TEXT); - + g_Font[font_info]->RenderString(dx1+average_bitrate_offset, average_bitrate_pos, sw, currate, COL_MENUCONTENT_TEXT); } if (!mp) { showSNR (); - if(pmt_version != current_pmt_version && delay_counter > delay){ - current_pmt_version = pmt_version; - paint_techinfo (x + 10, y+ hheight +5); + if (++delay_counter > delay) { + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if (channel) + pmt_version = channel->getPmtVersion(); + delay_counter = 0; + if (pmt_version != current_pmt_version && delay_counter > delay){ + current_pmt_version = pmt_version; + paint_techinfo(dx1, y + hheight + 5); + } } } - delay_counter++; } rate.short_average = abit_s; if (signal.max_ber < signal.ber) @@ -228,6 +233,10 @@ int CStreamInfo2::doSignalStrengthLoop () signal.old_snr = signal.snr; signal.old_ber = signal.ber; + neutrino_msg_data_t data; + /* rate limiting is done in update_rate */ + g_RCInput->getMsg_us(&msg, &data, 0); + // switch paint mode if (msg == CRCInput::RC_red || msg == CRCInput::RC_blue || msg == CRCInput::RC_green || msg == CRCInput::RC_yellow) { hide (); @@ -468,7 +477,7 @@ void CStreamInfo2::paint (int /*mode*/) pip->paint(CC_SAVE_SCREEN_NO); paint_techinfo (xpos, ypos); - paint_signal_fe_box (width - width/3 - 10, (y + 10 + height/3 + hheight), width/3, height/3 + hheight); + paint_signal_fe_box (width - width/3 - 10, y + 10 + height/3, width/3, height/3 + hheight); } else { // -- small PIG, small signal graph // -- paint backround, title pig, etc. @@ -840,7 +849,6 @@ void CStreamInfo2::paintCASystem(int xpos, int ypos) } spaceoffset+=4; - ypos += iheight*2; bool cryptsysteme = true; for(int ca_id = 0; ca_id < NUM_CAIDS; ca_id++){ if(caids[ca_id] == true){ @@ -949,8 +957,7 @@ int CStreamInfo2::update_rate () int ret = 0; int timeout = 100; - int b_len; - + int b_len = 0; if(!dmx && !mp) return 0; @@ -958,7 +965,15 @@ int CStreamInfo2::update_rate () usleep(timeout * 1000); b_len = mp->GetReadCount(); } else { - b_len = dmx->Read(dmxbuf, TS_BUF_SIZE, timeout); + time_t start = time_monotonic_ms(); + /* always sample for ~100ms */ + while (time_monotonic_ms() - start < timeout) + { + ret = dmx->Read(dmxbuf, TS_BUF_SIZE, 10); + if (ret >= 0) + b_len += ret; + } + //printf("ts: read %d time %d\n", b_len, time_monotonic_ms() - start); } //printf("ts: read %d\n", b_len); @@ -988,8 +1003,8 @@ int CStreamInfo2::update_rate () last_tv.tv_sec = tv.tv_sec; last_tv.tv_usec = tv.tv_usec; - ret = 1; - return ret; + + return 1; } int CStreamInfo2::ts_close () @@ -1005,9 +1020,15 @@ int CStreamInfo2::ts_close () void CStreamInfo2::showSNR () { + /* sig_text_y + sheight + 4 + 5 is upper limit of ber/snr/sig numbers + * sheight*3 is 3x sig numbers + 1/2 sheight */ + int snr_y = sig_text_y + 4+5 + sheight*9 / 2; + int snr_h = 50; + if (snr_y + snr_h > max_height - 10) + return; if (signalbox == NULL) { - signalbox = new CSignalBox(x + 10, yypos, 240, 50, frontend); + signalbox = new CSignalBox(sigBox_x, snr_y, 240, snr_h, frontend); signalbox->setColorBody(COL_MENUCONTENT_PLUS_0); signalbox->setTextColor(COL_MENUCONTENT_TEXT); signalbox->doPaintBg(true); diff --git a/src/gui/test_menu.cpp b/src/gui/test_menu.cpp index 2ad4e0734..bda48c198 100644 --- a/src/gui/test_menu.cpp +++ b/src/gui/test_menu.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -58,7 +59,9 @@ #include #include +#if HAVE_COOL_HARDWARE extern int cs_test_card(int unit, char * str); +#endif #define TestButtonsCount 4 const struct button_label TestButtons[/*TestButtonsCount*/] = @@ -189,6 +192,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) return res; } +#if HAVE_COOL_HARDWARE else if (actionKey == "card0") { char str[255]; @@ -235,6 +239,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) return res; } +#endif else if (actionKey == "hdd") { char buffer[255]; @@ -799,8 +804,10 @@ void CTestMenu::showHWTests(CMenuWidget *widget) widget->addIntroItems(); widget->addItem(new CMenuForwarder("VFD", true, NULL, this, "vfd")); widget->addItem(new CMenuForwarder("Network", true, NULL, this, "network")); +#if HAVE_COOL_HARDWARE widget->addItem(new CMenuForwarder("Smartcard 1", true, NULL, this, "card0")); widget->addItem(new CMenuForwarder("Smartcard 2", true, NULL, this, "card1")); +#endif widget->addItem(new CMenuForwarder("HDD", true, NULL, this, "hdd")); widget->addItem(new CMenuForwarder("SD/MMC", true, NULL, this, "mmc")); #if 0 //some parts DEPRECATED diff --git a/src/gui/update.cpp b/src/gui/update.cpp index dff219cb6..0c55442ad 100644 --- a/src/gui/update.cpp +++ b/src/gui/update.cpp @@ -594,6 +594,7 @@ int CFlashUpdate::exec(CMenuTarget* parent, const std::string &actionKey) #endif if(fileType < '3') { //flash it... +#if ENABLE_EXTUPDATE #ifndef BOXMODEL_APOLLO if (g_settings.apply_settings) { if (ShowMsg(LOCALE_MESSAGEBOX_INFO, g_Locale->getText(LOCALE_FLASHUPDATE_APPLY_SETTINGS), CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbNo, NEUTRINO_ICON_UPDATE) == CMessageBox::mbrYes) @@ -603,6 +604,7 @@ int CFlashUpdate::exec(CMenuTarget* parent, const std::string &actionKey) } } #endif +#endif #ifdef DEBUG1 if(1) { @@ -813,6 +815,8 @@ void CFlashExpert::readmtd(int preadmtd) netGetHostname(hostName); std::string timeStr = getNowTimeStr("_%Y%m%d_%H%M"); std::string tankStr = ""; + +#if ENABLE_EXTUPDATE #ifdef BOXMODEL_APOLLO int eSize = CMTDInfo::getInstance()->getMTDEraseSize(CMTDInfo::getInstance()->findMTDsystem()); if (preadmtd == 0) { @@ -829,6 +833,7 @@ void CFlashExpert::readmtd(int preadmtd) if (g_settings.softupdate_name_mode_backup == CExtUpdate::SOFTUPDATE_NAME_HOSTNAME_TIME) filename = (std::string)g_settings.update_dir + "/" + mtdInfo->getMTDName(preadmtd) + timeStr + "_" + hostName + tankStr + ".img"; else +#endif filename = (std::string)g_settings.update_dir + "/" + mtdInfo->getMTDName(preadmtd) + timeStr + tankStr + ".img"; #ifdef BOXMODEL_APOLLO @@ -968,9 +973,11 @@ int CFlashExpert::showMTDSelector(const std::string & actionkey) sprintf(sActionKey, "%s%d", actionkey.c_str(), lx); mtdselector->addItem(new CMenuForwarder(mtdInfo->getMTDName(lx).c_str(), enabled, NULL, this, sActionKey, CRCInput::convertDigitToKey(shortcut++))); } +#if ENABLE_EXTUPDATE #ifndef BOXMODEL_APOLLO if (actionkey == "writemtd") mtdselector->addItem(new CMenuForwarder("systemFS with settings", true, NULL, this, "writemtd10", CRCInput::convertDigitToKey(shortcut++))); +#endif #endif int res = mtdselector->exec(NULL,""); delete mtdselector; @@ -1040,11 +1047,14 @@ int CFlashExpert::exec(CMenuTarget* parent, const std::string & actionKey) selectedMTD = iWritemtd; showFileSelector(""); } else { +#if ENABLE_EXTUPDATE if(selectedMTD == 10) { std::string aK = actionKey; CExtUpdate::getInstance()->applySettings(aK, CExtUpdate::MODE_EXPERT); } - else if(selectedMTD==-1) { + else +#endif + if (selectedMTD == -1) { writemtd(actionKey, MTD_OF_WHOLE_IMAGE); } else { writemtd(actionKey, selectedMTD); diff --git a/src/gui/update_ext.h b/src/gui/update_ext.h index c33d8c4f8..ff3d301c3 100644 --- a/src/gui/update_ext.h +++ b/src/gui/update_ext.h @@ -27,6 +27,7 @@ #ifndef __CEXTUPDATE__ #define __CEXTUPDATE__ +#if ENABLE_EXTUPDATE #include #include @@ -120,4 +121,6 @@ static unsigned int timer_msec; snprintf(updateLogBuf, sizeof(updateLogBuf), "[update:%d] " fmt, __LINE__ , ## args); \ updateLog(updateLogBuf); +#endif + #endif // __CEXTUPDATE__ diff --git a/src/gui/update_settings.cpp b/src/gui/update_settings.cpp index 9497add6a..26872a18c 100644 --- a/src/gui/update_settings.cpp +++ b/src/gui/update_settings.cpp @@ -67,6 +67,7 @@ const CMenuOptionChooser::keyval FLASHUPDATE_UPDATEMODE_OPTIONS[FLASHUPDATE_UPDA { 1, LOCALE_FLASHUPDATE_UPDATEMODE_INTERNET } }; +#if ENABLE_EXTUPDATE #define SOFTUPDATE_NAME_MODE1_OPTION_COUNT 3 const CMenuOptionChooser::keyval SOFTUPDATE_NAME_MODE1_OPTIONS[SOFTUPDATE_NAME_MODE1_OPTION_COUNT] = { @@ -81,6 +82,7 @@ const CMenuOptionChooser::keyval SOFTUPDATE_NAME_MODE2_OPTIONS[SOFTUPDATE_NAME_M { CExtUpdate::SOFTUPDATE_NAME_DEFAULT, LOCALE_FLASHUPDATE_NAMEMODE2_DEFAULT }, { CExtUpdate::SOFTUPDATE_NAME_HOSTNAME_TIME, LOCALE_FLASHUPDATE_NAMEMODE2_HOSTNAME_TIME } }; +#endif int CUpdateSettings::exec(CMenuTarget* parent, const std::string &actionKey) { @@ -128,6 +130,7 @@ int CUpdateSettings::initMenu() // fw_url->setHint("", LOCALE_MENU_HINT_XXX); CMenuForwarder * fw_update_dir = new CMenuForwarder(LOCALE_EXTRA_UPDATE_DIR, true, g_settings.update_dir , this, "update_dir", CRCInput::RC_red); // fw_update_dir->setHint("", LOCALE_MENU_HINT_XXX); +#if ENABLE_EXTUPDATE CMenuOptionChooser *name_backup = new CMenuOptionChooser(LOCALE_FLASHUPDATE_NAMEMODE2, &g_settings.softupdate_name_mode_backup, SOFTUPDATE_NAME_MODE2_OPTIONS, SOFTUPDATE_NAME_MODE2_OPTION_COUNT, true); // name_backup->setHint("", LOCALE_MENU_HINT_XXX); @@ -139,6 +142,7 @@ int CUpdateSettings::initMenu() // name_apply->setHint("", LOCALE_MENU_HINT_XXX); OnOffNotifier->addItem(name_apply); #endif +#endif #if 0 CMenuOptionChooser *apply_kernel = new CMenuOptionChooser(LOCALE_FLASHUPDATE_MENU_APPLY_KERNEL, &g_settings.apply_kernel, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, g_settings.apply_settings); @@ -151,11 +155,13 @@ int CUpdateSettings::initMenu() w_upsettings.addItem(fw_update_dir); w_upsettings.addItem(fw_url); +#if ENABLE_EXTUPDATE w_upsettings.addItem(name_backup); #ifndef BOXMODEL_APOLLO w_upsettings.addItem(GenericMenuSeparatorLine); w_upsettings.addItem(apply_settings); w_upsettings.addItem(name_apply); +#endif #endif w_upsettings.addItem(autocheck); diff --git a/src/gui/user_menue.cpp b/src/gui/user_menue.cpp index 652cddd27..f35c37f89 100644 --- a/src/gui/user_menue.cpp +++ b/src/gui/user_menue.cpp @@ -11,6 +11,7 @@ Copyright (C) 2011 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2013-2014 Stefan Seyfried License: GPL @@ -407,7 +408,7 @@ bool CUserMenu::showUserMenu(neutrino_msg_t msg) menu_item->setHint(NEUTRINO_ICON_HINT_NKPLAY, LOCALE_MENU_HINT_NKPLAY); break; #endif -#if HAVE_SPARK_HARDWARE +#if 0 case SNeutrinoSettings::ITEM_THREE_D_MODE: keyhelper.get(&key,&icon); menu_item = new CMenuForwarder(LOCALE_THREE_D_SETTINGS, true, NULL, neutrino, "3dmode", key, icon); diff --git a/src/gui/user_menue_setup.cpp b/src/gui/user_menue_setup.cpp index e922b017e..9bccbfb84 100644 --- a/src/gui/user_menue_setup.cpp +++ b/src/gui/user_menue_setup.cpp @@ -11,6 +11,7 @@ Copyright (C) 2010 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2014 Stefan Seyfried License: GPL diff --git a/src/gui/vfd_setup.cpp b/src/gui/vfd_setup.cpp index 4de1c2414..d2b5a199c 100644 --- a/src/gui/vfd_setup.cpp +++ b/src/gui/vfd_setup.cpp @@ -45,6 +45,7 @@ #include #include +#include #include #include diff --git a/src/gui/videosettings.cpp b/src/gui/videosettings.cpp index 144d6bfa1..53b956bb9 100644 --- a/src/gui/videosettings.cpp +++ b/src/gui/videosettings.cpp @@ -10,6 +10,8 @@ Copyright (C) 2009 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2010-2012 Stefan Seyfried + License: GPL This program is free software; you can redistribute it and/or modify @@ -47,6 +49,7 @@ #include #include +#include #include @@ -55,7 +58,9 @@ #include #include +#ifdef BOXMODEL_APOLLO #include +#endif extern cVideo *videoDecoder; #ifdef ENABLE_PIP @@ -114,6 +119,15 @@ const CMenuOptionChooser::keyval VIDEOMENU_43MODE_OPTIONS[] = }; #define VIDEOMENU_43MODE_OPTION_COUNT (sizeof(VIDEOMENU_43MODE_OPTIONS)/sizeof(CMenuOptionChooser::keyval)) +#ifndef BOXMODEL_APOLLO +#define VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT 2 +const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_TD_OPTIONS[VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT] = +{ + { ANALOG_SD_RGB_SCART, LOCALE_VIDEOMENU_ANALOG_SD_RGB_SCART }, + { ANALOG_SD_YPRPB_SCART, LOCALE_VIDEOMENU_ANALOG_SD_YPRPB_SCART } +}; +#endif + #ifdef ANALOG_MODE #define VIDEOMENU_VIDEOSIGNAL_HD1_OPTION_COUNT 8 const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_HD1_OPTIONS[VIDEOMENU_VIDEOSIGNAL_HD1_OPTION_COUNT] = @@ -189,6 +203,28 @@ const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_HD1PLUS_CINCH_OPTIONS[VID }; #endif +/* + * key value of -1 means the mode is not available + * TODO: instead of #ifdef select at run time + */ +#if HAVE_TRIPLEDRAGON +CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = +{ + { VIDEO_STD_SECAM, NONEXISTANT_LOCALE, "SECAM" }, + { VIDEO_STD_PAL, NONEXISTANT_LOCALE, "PAL" }, + { -1, NONEXISTANT_LOCALE, "576p" }, + { -1, NONEXISTANT_LOCALE, "720p 50Hz" }, + { -1, NONEXISTANT_LOCALE, "1080i 50Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 24Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 25Hz" }, + { VIDEO_STD_NTSC, NONEXISTANT_LOCALE, "NTSC" }, + { -1, NONEXISTANT_LOCALE, "480p" }, + { -1, NONEXISTANT_LOCALE, "720p 60Hz" }, + { -1, NONEXISTANT_LOCALE, "1080i 60Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 50Hz" }, + { -1, NONEXISTANT_LOCALE, "Auto" } +}; +#elif HAVE_COOL_HARDWARE /* numbers corresponding to video.cpp from zapit */ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = { @@ -199,6 +235,8 @@ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_O { VIDEO_STD_1080I50, NONEXISTANT_LOCALE, "1080i 50Hz" }, #ifdef BOXMODEL_APOLLO { VIDEO_STD_1080P50, NONEXISTANT_LOCALE, "1080p 50Hz" }, +#else + { -1, NONEXISTANT_LOCALE, "1080p 50Hz" }, #endif { VIDEO_STD_1080P24, NONEXISTANT_LOCALE, "1080p 24Hz" }, { VIDEO_STD_1080P25, NONEXISTANT_LOCALE, "1080p 25Hz" }, @@ -207,19 +245,63 @@ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_O { VIDEO_STD_720P60, NONEXISTANT_LOCALE, "720p 60Hz" }, { VIDEO_STD_1080I60, NONEXISTANT_LOCALE, "1080i 60Hz" }, #ifdef BOXMODEL_APOLLO + /* TODO: fix this crap */ { VIDEO_STD_1080P60, NONEXISTANT_LOCALE, "1080p 60Hz" }, { VIDEO_STD_1080P2397, NONEXISTANT_LOCALE, "1080p 23.97Hz"}, { VIDEO_STD_1080P2997, NONEXISTANT_LOCALE, "1080p 29.97Hz"}, #endif { VIDEO_STD_AUTO, NONEXISTANT_LOCALE, "Auto" } }; +#elif HAVE_SPARK_HARDWARE || HAVE_AZBOX_HARDWARE +CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = +{ + { -1, NONEXISTANT_LOCALE, "SECAM" }, + { VIDEO_STD_PAL, NONEXISTANT_LOCALE, "PAL" }, + { VIDEO_STD_576P, NONEXISTANT_LOCALE, "576p" }, + { VIDEO_STD_720P50, NONEXISTANT_LOCALE, "720p 50Hz" }, + { VIDEO_STD_1080I50, NONEXISTANT_LOCALE, "1080i 50Hz" }, + { VIDEO_STD_1080P24, NONEXISTANT_LOCALE, "1080p 24Hz" }, + { VIDEO_STD_1080P25, NONEXISTANT_LOCALE, "1080p 25Hz" }, + { -1, NONEXISTANT_LOCALE, "NTSC" }, + { -1, NONEXISTANT_LOCALE, "480p" }, + { VIDEO_STD_720P60, NONEXISTANT_LOCALE, "720p 60Hz" }, + { VIDEO_STD_1080I60, NONEXISTANT_LOCALE, "1080i 60Hz" }, + { VIDEO_STD_1080P50, NONEXISTANT_LOCALE, "1080p 50Hz" }, + { -1, NONEXISTANT_LOCALE, "Auto" } +}; +#else +/* generic PC -> 4 different resolutions, 480, 576, 720 and 1080 lines */ +CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = +{ + { -1, NONEXISTANT_LOCALE, "SECAM" }, + { VIDEO_STD_PAL, NONEXISTANT_LOCALE, "PAL" }, + { -1, NONEXISTANT_LOCALE, "576p" }, + { VIDEO_STD_720P50, NONEXISTANT_LOCALE, "720p 50Hz" }, + { VIDEO_STD_1080I50, NONEXISTANT_LOCALE, "1080i 50Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 24Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 25Hz" }, + { VIDEO_STD_NTSC, NONEXISTANT_LOCALE, "NTSC" }, + { -1, NONEXISTANT_LOCALE, "480p" }, + { -1, NONEXISTANT_LOCALE, "720p 60Hz" }, + { -1, NONEXISTANT_LOCALE, "1080i 60Hz" }, + { -1, NONEXISTANT_LOCALE, "1080p 50Hz" }, + { -1, NONEXISTANT_LOCALE, "Auto" } +}; +#endif + +#if HAVE_TRIPLEDRAGON +#define VIDEOMENU_VIDEOFORMAT_OPTION_COUNT 2 +#else #define VIDEOMENU_VIDEOFORMAT_OPTION_COUNT 3//2 +#endif const CMenuOptionChooser::keyval VIDEOMENU_VIDEOFORMAT_OPTIONS[VIDEOMENU_VIDEOFORMAT_OPTION_COUNT] = { { DISPLAY_AR_4_3, LOCALE_VIDEOMENU_VIDEOFORMAT_43 }, { DISPLAY_AR_16_9, LOCALE_VIDEOMENU_VIDEOFORMAT_169 }, +#if !HAVE_TRIPLEDRAGON { DISPLAY_AR_14_9, LOCALE_VIDEOMENU_VIDEOFORMAT_149 } +#endif }; #define VIDEOMENU_DBDR_OPTION_COUNT 3 @@ -237,6 +319,16 @@ int CVideoSettings::showVideoSetup() videosetup->setSelected(selected); videosetup->setWizardMode(is_wizard); + CMenuOptionChooser::keyval_ext vmode_options[VIDEOMENU_VIDEOMODE_OPTION_COUNT]; + int vmode_option_count = 0; + for (int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) + { + if (VIDEOMENU_VIDEOMODE_OPTIONS[i].key == -1) + continue; + vmode_options[vmode_option_count] = VIDEOMENU_VIDEOMODE_OPTIONS[i]; + vmode_option_count++; + } + //analog options unsigned int system_rev = cs_get_revision(); CMenuOptionChooser * vs_analg_ch = NULL; @@ -261,6 +353,12 @@ int CVideoSettings::showVideoSetup() vs_chinch_ch->setHint("", LOCALE_MENU_HINT_VIDEO_CINCH_MODE); #endif } +#ifndef BOXMODEL_APOLLO + else if (g_info.hw_caps->has_SCART) /* TRIPLEDRAGON hack... :-) TODO: SPARK? */ + { + vs_scart_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_SCART, &g_settings.analog_mode1, VIDEOMENU_VIDEOSIGNAL_TD_OPTIONS, VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT, true, this); + } +#endif //4:3 mode CMenuOptionChooser * vs_43mode_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_43MODE, &g_settings.video_43mode, VIDEOMENU_43MODE_OPTIONS, VIDEOMENU_43MODE_OPTION_COUNT, true, this); @@ -271,44 +369,55 @@ int CVideoSettings::showVideoSetup() vs_dispformat_ch->setHint("", LOCALE_MENU_HINT_VIDEO_FORMAT); //video system - CMenuOptionChooser * vs_videomodes_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_VIDEOMODE, &g_settings.video_Mode, VIDEOMENU_VIDEOMODE_OPTIONS, VIDEOMENU_VIDEOMODE_OPTION_COUNT, true, this, CRCInput::RC_nokey, "", true); + CMenuOptionChooser * vs_videomodes_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_VIDEOMODE, &g_settings.video_Mode, vmode_options, vmode_option_count, true, this, CRCInput::RC_nokey, "", true); vs_videomodes_ch->setHint("", LOCALE_MENU_HINT_VIDEO_MODE); - CMenuOptionChooser * vs_dbdropt_ch = NULL; - CMenuForwarder * vs_videomodes_fw = NULL; + CMenuOptionChooser *vs_dbdropt_ch = NULL; CMenuWidget videomodes(LOCALE_MAINSETTINGS_VIDEO, NEUTRINO_ICON_SETTINGS); #ifdef BOXMODEL_APOLLO CMenuForwarder * vs_automodes_fw = NULL; CMenuWidget automodes(LOCALE_MAINSETTINGS_VIDEO, NEUTRINO_ICON_SETTINGS); #endif CAutoModeNotifier anotify; + CMenuForwarder *vs_videomodes_fw = NULL; if (!g_settings.easymenu) { //dbdr options - vs_dbdropt_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_DBDR, &g_settings.video_dbdr, VIDEOMENU_DBDR_OPTIONS, VIDEOMENU_DBDR_OPTION_COUNT, true, this); - vs_dbdropt_ch->setHint("", LOCALE_MENU_HINT_VIDEO_DBDR); + if (system_rev != 0x01) /* dbdr options only on COOLSTREAM */ + { + vs_dbdropt_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_DBDR, &g_settings.video_dbdr, VIDEOMENU_DBDR_OPTIONS, VIDEOMENU_DBDR_OPTION_COUNT, true, this); + vs_dbdropt_ch->setHint("", LOCALE_MENU_HINT_VIDEO_DBDR); + } //video system modes submenue - videomodes.addIntroItems(LOCALE_VIDEOMENU_ENABLED_MODES); + if (g_info.hw_caps->has_HDMI) /* does this make sense on a box without HDMI? */ + { + videomodes.addIntroItems(LOCALE_VIDEOMENU_ENABLED_MODES); - for (int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) - videomodes.addItem(new CMenuOptionChooser(VIDEOMENU_VIDEOMODE_OPTIONS[i].valname, &g_settings.enabled_video_modes[i], OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, &anotify)); + for (int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) + if (VIDEOMENU_VIDEOMODE_OPTIONS[i].key != -1) + videomodes.addItem(new CMenuOptionChooser(VIDEOMENU_VIDEOMODE_OPTIONS[i].valname, &g_settings.enabled_video_modes[i], OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, &anotify)); - vs_videomodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES, true, NULL, &videomodes, NULL, CRCInput::RC_red); - vs_videomodes_fw->setHint("", LOCALE_MENU_HINT_VIDEO_MODES); + vs_videomodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES, true, NULL, &videomodes, NULL, CRCInput::RC_red); + vs_videomodes_fw->setHint("", LOCALE_MENU_HINT_VIDEO_MODES); #ifdef BOXMODEL_APOLLO - automodes.addIntroItems(LOCALE_VIDEOMENU_ENABLED_MODES_AUTO); + automodes.addIntroItems(LOCALE_VIDEOMENU_ENABLED_MODES_AUTO); - for (int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT - 1; i++) - automodes.addItem(new CMenuOptionChooser(VIDEOMENU_VIDEOMODE_OPTIONS[i].valname, &g_settings.enabled_auto_modes[i], OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, &anotify)); + for (int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT - 1; i++) + automodes.addItem(new CMenuOptionChooser(VIDEOMENU_VIDEOMODE_OPTIONS[i].valname, &g_settings.enabled_auto_modes[i], OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, &anotify)); - vs_automodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES_AUTO, true, NULL, &automodes, NULL, CRCInput::RC_green); - vs_automodes_fw->setHint("", LOCALE_MENU_HINT_VIDEO_MODES_AUTO); + vs_automodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES_AUTO, true, NULL, &automodes, NULL, CRCInput::RC_green); + vs_automodes_fw->setHint("", LOCALE_MENU_HINT_VIDEO_MODES_AUTO); #endif + } } + neutrino_locale_t tmp_locale = NONEXISTANT_LOCALE; + /* TODO: check the locale */ + if (vs_analg_ch != NULL || vs_scart_ch != NULL || vs_chinch_ch != NULL) + tmp_locale = LOCALE_VIDEOMENU_TV_SCART; //--------------------------------------- - videosetup->addIntroItems(LOCALE_MAINSETTINGS_VIDEO /*, LOCALE_VIDEOMENU_TV_SCART*/); + videosetup->addIntroItems(LOCALE_MAINSETTINGS_VIDEO, tmp_locale); //--------------------------------------- //videosetup->addItem(vs_scart_sep); //separator scart if (vs_analg_ch != NULL) @@ -317,14 +426,17 @@ int CVideoSettings::showVideoSetup() videosetup->addItem(vs_scart_ch); //scart if (vs_chinch_ch != NULL) videosetup->addItem(vs_chinch_ch);//chinch - //videosetup->addItem(GenericMenuSeparatorLine); + //if (tmp_locale != NONEXISTANT_LOCALE) + // videosetup->addItem(GenericMenuSeparatorLine); //--------------------------------------- videosetup->addItem(vs_43mode_ch); //4:3 mode videosetup->addItem(vs_dispformat_ch); //display format videosetup->addItem(vs_videomodes_ch); //video system if (!g_settings.easymenu) { - videosetup->addItem(vs_dbdropt_ch); //dbdr options - videosetup->addItem(vs_videomodes_fw); //video modes submenue + if (vs_dbdropt_ch != NULL) + videosetup->addItem(vs_dbdropt_ch); //dbdr options + if (vs_videomodes_fw != NULL) + videosetup->addItem(vs_videomodes_fw); //video modes submenue #ifdef BOXMODEL_APOLLO videosetup->addItem(vs_automodes_fw); //video auto modes submenue #endif @@ -589,6 +701,8 @@ void CVideoSettings::nextMode(void) curmode++; if (curmode >= VIDEOMENU_VIDEOMODE_OPTION_COUNT) curmode = 0; + if (VIDEOMENU_VIDEOMODE_OPTIONS[curmode].key == -1) + continue; if (g_settings.enabled_video_modes[curmode]) break; i++; diff --git a/src/gui/widget/buttons.cpp b/src/gui/widget/buttons.cpp index a427be80a..f85af5a52 100644 --- a/src/gui/widget/buttons.cpp +++ b/src/gui/widget/buttons.cpp @@ -30,7 +30,7 @@ #include #include #include -// #include +#include @@ -133,7 +133,7 @@ int paintButtons( const button_label_ext * const content, if (count > 16 || count == 0) { fprintf(stderr, "paintButtons does only support max 16 buttons yet (%d)\n", count); -// print_stacktrace(); + print_stacktrace(); return 0; } if (maxwidth < 200 && show) @@ -349,7 +349,7 @@ int paintButtons( const int &x, fprintf(stderr, "paintButtons: maxwidth very small\n"); fprintf(stderr, " x: %d y: %d footw: %d count: %d maxw: %d footh: %d\n ", x, y, footerwidth, count, maxwidth, footerheight); - //print_stacktrace(); + print_stacktrace(); } uint i; diff --git a/src/gui/widget/listbox.cpp b/src/gui/widget/listbox.cpp index 0ddf8d791..3672f0cd1 100644 --- a/src/gui/widget/listbox.cpp +++ b/src/gui/widget/listbox.cpp @@ -71,13 +71,11 @@ void CListBox::paint() frameBuffer->paintBoxRel(x+ width- 15,ypos, 15, sb, COL_MENUCONTENT_PLUS_1); int sbc= ((getItemCount()- 1)/ listmaxshow)+ 1; + int sbs= (selected/listmaxshow); if (sbc < 1) sbc = 1; - int sbh= (sb- 4)/ sbc; - int sbs= (selected/listmaxshow); - - frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ sbs* sbh , 11, sbh, COL_MENUCONTENT_PLUS_3); + frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ sbs * (sb-4)/sbc, 11, (sb-4)/sbc, COL_MENUCONTENT_PLUS_3); } void CListBox::paintHead() diff --git a/src/gui/widget/listhelpers.cpp b/src/gui/widget/listhelpers.cpp index 45af70358..0f7c19724 100644 --- a/src/gui/widget/listhelpers.cpp +++ b/src/gui/widget/listhelpers.cpp @@ -33,7 +33,7 @@ static int upDownKey(int size, neutrino_msg_t msg, int lines, int sel) return -1; if (msg >= CRCInput::RC_MaxRC) { - printf("CListHelpers:%s: invalid key? 0x%X\n", __func__, msg); + printf("CListHelpers:%s: invalid key? 0x%X\n", __func__, (uint32_t)msg); return -1; } int key = (int)msg; @@ -46,7 +46,7 @@ static int upDownKey(int size, neutrino_msg_t msg, int lines, int sel) else if (msg == CRCInput::RC_down) step = 1; else { - printf("CListHelpers:%s: invalid key? 0x%X\n", __func__, msg); + printf("CListHelpers:%s: invalid key? 0x%X\n", __func__, (uint32_t)msg); return -1; } // printf("CListHelpers:%s: key 0x%04lx lines %d size %d sel %d\n", __func__, msg, lines, size, sel); diff --git a/src/gui/widget/menue.cpp b/src/gui/widget/menue.cpp index aadba4ecd..02f8c5dab 100644 --- a/src/gui/widget/menue.cpp +++ b/src/gui/widget/menue.cpp @@ -820,7 +820,6 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) paint(); break; } - frameBuffer->blit(); continue; } for (unsigned int i= 0; i< items.size(); i++) { @@ -2373,6 +2372,7 @@ bool CZapProtection::check() hint = NONEXISTANT_LOCALE; int res; std::string cPIN; + char systemstr[128]; do { cPIN = ""; @@ -2381,10 +2381,11 @@ bool CZapProtection::check() res = PINInput->exec(getParent(), ""); delete PINInput; - if (!access(CONFIGDIR "/pinentered.sh", X_OK)) { - std::string systemstr = CONFIGDIR "/pinentered.sh " + cPIN; - system(systemstr.c_str()); - } + cPIN[4] = 0; + strcpy(systemstr, CONFIGDIR "/pinentered.sh "); + strcat(systemstr, cPIN.c_str()); + system(systemstr); + hint = LOCALE_PINPROTECTION_WRONGCODE; } while ( (cPIN != *validPIN) && !cPIN.empty() && ( res == menu_return::RETURN_REPAINT ) && diff --git a/src/gui/widget/msgbox.cpp b/src/gui/widget/msgbox.cpp index 503e79233..96c273dbc 100644 --- a/src/gui/widget/msgbox.cpp +++ b/src/gui/widget/msgbox.cpp @@ -851,11 +851,11 @@ int ShowMsg2UTF( const char * const Title, int mode = CMsgBox::SCROLL | CMsgBox::TITLE | CMsgBox::FOOT | - CMsgBox::BORDER;// | + CMsgBox::BORDER | + CMsgBox::AUTO_HIGH; //CMsgBox::NO_AUTO_LINEBREAK | //CMsgBox::CENTER | //CMsgBox::AUTO_WIDTH | - //CMsgBox::AUTO_HIGH; CBox position ( g_settings.screen_StartX+30, g_settings.screen_StartY+30, g_settings.screen_EndX - g_settings.screen_StartX-60, diff --git a/src/gui/widget/progresswindow.cpp b/src/gui/widget/progresswindow.cpp index 8e992cf1c..905778d67 100644 --- a/src/gui/widget/progresswindow.cpp +++ b/src/gui/widget/progresswindow.cpp @@ -5,6 +5,8 @@ Implementation of CComponent Window class. Copyright (C) 2014 Thilo Graf 'dbt' + Copyright (C) 2009-2013 Stefan Seyfried + License: GPL This program is free software; you can redistribute it and/or diff --git a/src/lcddisplay/fontrenderer.cpp b/src/lcddisplay/fontrenderer.cpp index 581c90fa2..930283cc6 100644 --- a/src/lcddisplay/fontrenderer.cpp +++ b/src/lcddisplay/fontrenderer.cpp @@ -308,6 +308,11 @@ void LcdFont::RenderString(int x, int y, const int width, const char * text, con pthread_mutex_unlock(&renderer->render_mutex); } +int LcdFont::getRenderWidth(const std::string &text, const bool utf8_encoded) +{ + return getRenderWidth(text.c_str(), utf8_encoded); +}; + int LcdFont::getRenderWidth(const char * text, const bool utf8_encoded) { pthread_mutex_lock(&renderer->render_mutex); diff --git a/src/lcddisplay/fontrenderer.h b/src/lcddisplay/fontrenderer.h index 805149c1c..97479f590 100644 --- a/src/lcddisplay/fontrenderer.h +++ b/src/lcddisplay/fontrenderer.h @@ -56,13 +56,15 @@ class LcdFont FT_Error getGlyphBitmap(FT_ULong glyph_index, FTC_SBit *sbit); - public: - void RenderString(int x, int y, int width, const char *text, int color, int selected=0, const bool utf8_encoded = false); + public: + void RenderString(int x, int y, int width, const char *text, int color, + int selected = 0, const bool utf8_encoded = true); - int getRenderWidth(const char *text, const bool utf8_encoded = false); + int getRenderWidth(const char *text, const bool utf8_encoded = true); + int getRenderWidth(const std::string &text, const bool utf8_encoded = true); - LcdFont(CLCDDisplay *fb, LcdFontRenderClass *render, FTC_FaceID faceid, int isize); - ~LcdFont(){} + LcdFont(CLCDDisplay *fb, LcdFontRenderClass *render, FTC_FaceID faceid, int isize); + ~LcdFont(){} }; diff --git a/src/lcddisplay/lcddisplay.cpp b/src/lcddisplay/lcddisplay.cpp index 4d71b3192..d26151b1f 100644 --- a/src/lcddisplay/lcddisplay.cpp +++ b/src/lcddisplay/lcddisplay.cpp @@ -25,6 +25,9 @@ */ #include +#ifdef HAVE_SPARK_HARDWARE +#define HAVE_GENERIC_HARDWARE 1 +#endif #include "lcddisplay.h" #include @@ -33,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -454,11 +458,7 @@ bool CLCDDisplay::load_png(const char * const filename) png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); else { -#if (PNG_LIBPNG_VER < 10500) - if (!(setjmp(png_ptr->jmpbuf))) -#else if (!setjmp(png_jmpbuf(png_ptr))) -#endif { png_init_io(png_ptr,fh); diff --git a/src/lcddisplay/lcddisplay.h b/src/lcddisplay/lcddisplay.h index 6585c9713..48339c2c5 100644 --- a/src/lcddisplay/lcddisplay.h +++ b/src/lcddisplay/lcddisplay.h @@ -26,6 +26,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef HAVE_SPARK_HARDWARE +#error src/lcddisplay/lcddisplay.h must not be included on SPARK +#endif #ifdef HAVE_GENERIC_HARDWARE // dummy #define LCD_ROWS 8 diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 4c4992449..b3b35a472 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -3,7 +3,6 @@ Copyright (C) 2001 Steffen Hehn 'McClean' and some other guys - Homepage: http://dbox.cyberphoria.org/ Copyright (C) 2006-2014 Stefan Seyfried @@ -22,8 +21,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA + along with this program. If not, see . + */ #ifdef HAVE_CONFIG_H @@ -225,6 +224,9 @@ CNeutrinoFonts * neutrinoFonts = NULL; bool parentallocked = false; static char **global_argv; +/* hack until we have real platform abstraction... */ +static bool can_deepstandby = false; + extern const char * locale_real_names[]; /* #include */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -237,6 +239,11 @@ CNeutrinoApp::CNeutrinoApp() frameBuffer = CFrameBuffer::getInstance(); frameBuffer->setIconBasePath(ICONSDIR); +#if HAVE_TRIPLEDRAGON || USE_STB_HAL + /* this needs to happen before the framebuffer is set up */ + init_td_api(); + // shutdown_td_api(); +#endif SetupFrameBuffer(); mode = mode_unknown; @@ -297,7 +304,7 @@ const lcd_setting_struct_t lcd_setting[SNeutrinoSettings::LCD_SETTING_COUNT] = {"lcd_show_volume" , DEFAULT_LCD_SHOW_VOLUME }, {"lcd_autodimm" , DEFAULT_LCD_AUTODIMM }, {"lcd_deepbrightness" , DEFAULT_VFD_STANDBYBRIGHTNESS } -#if HAVE_TRIPLEDRAGON +#if HAVE_TRIPLEDRAGON || USE_STB_HAL ,{ "lcd_epgmode" , 0 /*DEFAULT_LCD_EPGMODE*/ } #endif }; @@ -315,10 +322,17 @@ static SNeutrinoSettings::usermenu_t usermenu_default[] = { /************************************************************************************** * CNeutrinoApp - loadSetup, load the application-settings * **************************************************************************************/ +#if HAVE_TRIPLEDRAGON || HAVE_SPARK_HARDWARE || HAVE_GENERIC_HARDWARE +#define DEFAULT_X_START_SD 32 +#define DEFAULT_Y_START_SD 26 +#define DEFAULT_X_END_SD 694 +#define DEFAULT_Y_END_SD 570 +#else #define DEFAULT_X_START_SD 60 #define DEFAULT_Y_START_SD 20 #define DEFAULT_X_END_SD 1220 #define DEFAULT_Y_END_SD 560 +#endif #define DEFAULT_X_START_HD 45 //5 //NI #define DEFAULT_Y_START_HD 30 //5 //NI @@ -386,7 +400,14 @@ int CNeutrinoApp::loadSetup(const char * fname) dprintf(DEBUG_NORMAL, "g_settings.easymenu %d\n", g_settings.easymenu); // video - g_settings.video_Mode = configfile.getInt32("video_Mode", VIDEO_STD_1080I50); // VIDEO_STD_720P50 +#if HAVE_TRIPLEDRAGON + int vid_Mode_default = VIDEO_STD_PAL; +#else + int vid_Mode_default = VIDEO_STD_720P50; + if (getenv("NEUTRINO_DEFAULT_SCART") != NULL) + vid_Mode_default = VIDEO_STD_PAL; +#endif + g_settings.video_Mode = configfile.getInt32("video_Mode", vid_Mode_default); #ifdef ANALOG_MODE g_settings.analog_mode1 = configfile.getInt32("analog_mode1", (int)ANALOG_MODE(BOTH,SD,RGB)); // default RGB g_settings.analog_mode2 = configfile.getInt32("analog_mode2", (int)ANALOG_MODE(CINCH,SD,YPRPB)); // default YPBPR @@ -436,9 +457,11 @@ int CNeutrinoApp::loadSetup(const char * fname) sprintf(cfg_key, "enabled_video_mode_%d", i); g_settings.enabled_video_modes[i] = configfile.getInt32(cfg_key, 0); } +#if VIDEOMENU_VIDEOMODE_OPTION_COUNT > 3 g_settings.enabled_video_modes[3] = 1; // 720p 50Hz g_settings.enabled_video_modes[4] = 1; // 1080i 50Hz g_settings.enabled_video_modes[9] = 1; // 720p 60Hz //NI +#endif for(int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) { sprintf(cfg_key, "enabled_auto_mode_%d", i); @@ -497,7 +520,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.shutdown_count = configfile.getInt32("shutdown_count", 0); g_settings.shutdown_min = 0; - if(cs_get_revision() > 7) + if (can_deepstandby || cs_get_revision() == 1) g_settings.shutdown_min = configfile.getInt32("shutdown_min", 000); //NI g_settings.sleeptimer_min = configfile.getInt32("sleeptimer_min", 0); @@ -773,6 +796,11 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.screen_EndY_lcd = configfile.getInt32( "screen_EndY_lcd", DEFAULT_Y_END_HD); g_settings.screen_preset = configfile.getInt32( "screen_preset", 1); +#if HAVE_TRIPLEDRAGON + g_settings.screen_preset = 0; /* does not make sense to have two configurations for that... */ +#elif ! HAVE_COOLSTREAM + g_settings.screen_preset = 1; /* spark is now always using 1280x720 framebuffer */ +#endif g_settings.screen_StartX = g_settings.screen_preset ? g_settings.screen_StartX_lcd : g_settings.screen_StartX_crt; g_settings.screen_StartY = g_settings.screen_preset ? g_settings.screen_StartY_lcd : g_settings.screen_StartY_crt; g_settings.screen_EndX = g_settings.screen_preset ? g_settings.screen_EndX_lcd : g_settings.screen_EndX_crt; @@ -793,8 +821,13 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.softupdate_mode = configfile.getInt32( "softupdate_mode", 1 ); g_settings.apply_kernel = configfile.getBool("apply_kernel" , false); g_settings.apply_settings = configfile.getBool("apply_settings" , false); +#if ENABLE_EXTUPDATE g_settings.softupdate_name_mode_apply = configfile.getInt32( "softupdate_name_mode_apply", CExtUpdate::SOFTUPDATE_NAME_DEFAULT); g_settings.softupdate_name_mode_backup = configfile.getInt32( "softupdate_name_mode_backup", CExtUpdate::SOFTUPDATE_NAME_DEFAULT); +#else + g_settings.softupdate_name_mode_apply = 0; + g_settings.softupdate_name_mode_backup = 0; /* unused, but still initialize it */ +#endif g_settings.flashupdate_createimage_add_var = configfile.getInt32( "flashupdate_createimage_add_var", 1); g_settings.flashupdate_createimage_add_root1 = configfile.getInt32( "flashupdate_createimage_add_root1", 0); @@ -1775,7 +1808,7 @@ void CNeutrinoApp::SetChannelMode(int newmode) INFO("newmode %d sort old %d new %d", newmode, sortmode[newmode], g_settings.channellist_sort_mode); if(newmode != LIST_MODE_FAV && sortmode[newmode] != g_settings.channellist_sort_mode && g_settings.channellist_sort_mode < CChannelList::SORT_MAX) { sortmode[newmode] = g_settings.channellist_sort_mode; - INFO("sorting, mode %d, %d bouquets\n", g_settings.channellist_sort_mode, (int)bouquetList->Bouquets.size()); + INFO("sorting, mode %d, %d bouquets", g_settings.channellist_sort_mode, (int)bouquetList->Bouquets.size()); for (uint32_t i = 0; i < bouquetList->Bouquets.size(); i++) { if(g_settings.channellist_sort_mode == CChannelList::SORT_ALPHA) bouquetList->Bouquets[i]->channelList->SortAlpha(); @@ -2019,6 +2052,14 @@ void CNeutrinoApp::InitZapitClient() void CNeutrinoApp::InitSectiondClient() { +#if 0 + /* TODO: check if still needed */ + /* wait for sectionsd to be able to process our registration */ + time_t t = time_monotonic_ms(); + while (! sectionsd_isReady()) + sleep(0); + dprintf(DEBUG_NORMAL, "had to wait %ld ms for sectionsd to start up\n", time_monotonic_ms() - t); +#endif g_Sectionsd = new CSectionsdClient; g_Sectionsd->registerEvent(CSectionsdClient::EVT_TIMESET, 222, NEUTRINO_UDS_NAME); g_Sectionsd->registerEvent(CSectionsdClient::EVT_GOT_CN_EPG, 222, NEUTRINO_UDS_NAME); @@ -2030,7 +2071,7 @@ void CNeutrinoApp::InitSectiondClient() #include #endif -void wake_up( bool &wakeup) +void wake_up(bool &wakeup) { #if HAVE_COOL_HARDWARE #ifndef FP_IOCTL_CLEAR_WAKEUP_TIMER @@ -2052,13 +2093,18 @@ void wake_up( bool &wakeup) close(fd); } printf("[timerd] wakeup from standby: %s\n", wakeup ? "yes" : "no"); +#endif + /* not platform specific - this is created by the init process */ + if (access("/tmp/.timer_wakeup", F_OK) == 0) { + wakeup = 1; + unlink("/tmp/.timer_wakeup"); + } + if(!wakeup){ puts("[neutrino.cpp] executing " NEUTRINO_LEAVE_DEEPSTANDBY_SCRIPT "."); if (my_system(NEUTRINO_LEAVE_DEEPSTANDBY_SCRIPT) != 0) perror(NEUTRINO_LEAVE_DEEPSTANDBY_SCRIPT " failed"); } -#endif - } int CNeutrinoApp::run(int argc, char **argv) @@ -2069,6 +2115,10 @@ TIMER_START(); cs_api_init(); cs_register_messenger(CSSendMessage); + g_info.hw_caps = get_hwcaps(); + can_deepstandby = g_info.hw_caps->can_shutdown; + g_info.has_fan = g_info.hw_caps->has_fan; + g_Locale = new CLocaleManager; int loadSettingsErg = loadSetup(NEUTRINO_SETTINGS_FILE); @@ -2165,14 +2215,14 @@ TIMER_START(); InitZapitClient(); g_Zapit->setStandby(false); + g_info.hw_caps = get_hwcaps(); CheckFastScan(); //timer start + long timerd_signal = 0; timer_wakeup = false;//init wake_up( timer_wakeup ); - pthread_create (&timer_thread, NULL, timerd_main_thread, (void *) (timer_wakeup && g_settings.shutdown_timer_record_type)); - timerd_thread_started = true; init_cec_setting = true; if(!(g_settings.shutdown_timer_record_type && timer_wakeup && g_settings.hdmi_cec_mode)){ @@ -2184,6 +2234,10 @@ TIMER_START(); timer_wakeup = (timer_wakeup && g_settings.shutdown_timer_record_type); g_settings.shutdown_timer_record_type = false; + timerd_signal = (timer_wakeup && g_settings.shutdown_timer_record_type); + pthread_create (&timer_thread, NULL, timerd_main_thread, (void *)&timerd_signal); + timerd_thread_started = true; + powerManager = new cPowerManager; powerManager->Open(); @@ -2245,6 +2299,11 @@ TIMER_START(); InitSectiondClient(); + /* wait until timerd is ready... */ + time_t timerd_wait = time_monotonic_ms(); + while (timerd_signal >= 0) + usleep(100); + dprintf(DEBUG_NORMAL, "had to wait %ld ms for timerd start...\n", time_monotonic_ms() - timerd_wait); InitTimerdClient(); // volume @@ -2286,6 +2345,9 @@ TIMER_START(); hdd->exec(NULL, ""); delete hdd; + hintBox->hide(); // InitZapper also displays a hintbox + delete hintBox; + cCA::GetInstance()->Ready(true); //InitZapper(); @@ -2324,7 +2386,7 @@ TIMER_STOP("################################## after all ####################### } RealRun(); - ExitRun(true, (cs_get_revision() > 7)); + ExitRun(true, can_deepstandby); return 0; } @@ -2475,7 +2537,7 @@ void CNeutrinoApp::RealRun() m_idletime = time(NULL); if (m_screensaver) { - printf("[neutrino] CSreenSaver stop; msg: %X\n", msg); + printf("[neutrino] CSreenSaver stop; msg: %lX\n", msg); screensaver(false); frameBuffer->stopFrame(); @@ -2571,6 +2633,7 @@ void CNeutrinoApp::RealRun() InfoClock->enableInfoClock(true); InfoIcons->enableInfoIcons(true); //NI InfoIcons } +#ifdef SCREENSHOT else if (msg == (neutrino_msg_t) g_settings.key_screenshot) { for(int i = 0; i < g_settings.screenshot_count; i++) { CScreenShot * sc = new CScreenShot("", (CScreenShot::screenshot_format_t)g_settings.screenshot_format); @@ -2578,6 +2641,7 @@ void CNeutrinoApp::RealRun() sc->Start(); } } +#endif else if( msg == (neutrino_msg_t) g_settings.key_lastchannel ) { // Quick Zap numericZap( msg ); @@ -2739,6 +2803,8 @@ void CNeutrinoApp::RealRun() CTimerList Timerlist; Timerlist.exec(NULL, ""); } + else if (msg == CRCInput::RC_aux) + scartMode(true); else { if (msg == CRCInput::RC_home) { @@ -2755,7 +2821,7 @@ void CNeutrinoApp::RealRun() } else { // mode == mode_scart - if( msg == CRCInput::RC_home ) { + if (msg == CRCInput::RC_home || msg == CRCInput::RC_aux) { if( mode == mode_scart ) { // Scart-Mode verlassen scartMode( false ); @@ -2957,7 +3023,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) if(msg == NeutrinoMessages::EVT_WEBTV_ZAP_COMPLETE) { t_channel_id chid = *(t_channel_id *) data; - printf("EVT_WEBTV_ZAP_COMPLETE: %llx\n", chid); + printf("EVT_WEBTV_ZAP_COMPLETE: %" PRIx64 "\n", chid); if (mode == mode_standby) { delete [] (unsigned char*) data; } else { @@ -3024,9 +3090,9 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) res = res | g_RemoteControl->handleMsg(msg, data); res = res | g_InfoViewer->handleMsg(msg, data); - //NI - if (channelList) + if (channelList) /* can be not yet ready during startup */ res = res | channelList->handleMsg(msg, data); + // else fprintf(stderr, "channelList = NULL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); res = res | CRecordManager::getInstance()->handleMsg(msg, data); res = res | CEpgScan::getInstance()->handleMsg(msg, data); res = res | CHDDMenuHandler::getInstance()->handleMsg(msg, data); @@ -3198,6 +3264,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) delete sleepTimer; return messages_return::handled; } +#ifdef SCREENSHOT else if (msg == (neutrino_msg_t) g_settings.key_screenshot) { //video+osd scaled to osd size CScreenShot * sc = new CScreenShot("", (CScreenShot::screenshot_format_t)g_settings.screenshot_format); @@ -3205,6 +3272,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) sc->MakeFileName(CZapit::getInstance()->GetCurrentChannelID()); sc->Start(); } +#endif /* ================================== MESSAGES ================================================ */ else if (msg == NeutrinoMessages::EVT_VOLCHANGED) { @@ -3421,7 +3489,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) return messages_return::handled; } } - if(g_settings.shutdown_real) + if (g_settings.shutdown_real && can_deepstandby) g_RCInput->postMsg(NeutrinoMessages::SHUTDOWN, 0); else g_RCInput->postMsg(NeutrinoMessages::STANDBY_ON, 0); @@ -3466,7 +3534,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) } else if( msg == NeutrinoMessages::SHUTDOWN ) { if(!skipShutdownTimer) { - ExitRun(true, (cs_get_revision() > 7)); + ExitRun(true, can_deepstandby); } else { skipShutdownTimer=false; @@ -3525,7 +3593,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) return messages_return::handled; } else if( msg == NeutrinoMessages::CHANGEMODE ) { - printf("CNeutrinoApp::handleMsg: CHANGEMODE to %d rezap %d\n", data & mode_mask, (data & norezap) != norezap); + printf("CNeutrinoApp::handleMsg: CHANGEMODE to %d rezap %d\n", (int)(data & mode_mask), (data & norezap) != norezap); if((data & mode_mask)== mode_radio) { if( mode != mode_radio ) { radioMode((data & norezap) != norezap); @@ -3624,7 +3692,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) return messages_return::handled; } if ((msg >= CRCInput::RC_WithData) && (msg < CRCInput::RC_WithData + 0x10000000)) { - INFO("###################################### DELETED msg %x data %x\n", msg, data); + INFO("###################################### DELETED msg %lx data %lx\n", msg, data); delete [] (unsigned char*) data; return messages_return::handled; } @@ -3636,6 +3704,7 @@ extern bool timer_is_rec;//timermanager.cpp void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) { + printf("[neutrino] %s retcode: %d can_deep: %d\n", __func__, retcode, can_deepstandby); bool do_shutdown = true; CRecordManager::getInstance()->StopAutoRecord(); @@ -3680,7 +3749,9 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) g_settings.shutdown_timer_record_type = timer_is_rec; saveSetup(NEUTRINO_SETTINGS_FILE); +#if 0 if(retcode) { +#endif puts("[neutrino.cpp] executing " NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT "."); if (my_system(NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT) != 0) perror(NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT " failed"); @@ -3690,9 +3761,11 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) InfoIcons->saveIconstate(); printf("entering off state\n"); + printf("timer_minutes: %ld\n", timer_minutes); mode = mode_off; //CVFD::getInstance()->ShowText(g_Locale->getText(LOCALE_MAINMENU_SHUTDOWN)); +#if 0 { fp_standby_data_t standby; time_t mtime = time(NULL); @@ -3758,18 +3831,76 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) } } } else { +#endif + int leds = 0; + int bright = 0; +#if HAVE_COOL_HARDWARE + if (retcode) { + leds = 0x40; + switch (g_settings.led_deep_mode){ + case 0: + leds = 0x0;//off leds + break; + case 1: + leds = 0x60;//on led1 & 2 + break; + case 2: + leds = 0x20;//led1 on , 2 off + break; + case 3: + leds = 0x40;//led2 off, 2 on + break; + default: + break; + } + if (leds && g_settings.led_blink && timer_minutes) + leds |= 0x80; + } + if (cs_get_revision() != 10) + bright = g_settings.lcd_setting[SNeutrinoSettings::LCD_DEEPSTANDBY_BRIGHTNESS]; +#endif + if (timer_minutes || leds) + { + FILE *f = fopen("/tmp/.timer", "w"); + if (f) + { + fprintf(stderr, "timer_wakeup: %ld\n", timer_minutes * 60); + fprintf(f, "%ld\n", timer_minutes * 60); + fprintf(f, "%d\n", leds); + fprintf(f, "%d\n", bright); + fclose(f); + } + else + perror("fopen /tmp/.timer"); + } + delete g_RCInput; + g_RCInput = NULL; //NI my_system("/etc/init.d/rcK"); //fan speed if (g_info.has_fan) { CFanControlNotifier::setSpeed(0); } //CVFD::getInstance()->ShowText(g_Locale->getText(LOCALE_MAINMENU_REBOOT)); + delete CVFD::getInstance(); + delete SHTDCNT::getInstance(); stop_video(); + + printf("[neutrino] This is the end. exiting with code %d\n", retcode); Cleanup(); - //_exit(retcode); +#if HAVE_COOL_HARDWARE + FILE *f = fopen("/tmp/.shutdown", "w"); + fclose(f); +#endif +#ifdef __sh__ + /* the sh4 gcc seems to dislike someting about openthreads... */ + _exit(retcode); +#else exit(retcode); +#endif +#if 0 } +#endif } } @@ -3871,13 +4002,22 @@ void CNeutrinoApp::scartMode( bool bOnOff ) frameBuffer->paintBackground(); //g_Controld->setScartMode( 1 ); +#if HAVE_TRIPLEDRAGON + /* would this hurt on Coolstream? */ + videoDecoder->Stop(true); + videoDecoder->Standby(true); +#endif CVFD::getInstance()->setMode(CVFD::MODE_SCART); lastMode = mode; mode = mode_scart; } else { // SCART AUS //g_Controld->setScartMode( 0 ); - +#if HAVE_TRIPLEDRAGON + /* could actually go into radioMode() and tvMode()? */ + videoDecoder->Standby(false); + videoDecoder->Start(); +#endif mode = mode_unknown; //re-set mode if( lastMode == mode_radio ) { @@ -3907,6 +4047,7 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) if ( FILE *f = fopen("/tmp/.ni-standby", "w") ) fclose(f); + CVFD::getInstance()->ShowText("standby... "); if( mode == mode_scart ) { //g_Controld->setScartMode( 0 ); } @@ -3990,14 +4131,15 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) } else { // Active standby off powerManager->SetStandby(false, false); + CVFD::getInstance()->setMode(CVFD::MODE_TVRADIO); + CVFD::getInstance()->ShowText("resume... "); cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000); videoDecoder->Standby(false); CEpgScan::getInstance()->Stop(); + CSectionsdClient::CurrentNextInfo dummy; + g_InfoViewer->getEPG(0, dummy); g_RCInput->killTimer(fst_timer); - CSectionsdClient::CurrentNextInfo dummy; //NI - g_InfoViewer->getEPG(0, dummy); //NI - if(init_cec_setting){ //init cec settings CCECSetup cecsetup; @@ -4046,6 +4188,12 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) if(!recordingstatus) { //only switch to standby_channel_id when not recording live_channel_id = standby_channel_id; } +#if 0 + /* todo: check parental pin */ + videoDecoder->Standby(false); + channelList->setSelected(0xfffffff); /* make sure that zapTo_ChannelID will zap */ + channelList->zapTo_ChannelID(live_channel_id); +#endif channelList->zapTo_ChannelID(live_channel_id, true); /* force re-zap */ g_Sectionsd->setPauseScanning(false); @@ -4272,11 +4420,12 @@ int CNeutrinoApp::exec(CMenuTarget* parent, const std::string & actionKey) delete hintBox; stop_daemons(true); + delete CVFD::getInstance(); + delete SHTDCNT::getInstance(); stop_video(); /* g_Timerd, g_Zapit and CVFD are used in stop_daemons */ delete g_Timerd; delete g_Zapit; //do we really need this? - delete CVFD::getInstance(); for(int i = 3; i < 256; i++) close(i); @@ -4462,9 +4611,14 @@ void sighandler (int signum) delete CRecordManager::getInstance(); //CNeutrinoApp::getInstance()->saveSetup(NEUTRINO_SETTINGS_FILE); stop_daemons(); + delete CVFD::getInstance(); + delete SHTDCNT::getInstance(); stop_video(); - //_exit(0); +#ifdef __sh__ + _exit(0); +#else exit(0); +#endif default: break; } @@ -4560,7 +4714,7 @@ void CNeutrinoApp::loadKeys(const char * fname) /* options */ g_settings.menu_left_exit = tconfig.getInt32( "menu_left_exit", 0 ); g_settings.key_click = tconfig.getInt32( "key_click", 1 ); - g_settings.repeat_blocker = tconfig.getInt32("repeat_blocker", 150); + g_settings.repeat_blocker = tconfig.getInt32("repeat_blocker", 450); g_settings.repeat_genericblocker = tconfig.getInt32("repeat_genericblocker", 100); g_settings.longkeypress_duration = tconfig.getInt32("longkeypress_duration", LONGKEYPRESS_OFF); @@ -4665,7 +4819,7 @@ void CNeutrinoApp::saveKeys(const char * fname) void CNeutrinoApp::StopSubtitles() { - printf("[neutrino] %s\n", __FUNCTION__); + //printf("[neutrino] %s\n", __FUNCTION__); int ttx, dvbpid, ttxpid, ttxpage; dvbpid = dvbsub_getpid(); @@ -4683,7 +4837,7 @@ void CNeutrinoApp::StopSubtitles() void CNeutrinoApp::StartSubtitles(bool show) { - printf("%s: %s\n", __FUNCTION__, show ? "Show" : "Not show"); + //printf("%s: %s\n", __FUNCTION__, show ? "Show" : "Not show"); if(!show) return; dvbsub_start(0); @@ -4831,8 +4985,11 @@ void CNeutrinoApp::Cleanup() printf("cleanup 18\n");fflush(stdout); delete g_EpgData; g_EpgData = NULL; printf("cleanup 19\n");fflush(stdout); +#if 0 + /* crashes in destructor???? very strange */ delete g_InfoViewer; g_InfoViewer = NULL; printf("cleanup 11\n");fflush(stdout); +#endif delete g_EventList; g_EventList = NULL; printf("cleanup 12\n");fflush(stdout); delete g_Locale; g_Locale = NULL; @@ -4871,11 +5028,11 @@ void CNeutrinoApp::Cleanup() printf("cleanup 5\n");fflush(stdout); delete CEitManager::getInstance(); printf("cleanup 6\n");fflush(stdout); - delete CVFD::getInstance(); + //delete CVFD::getInstance(); #ifdef __UCLIBC__ malloc_stats(NULL); #else - malloc_stats(); + //malloc_stats(); #endif #endif } diff --git a/src/neutrino_menue.cpp b/src/neutrino_menue.cpp index 6bf532f10..06006e9ee 100644 --- a/src/neutrino_menue.cpp +++ b/src/neutrino_menue.cpp @@ -5,13 +5,7 @@ and some other guys Homepage: http://dbox.cyberphoria.org/ - Kommentar: - - Diese GUI wurde von Grund auf neu programmiert und sollte nun vom - Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert - auf der Client-Server Idee, diese GUI ist also von der direkten DBox- - Steuerung getrennt. Diese wird dann von Daemons uebernommen. - + Copyright (C) 2009-2014 Stefan Seyfried License: GPL @@ -202,6 +196,7 @@ void CNeutrinoApp::InitMenuMain() mf->setHint(NEUTRINO_ICON_HINT_GAMES, LOCALE_MENU_HINT_GAMES); personalize.addItem(MENU_MAIN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_GAMES]); +#if 0 //tools bool show_tools = g_PluginList->hasPlugin(CPlugins::P_TYPE_TOOL); mf = new CMenuForwarder(LOCALE_MAINMENU_TOOLS, show_tools, NULL, new CPluginList(LOCALE_MAINMENU_TOOLS,CPlugins::P_TYPE_TOOL)); @@ -219,6 +214,12 @@ void CNeutrinoApp::InitMenuMain() mf = new CMenuForwarder(LOCALE_MAINMENU_LUA, show_lua, NULL, new CPluginList(LOCALE_MAINMENU_LUA,CPlugins::P_TYPE_LUA)); mf->setHint(NEUTRINO_ICON_HINT_SCRIPTS, LOCALE_MENU_HINT_LUA); personalize.addItem(MENU_MAIN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_LUA]); +#else + bool show_plugins = g_PluginList->hasPlugin(CPlugins::P_TYPE_NO_GAME); + mf = new CMenuForwarder(LOCALE_MAINMENU_LUA, show_plugins, NULL, new CPluginList(LOCALE_MAINMENU_LUA, CPlugins::P_TYPE_NO_GAME)); + mf->setHint(NEUTRINO_ICON_HINT_SCRIPTS, LOCALE_MENU_HINT_LUA); + personalize.addItem(MENU_MAIN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_LUA]); +#endif } //NI-Menu section*********************************************************************************************** @@ -266,11 +267,11 @@ void CNeutrinoApp::InitMenuMain() personalize.addItem(MENU_MAIN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_STANDBY]); //shutdown - //NI if(system_rev >= 8) { + if (g_info.hw_caps->can_shutdown) { mf = new CMenuForwarder(LOCALE_MAINMENU_SHUTDOWN, true, NULL, this, "shutdown", CRCInput::RC_standby); mf->setHint(NEUTRINO_ICON_HINT_SHUTDOWN, LOCALE_MENU_HINT_SHUTDOWN); personalize.addItem(MENU_MAIN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_SHUTDOWN]); - //NI } + } //NI blank screen mf = new CMenuForwarder(LOCALE_BLANK_SCREEN, true, NULL, this, "blank_screen", CRCInput::RC_pause); @@ -317,11 +318,11 @@ void CNeutrinoApp::InitMenuMain() personalize.addItem(MENU_SHUTDOWN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_REBOOT]); //shutdown - //NI if(system_rev >= 8) { + if (g_info.hw_caps->can_shutdown) { mf = new CMenuForwarder(LOCALE_MAINMENU_SHUTDOWN, true, NULL, this, "shutdown", CRCInput::RC_blue); mf->setHint(NEUTRINO_ICON_HINT_SHUTDOWN, LOCALE_MENU_HINT_SHUTDOWN); personalize.addItem(MENU_SHUTDOWN, mf, &g_settings.personalize[SNeutrinoSettings::P_MAIN_SHUTDOWN]); - //NI } + } //NI blank screen mf = new CMenuForwarder(LOCALE_BLANK_SCREEN, true, NULL, this, "blank_screen", CRCInput::RC_pause); @@ -515,11 +516,15 @@ void CNeutrinoApp::InitMenuService() } //bouquet edit + // TODO: this needs a neutrino restart after changing parentallock_prompt to activate :-( if (!g_settings.easymenu) { - mf = new CMenuForwarder(LOCALE_BOUQUETEDITOR_NAME , true, NULL, new CBEBouquetWidget(), NULL, CRCInput::RC_blue); + CLockedMenuForwarder *lf; + lf = new CLockedMenuForwarder(LOCALE_BOUQUETEDITOR_NAME, g_settings.parentallock_pincode, g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_CHANGETOLOCKED, true, NULL, new CBEBouquetWidget(), NULL, CRCInput::RC_blue); - mf->setHint(NEUTRINO_ICON_HINT_BEDIT, LOCALE_MENU_HINT_BEDIT); - personalize.addItem(MENU_SERVICE, mf, &g_settings.personalize[SNeutrinoSettings::P_MSER_BOUQUET_EDIT]); + /* does not work with CLockedMenuForwarder yet? + lf->setHint(NEUTRINO_ICON_HINT_BEDIT, LOCALE_MENU_HINT_BEDIT); + */ + personalize.addItem(MENU_SERVICE, lf, &g_settings.personalize[SNeutrinoSettings::P_MSER_BOUQUET_EDIT]); } //channel reset diff --git a/src/neutrino_menue.h b/src/neutrino_menue.h index b4e261625..88cff9594 100644 --- a/src/neutrino_menue.h +++ b/src/neutrino_menue.h @@ -73,9 +73,6 @@ enum MN_WIDGET_ID MN_WIDGET_ID_OSDSETUP_FONTSIZE_EPG, MN_WIDGET_ID_OSDSETUP_FONTSIZE_INFOBAR, - //progressbar setup - MN_WIDGET_ID_PROGRESSBAR, - //language setup MN_WIDGET_ID_LANGUAGESETUP, MN_WIDGET_ID_LANGUAGESETUP_LOCALE, diff --git a/src/nhttpd/Makefile.am b/src/nhttpd/Makefile.am index 6fbf9623a..1d07eb190 100644 --- a/src/nhttpd/Makefile.am +++ b/src/nhttpd/Makefile.am @@ -3,6 +3,7 @@ SUBDIRS = yhttpd_core yhttpd_mods tuxboxapi web AM_CPPFLAGS = -fno-rtti -fno-exceptions -D_FILE_OFFSET_BITS=64 AM_CPPFLAGS += \ + @HWLIB_CFLAGS@ \ -I$(srcdir) \ -I$(top_builddir) \ -I$(top_srcdir) \ diff --git a/src/nhttpd/tuxboxapi/controlapi.cpp b/src/nhttpd/tuxboxapi/controlapi.cpp index 62096733e..11a23039b 100644 --- a/src/nhttpd/tuxboxapi/controlapi.cpp +++ b/src/nhttpd/tuxboxapi/controlapi.cpp @@ -191,7 +191,9 @@ const CControlAPI::TyCgiCall CControlAPI::yCgiCallList[]= {"reloadsetup", &CControlAPI::ReloadNeutrinoSetupCGI, ""}, {"reloadplugins", &CControlAPI::ReloadPluginsCGI, ""}, {"reloadchannels", &CControlAPI::ReloadChannelsCGI, ""}, +#ifdef SCREENSHOT {"screenshot", &CControlAPI::ScreenshotCGI, ""}, +#endif // boxcontrol - devices {"volume", &CControlAPI::VolumeCGI, "text/plain"}, {"lcd", &CControlAPI::LCDAction, "text/plain"}, @@ -847,6 +849,7 @@ void CControlAPI::RCEmCGI(CyhookHandler *hh) if (!hh->ParamList["repeat"].empty()) repeat = atoi(hh->ParamList["repeat"].c_str()); #endif +#if 0 int evd = open(EVENTDEV, O_RDWR); if (evd < 0) { hh->SendError(); @@ -866,6 +869,9 @@ void CControlAPI::RCEmCGI(CyhookHandler *hh) return; } close(evd); +#endif + /* 0 == KEY_PRESSED in rcinput.cpp */ + g_RCInput->postMsg((neutrino_msg_t) sendcode, 0); hh->SendOk(); } //----------------------------------------------------------------------------- @@ -1890,7 +1896,7 @@ void CControlAPI::EpgCGI(CyhookHandler *hh) else if (!hh->ParamList["eventid"].empty()) { //special epg query uint64_t epgid = 0; - sscanf(hh->ParamList["eventid"].c_str(), "%llu", &epgid); + sscanf(hh->ParamList["eventid"].c_str(), "%" SCNu64 "", &epgid); CShortEPGData epg; if (CEitManager::getInstance()->getEPGidShort(epgid, &epg)) { hh->WriteLn(epg.title); @@ -1902,7 +1908,7 @@ void CControlAPI::EpgCGI(CyhookHandler *hh) if (!hh->ParamList["starttime"].empty()) { uint64_t epgid = 0; time_t starttime = 0; - sscanf(hh->ParamList["fskid"].c_str(), "%llu", &epgid); + sscanf(hh->ParamList["fskid"].c_str(), "%" SCNu64 "", &epgid); sscanf(hh->ParamList["starttime"].c_str(), "%lu", &starttime); CEPGData longepg; if (CEitManager::getInstance()->getEPGid(epgid, starttime, &longepg)) { @@ -1964,6 +1970,7 @@ void CControlAPI::ReloadChannelsCGI(CyhookHandler *hh) hh->SendOk(); } +#ifdef SCREENSHOT void CControlAPI::ScreenshotCGI(CyhookHandler *hh) { bool enableOSD = true; @@ -1990,6 +1997,7 @@ void CControlAPI::ScreenshotCGI(CyhookHandler *hh) hh->SendError(); #endif } +#endif //----------------------------------------------------------------------------- void CControlAPI::ZaptoCGI(CyhookHandler *hh) diff --git a/src/nhttpd/tuxboxapi/neutrinoapi.cpp b/src/nhttpd/tuxboxapi/neutrinoapi.cpp index baceef32d..f6be5186f 100644 --- a/src/nhttpd/tuxboxapi/neutrinoapi.cpp +++ b/src/nhttpd/tuxboxapi/neutrinoapi.cpp @@ -245,7 +245,7 @@ bool CNeutrinoAPI::GetStreamInfo(int bitInfo[10]) long value; int pos = 0; - memset(bitInfo, 0, 10); + memset(bitInfo, 0, sizeof(int[10])); FILE *fd = fopen("/proc/bus/bitstream", "rt"); diff --git a/src/nhttpd/tuxboxapi/neutrinoyparser.cpp b/src/nhttpd/tuxboxapi/neutrinoyparser.cpp index 68ea72f0d..871fa8c10 100644 --- a/src/nhttpd/tuxboxapi/neutrinoyparser.cpp +++ b/src/nhttpd/tuxboxapi/neutrinoyparser.cpp @@ -688,7 +688,7 @@ std::string CNeutrinoYParser::func_get_audio_pids_as_dropdown(CyhookHandler *, if(para == "apid") idx_as_id=false; else if(!para.empty() && ("channel="== para.substr(0,8))){ - if (sscanf(para.c_str(), "channel=%llx:audio=%i:", ¤t_channel_id,&selected_apid) == 2) { + if (sscanf(para.c_str(), "channel=%" SCNx64 ":audio=%i:", ¤t_channel_id,&selected_apid) == 2) { if(current_channel_id != 0 && CZapit::getInstance()->GetCurrentChannelID() != current_channel_id){ channel = CServiceManager::getInstance()->FindChannel(current_channel_id); } diff --git a/src/nhttpd/yhttpd.cpp b/src/nhttpd/yhttpd.cpp index ef5112d79..1aa0c55be 100644 --- a/src/nhttpd/yhttpd.cpp +++ b/src/nhttpd/yhttpd.cpp @@ -120,7 +120,7 @@ void thread_cleanup (void *p) #ifndef Y_CONFIG_BUILD_AS_DAEMON void * nhttpd_main_thread(void *) { - set_threadname(__func__); + set_threadname("yweb:main_thread"); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); aprintf("Webserver %s tid %ld\n", WEBSERVERNAME, syscall(__NR_gettid)); @@ -338,7 +338,7 @@ bool Cyhttpd::Configure() { // Main Webserver call //----------------------------------------------------------------------------- void Cyhttpd::run() { - set_threadname(__func__); + set_threadname("yweb:run"); if (webserver) { if (flag_threading_off) webserver->is_threading = false; diff --git a/src/nhttpd/yhttpd_mods/Makefile.am b/src/nhttpd/yhttpd_mods/Makefile.am index 2e748d983..d10b3f5b2 100644 --- a/src/nhttpd/yhttpd_mods/Makefile.am +++ b/src/nhttpd/yhttpd_mods/Makefile.am @@ -10,7 +10,10 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/lib/libconfigfile \ @FREETYPE_CFLAGS@ -AM_CPPFLAGS += -fno-rtti -fno-exceptions -D_FILE_OFFSET_BITS=64 +AM_CPPFLAGS += -fno-rtti -fno-exceptions -D_FILE_OFFSET_BITS=64 -D__STDC_FORMAT_MACROS + +AM_CPPFLAGS += \ + @HWLIB_CFLAGS@ noinst_LIBRARIES = libyhttpdmods.a diff --git a/src/nhttpd/yhttpd_mods/mod_sendfile.cpp b/src/nhttpd/yhttpd_mods/mod_sendfile.cpp index 4f4482ad7..b7efb6d4c 100644 --- a/src/nhttpd/yhttpd_mods/mod_sendfile.cpp +++ b/src/nhttpd/yhttpd_mods/mod_sendfile.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include // yhttpd #include @@ -118,8 +119,8 @@ THandleStatus CmodSendfile::Hook_PrepareResponse(CyhookHandler *hh) { hh->RangeEnd = hh->ContentLength - 1; const char *range = (hh->HeaderList["Range"].empty()) ? NULL : hh->HeaderList["Range"].c_str(); if ((range && - (2 != sscanf(range, "bytes=%lld-%lld", &hh->RangeStart, &hh->RangeEnd)) && - (1 != sscanf(range, "bytes=%lld-", &hh->RangeStart))) + (2 != sscanf(range, "bytes=%" PRId64 "-%" PRId64, &hh->RangeStart, &hh->RangeEnd)) && + (1 != sscanf(range, "bytes=%" PRId64 "-", &hh->RangeStart))) || (hh->RangeStart > hh->RangeEnd) || (hh->RangeEnd > hh->ContentLength - 1)) { hh->SetError(HTTP_REQUEST_RANGE_NOT_SATISFIABLE); diff --git a/src/nosanitize.h b/src/nosanitize.h new file mode 100644 index 000000000..03f1c7953 --- /dev/null +++ b/src/nosanitize.h @@ -0,0 +1,12 @@ +#ifndef __neutrino_sanitize_h__ +#define __neutrino_sanitize_h__ + +#ifndef ATTRIBUTE_NO_SANITIZE_ADDRESS +# if defined(__clang__) || defined (__GNUC__) +# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +# else +# define ATTRIBUTE_NO_SANITIZE_ADDRESS +# endif +#endif + +#endif /* __neutrino_sanitize_h__ */ diff --git a/src/rcsim.c b/src/rcsim.c index 2ae56a39c..d00f259f4 100644 --- a/src/rcsim.c +++ b/src/rcsim.c @@ -36,6 +36,7 @@ #include #include +#if 0 /* if you want use HAVE_XX_HARDWARE, better include config.h :-) */ #include "config.h" @@ -44,6 +45,8 @@ #elif defined (HAVE_COOL_HARDWARE) #define EVENTDEV "/dev/input/input0" #else +#endif +#else /* dreambox and tripledragon do not use a "normal" input device, so we cannot (ab-)use the event repeating function of it. use the neutrino socket instead. */ #include diff --git a/src/system/Makefile.am b/src/system/Makefile.am index c0c5df8eb..184f688bf 100644 --- a/src/system/Makefile.am +++ b/src/system/Makefile.am @@ -42,3 +42,4 @@ libneutrino_system_a_SOURCES = \ ytcache.cpp \ ytparser.cpp \ setting_helpers.cpp +# safe_system.c diff --git a/src/system/configure_network.cpp b/src/system/configure_network.cpp index 5804f1843..2925949ae 100644 --- a/src/system/configure_network.cpp +++ b/src/system/configure_network.cpp @@ -2,6 +2,7 @@ * $port: configure_network.cpp,v 1.7 2009/11/20 22:44:19 tuxbox-cvs Exp $ * * (C) 2003 by thegoodguy + * (C) 2011 Stefan Seyfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,9 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * + * along with this program. If not, see . */ #include #include /* perror... */ diff --git a/src/system/flashtool.cpp b/src/system/flashtool.cpp index a1d073151..107300fe8 100644 --- a/src/system/flashtool.cpp +++ b/src/system/flashtool.cpp @@ -44,6 +44,11 @@ #include #include +#if HAVE_TRIPLEDRAGON +/* TD kernel 2.6.12 is too old and does not have writesize yet, use oobsize instead */ +#define writesize oobsize +#endif + //NI lcd4l-support #include "gui/lcd4l.h" extern CLCD4l *LCD4l; diff --git a/src/system/helpers.cpp b/src/system/helpers.cpp index 266ffbf14..84379f510 100644 --- a/src/system/helpers.cpp +++ b/src/system/helpers.cpp @@ -30,11 +30,13 @@ #include #include #include +#include #include #include #include #include #include /* or */ +#include /* gettimeofday */ #include #include #include @@ -44,6 +46,7 @@ #include #include #include "debug.h" +#include #include #include #include @@ -413,7 +416,7 @@ int check_dir(const char * dir, bool allow_tmp) ret = 0; // ok } if(ret == -1) - printf("Wrong Filessystem Type: 0x%" PRIx32"\n",s.f_type); + printf("Wrong Filessystem Type: 0x%llx\n", (unsigned long long)s.f_type); } return ret; } @@ -666,7 +669,6 @@ CFileHelpers::CFileHelpers() { FileBufSize = 0xFFFF; FileBuf = new char[FileBufSize]; - doCopyFlag = true; } CFileHelpers::~CFileHelpers() @@ -685,7 +687,6 @@ CFileHelpers* CFileHelpers::getInstance() bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t mode) { - doCopyFlag = true; unlink(Dst); if ((fd1 = open(Src, O_RDONLY)) < 0) return false; @@ -697,63 +698,26 @@ bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t mode) uint32_t block; off64_t fsizeSrc64 = lseek64(fd1, 0, SEEK_END); lseek64(fd1, 0, SEEK_SET); - if (fsizeSrc64 > 0x7FFFFFF0) { // > 2GB - off64_t fsize64 = fsizeSrc64; - block = FileBufSize; - //printf("#####[%s] fsizeSrc64: %lld 0x%010llX - large file\n", __FUNCTION__, fsizeSrc64, fsizeSrc64); - while(fsize64 > 0) { - if(fsize64 < (off64_t)FileBufSize) - block = (uint32_t)fsize64; - read(fd1, FileBuf, block); - write(fd2, FileBuf, block); - fsize64 -= block; - if (!doCopyFlag) - break; - } - if (doCopyFlag) { - lseek64(fd2, 0, SEEK_SET); - off64_t fsizeDst64 = lseek64(fd2, 0, SEEK_END); - if (fsizeSrc64 != fsizeDst64){ - close(fd1); - close(fd2); - return false; - } - } + off64_t fsize64 = fsizeSrc64; + block = FileBufSize; + //printf("#####[%s] fsizeSrc64: %lld 0x%010llX - large file\n", __func__, fsizeSrc64, fsizeSrc64); + while (fsize64 > 0) { + if (fsize64 < (off64_t)FileBufSize) + block = (uint32_t)fsize64; + read(fd1, FileBuf, block); /* FIXME: short read??? */ + write(fd2, FileBuf, block); /* FIXME: short write?? */ + fsize64 -= block; } - else { // < 2GB - off_t fsizeSrc = lseek(fd1, 0, SEEK_END); - lseek(fd1, 0, SEEK_SET); - off_t fsize = fsizeSrc; - block = FileBufSize; - //printf("#####[%s] fsizeSrc: %ld 0x%08lX - normal file\n", __FUNCTION__, fsizeSrc, fsizeSrc); - while(fsize > 0) { - if(fsize < (off_t)FileBufSize) - block = (uint32_t)fsize; - read(fd1, FileBuf, block); - write(fd2, FileBuf, block); - fsize -= block; - if (!doCopyFlag) - break; - } - if (doCopyFlag) { - lseek(fd2, 0, SEEK_SET); - off_t fsizeDst = lseek(fd2, 0, SEEK_END); - if (fsizeSrc != fsizeDst){ - close(fd1); - close(fd2); - return false; - } - } + lseek64(fd2, 0, SEEK_SET); + off64_t fsizeDst64 = lseek64(fd2, 0, SEEK_END); + if (fsizeSrc64 != fsizeDst64) { + close(fd1); + close(fd2); + return false; } close(fd1); close(fd2); - if (!doCopyFlag) { - sync(); - unlink(Dst); - return false; - } - return true; } @@ -819,8 +783,11 @@ bool CFileHelpers::copyDir(const char *Src, const char *Dst, bool backupMode) // is file else if (S_ISREG(FileInfo.st_mode)) { std::string save = ""; + (void)backupMode; /* squelch unused parameter warning */ +#if ENABLE_EXTUPDATE if (backupMode && (CExtUpdate::getInstance()->isBlacklistEntry(srcPath))) save = ".save"; +#endif copyFile(srcPath, (dstPath + save).c_str(), FileInfo.st_mode & 0x0FFF); } } diff --git a/src/system/helpers.h b/src/system/helpers.h index 5c5a8be74..d74a2dcaa 100644 --- a/src/system/helpers.h +++ b/src/system/helpers.h @@ -87,7 +87,6 @@ class CFileHelpers CFileHelpers(); ~CFileHelpers(); static CFileHelpers* getInstance(); - bool doCopyFlag; bool copyFile(const char *Src, const char *Dst, mode_t mode = 644); //NI bool copyDir(const char *Src, const char *Dst, bool backupMode=false); diff --git a/src/system/httptool.cpp b/src/system/httptool.cpp index 72314f10d..56110f17a 100644 --- a/src/system/httptool.cpp +++ b/src/system/httptool.cpp @@ -18,6 +18,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include diff --git a/src/system/mtdutils/mkfs.jffs2.cpp b/src/system/mtdutils/mkfs.jffs2.cpp index 762e44f32..d8e1bbaf9 100644 --- a/src/system/mtdutils/mkfs.jffs2.cpp +++ b/src/system/mtdutils/mkfs.jffs2.cpp @@ -68,6 +68,10 @@ #include +#ifdef HAVE_CONFIG_H +#include +#endif + #include "rbtree.h" #include #include diff --git a/src/system/safe_system.c b/src/system/safe_system.c new file mode 100644 index 000000000..3e92028b7 --- /dev/null +++ b/src/system/safe_system.c @@ -0,0 +1,26 @@ +/* + * (C) 2011 Stefan Seyfried + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +int safe_system(const char *command) +{ + int fd; + /* hm, what if we have more than 256 FDs open? */ + for (fd = 3; fd < 256; fd++) + fcntl(fd, F_SETFD, FD_CLOEXEC); + return system(command); +} diff --git a/src/system/safe_system.h b/src/system/safe_system.h new file mode 100644 index 000000000..2f56e0dd7 --- /dev/null +++ b/src/system/safe_system.h @@ -0,0 +1,11 @@ +#ifndef _SAFE_SYSTEM_H_ +#define _SAFE_SYSTEM_H_ +#ifdef __cplusplus +extern "C" +{ +#endif +extern int safe_system(const char *); +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/system/set_threadname.h b/src/system/set_threadname.h index c87569869..eb954d4ea 100644 --- a/src/system/set_threadname.h +++ b/src/system/set_threadname.h @@ -7,7 +7,7 @@ inline void set_threadname(const char *name) { char threadname[17]; - strncpy(threadname, name, sizeof(threadname)); + strncpy(threadname, name, 16); threadname[16] = 0; prctl (PR_SET_NAME, (unsigned long)threadname); } diff --git a/src/system/setting_helpers.cpp b/src/system/setting_helpers.cpp index b27faff65..41c5c4bbd 100644 --- a/src/system/setting_helpers.cpp +++ b/src/system/setting_helpers.cpp @@ -29,6 +29,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "configure_network.h" #include @@ -492,9 +496,18 @@ bool CTZChangeNotifier::changeNotify(const neutrino_locale_t, void * Data) } if(found) { printf("Timezone: %s -> %s\n", name.c_str(), zone.c_str()); - std::string cmd = "cp /usr/share/zoneinfo/" + zone + " /etc/localtime"; - printf("exec %s\n", cmd.c_str()); - my_system(3,"/bin/sh", "-c", cmd.c_str()); + std::string cmd = "/usr/share/zoneinfo/" + zone; + printf("symlink %s to /etc/localtime\n", cmd.c_str()); + if (unlink("/etc/localtime")) + perror("unlink failed"); + if (symlink(cmd.c_str(), "/etc/localtime")) + perror("symlink failed"); + /* for yocto tzdata compatibility */ + FILE *f = fopen("/etc/timezone", "w"); + if (f) { + fprintf(f, "%s\n", zone.c_str()); + fclose(f); + } #if 0 cmd = ":" + zone; setenv("TZ", cmd.c_str(), 1); @@ -563,6 +576,7 @@ int CDataResetNotifier::exec(CMenuTarget* /*parent*/, const std::string& actionK return ret; } +#if HAVE_COOL_HARDWARE void CFanControlNotifier::setSpeed(unsigned int speed) { printf("FAN Speed %d\n", speed); @@ -585,6 +599,16 @@ bool CFanControlNotifier::changeNotify(const neutrino_locale_t, void * data) setSpeed(speed); return false; } +#else +void CFanControlNotifier::setSpeed(unsigned int) +{ +} + +bool CFanControlNotifier::changeNotify(const neutrino_locale_t, void *) +{ + return false; +} +#endif bool CCpuFreqNotifier::changeNotify(const neutrino_locale_t, void * data) { @@ -604,14 +628,23 @@ bool CAutoModeNotifier::changeNotify(const neutrino_locale_t /*OptionName*/, voi int i; int modes[VIDEO_STD_MAX+1]; - memset(modes, 0, sizeof(int)*VIDEO_STD_MAX+1); + memset(modes, 0, sizeof(modes)); - for(i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) + for(i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) { + if (VIDEOMENU_VIDEOMODE_OPTIONS[i].key < 0) /* not available on this platform */ + continue; + if (VIDEOMENU_VIDEOMODE_OPTIONS[i].key >= VIDEO_STD_MAX) { + /* this must not happen */ + printf("CAutoModeNotifier::changeNotify VIDEOMODE_OPTIONS[%d].key = %d (>= %d)\n", + i, VIDEOMENU_VIDEOMODE_OPTIONS[i].key, VIDEO_STD_MAX); + continue; + } #ifdef BOXMODEL_APOLLO modes[VIDEOMENU_VIDEOMODE_OPTIONS[i].key] = g_settings.enabled_auto_modes[i]; #else modes[VIDEOMENU_VIDEOMODE_OPTIONS[i].key] = g_settings.enabled_video_modes[i]; #endif + } videoDecoder->SetAutoModes(modes); return false; } diff --git a/src/system/setting_helpers.h b/src/system/setting_helpers.h index 1c23a2ddc..90134d5e5 100644 --- a/src/system/setting_helpers.h +++ b/src/system/setting_helpers.h @@ -50,7 +50,7 @@ class CGenericMenuActivate void Clear() { items.clear(); } void Activate(bool enable) { - for(std::vector::iterator it = items.begin(); it != items.end(); it++) + for(std::vector::iterator it = items.begin(); it != items.end(); ++it) (*it)->setActive(enable); } }; diff --git a/src/system/settings.h b/src/system/settings.h index c2ed5bb41..71c7aad67 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -4,6 +4,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ + Copyright (C) 2007-2012 Stefan Seyfried + Kommentar: Diese GUI wurde von Grund auf neu programmiert und sollte nun vom @@ -39,13 +41,15 @@ #include #include // UTF8 +#include + #include #include #ifdef BOXMODEL_APOLLO #define VIDEOMENU_VIDEOMODE_OPTION_COUNT 16 #else -#define VIDEOMENU_VIDEOMODE_OPTION_COUNT 12 +#define VIDEOMENU_VIDEOMODE_OPTION_COUNT 13 #endif struct SNeutrinoTheme @@ -698,7 +702,7 @@ struct SNeutrinoSettings LCD_SHOW_VOLUME , LCD_AUTODIMM , LCD_DEEPSTANDBY_BRIGHTNESS, -#if HAVE_TRIPLEDRAGON +#if HAVE_TRIPLEDRAGON || USE_STB_HAL LCD_EPGMODE , #endif LCD_SETTING_COUNT @@ -946,8 +950,8 @@ const time_settings_struct_t timing_setting[SNeutrinoSettings::TIMING_SETTING_CO struct SglobalInfo { unsigned char box_Type; - delivery_system_t delivery_system; bool has_fan; + hw_caps_t *hw_caps; }; const int RECORDING_OFF = 0; diff --git a/src/timerd/Makefile.am b/src/timerd/Makefile.am index 4bbe89fa6..b3c68456f 100644 --- a/src/timerd/Makefile.am +++ b/src/timerd/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = -fno-rtti -fno-exceptions -D__STDC_FORMAT_MACROS AM_CPPFLAGS += \ + @HWLIB_CFLAGS@ \ -I$(top_builddir) \ -I$(top_srcdir) \ -I$(top_srcdir)/src \ diff --git a/src/timerd/timerd.cpp b/src/timerd/timerd.cpp index c6b639826..a0bfe7af7 100644 --- a/src/timerd/timerd.cpp +++ b/src/timerd/timerd.cpp @@ -486,12 +486,16 @@ int timerd_main_thread(void *data) CBasicServer timerd_server; - if (!timerd_server.prepare(TIMERD_UDS_NAME)) + if (!timerd_server.prepare(TIMERD_UDS_NAME)) { + *(long *)data = -2; /* signal neutrino that waiting is pointless */ return -1; + } // Start timer thread CTimerManager::getInstance(); - CTimerManager::getInstance()->wakeup =(bool)data; + CTimerManager::getInstance()->wakeup = !!(*(long *)data); + + *(long *)data = -1; /* signal we're up and running */ timerd_server.run(timerd_parse_command, CTimerdMsg::ACTVERSION); printf("timerd shutdown complete\n"); diff --git a/src/uncoolinit.cpp b/src/uncoolinit.cpp new file mode 100644 index 000000000..52a5d4a4e --- /dev/null +++ b/src/uncoolinit.cpp @@ -0,0 +1,57 @@ +/* + * (C) 2013 Stefan Seyfried, License: GPL v3+ + * + * uncoolinit -- work around driver initalization bug on + * (at least) Coolstream HD1 "first fifty edition". + * When starting up with 720p, the HDMI output is pink-tinted + * and without sound until switching resolution once. + * + * work around the issue by initializing the videodecoder in + * 1080i mode. + * + * This is really just a workaround for crappy drivers, but + * better than nothing :-) + */ + +#include +#include +#include +#include + +#include +#include +#include + +cVideo *v = NULL; +cDemux *d = NULL; + +int main (int argc, char **argv) +{ + struct timespec s, e; + clock_gettime(CLOCK_MONOTONIC, &s); + printf("\nuncoolinit by seife -- working around crappy drivers since 2009!\n"); + /* initialize everything */ + cs_api_init(); + d = new cDemux(); /* dummy demux for getChannel() and getBuffer() */ + d->Open(DMX_VIDEO_CHANNEL); /* do we really need to open it? */ + + /* this enables output in 1080i mode */ + v = new cVideo(VIDEO_STD_1080I50, d->getChannel(), d->getBuffer()); + + /* should we slow down booting even more by showing a picture? */ + if (argc > 1) { + v->ShowPicture(argv[1]); + if (argc > 2) + sleep(atoi(argv[2])); + v->StopPicture(); + } + + /* clean up after ourselves, or the drivers will be *very* unhappy */ + delete v; + delete d; + cs_api_exit(); + clock_gettime(CLOCK_MONOTONIC, &e); + printf("uncoolinit ends, took %lld ms\n", + (e.tv_sec*1000 + e.tv_nsec/1000000LL) - (s.tv_sec*1000 + s.tv_nsec/1000000LL)); + return 0; +} diff --git a/src/uncooloff.c b/src/uncooloff.c new file mode 100644 index 000000000..2c48e8cd0 --- /dev/null +++ b/src/uncooloff.c @@ -0,0 +1,69 @@ +/* + * uncooloff - switch off the box with a possible timer wakeup + * this is needed because the drivers do not implement a proper + * hwclock interface :-( + * + * (C) 2013-2014 Stefan Seyfried + * + * License: GPLv2+ + */ + +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char **argv) +{ + int fd; + int leds; + int brightness; + fp_standby_data_t fp; + time_t timer_seconds; + time_t now = time(NULL); + struct tm *tmnow = localtime(&now); + time_t fp_timer = 0; + + if (argc < 3) { + fprintf(stderr, "need timer_seconds, led and brightness values\n"); + return 1; + } + + timer_seconds = atol(argv[1]); + leds = atoi(argv[2]); + brightness = atoi(argv[3]); + + if (timer_seconds) { + fp_timer = (timer_seconds - now) / 60; + if (fp_timer < 1) { + fprintf(stderr, "warning: interval less than 1 minute (%d s) correcting\n", + (int)(timer_seconds - now)); + fp_timer = 1; + } + } + fprintf(stderr, "now: %ld, timer %ld, FP timer %ldmin\n\n", now / 60, timer_seconds / 60, fp_timer); + + fp.brightness = brightness; + fp.flags = leds; + fp.current_hour = tmnow->tm_hour; + fp.current_minute = tmnow->tm_min; + fp.timer_minutes_hi = fp_timer >> 8;; + fp.timer_minutes_lo = fp_timer & 0xFF; + + fd = open("/dev/display", O_RDONLY); + if (fd < 0) + perror("/dev/display"); + else { + if (ioctl(fd, IOC_FP_STANDBY, (fp_standby_data_t *) &fp)) + perror("IOC_FP_STANDBY"); + else { + while (1) + sleep(1); + } + } + return 1; +} diff --git a/src/zapit/data/Makefile.am b/src/zapit/data/Makefile.am index 56710b294..f82c9658e 100644 --- a/src/zapit/data/Makefile.am +++ b/src/zapit/data/Makefile.am @@ -1,4 +1,4 @@ configdir = $(CONFIGDIR)/zapit -config_DATA = frontend.conf +# config_DATA = frontend.conf diff --git a/src/zapit/include/audio.h b/src/zapit/include/audio.h index 2bc0cc772..812f2501a 100644 --- a/src/zapit/include/audio.h +++ b/src/zapit/include/audio.h @@ -1,6 +1,6 @@ #if HAVE_COOL_HARDWARE #include #endif -#if HAVE_TRIPLEDRAGON -#include +#if USE_STB_HAL +#include #endif diff --git a/src/zapit/include/dmx.h b/src/zapit/include/dmx.h index 8dd57df69..c8f41b8a3 100644 --- a/src/zapit/include/dmx.h +++ b/src/zapit/include/dmx.h @@ -1,9 +1,9 @@ #if HAVE_COOL_HARDWARE #include -#elif HAVE_TRIPLEDRAGON -#include +#elif USE_STB_HAL +#include #else -#error neither HAVE_COOL_HARDWARE nor HAVE_TRIPLEDRAGON defined. +#error neither HAVE_COOL_HARDWARE nor USE_STB_HAL defined. #error do you need to include config.h? #endif diff --git a/src/zapit/include/linux/dvb/audio.h b/src/zapit/include/private/linux/dvb/audio.h similarity index 100% rename from src/zapit/include/linux/dvb/audio.h rename to src/zapit/include/private/linux/dvb/audio.h diff --git a/src/zapit/include/linux/dvb/ca.h b/src/zapit/include/private/linux/dvb/ca.h similarity index 100% rename from src/zapit/include/linux/dvb/ca.h rename to src/zapit/include/private/linux/dvb/ca.h diff --git a/src/zapit/include/linux/dvb/dmx.h b/src/zapit/include/private/linux/dvb/dmx.h similarity index 100% rename from src/zapit/include/linux/dvb/dmx.h rename to src/zapit/include/private/linux/dvb/dmx.h diff --git a/src/zapit/include/linux/dvb/frontend.h b/src/zapit/include/private/linux/dvb/frontend.h similarity index 100% rename from src/zapit/include/linux/dvb/frontend.h rename to src/zapit/include/private/linux/dvb/frontend.h diff --git a/src/zapit/include/linux/dvb/net.h b/src/zapit/include/private/linux/dvb/net.h similarity index 100% rename from src/zapit/include/linux/dvb/net.h rename to src/zapit/include/private/linux/dvb/net.h diff --git a/src/zapit/include/linux/dvb/osd.h b/src/zapit/include/private/linux/dvb/osd.h similarity index 100% rename from src/zapit/include/linux/dvb/osd.h rename to src/zapit/include/private/linux/dvb/osd.h diff --git a/src/zapit/include/linux/dvb/version.h b/src/zapit/include/private/linux/dvb/version.h similarity index 100% rename from src/zapit/include/linux/dvb/version.h rename to src/zapit/include/private/linux/dvb/version.h diff --git a/src/zapit/include/linux/dvb/video.h b/src/zapit/include/private/linux/dvb/video.h similarity index 100% rename from src/zapit/include/linux/dvb/video.h rename to src/zapit/include/private/linux/dvb/video.h diff --git a/src/zapit/include/video.h b/src/zapit/include/video.h index 636dc2189..61ca70a4d 100644 --- a/src/zapit/include/video.h +++ b/src/zapit/include/video.h @@ -2,7 +2,7 @@ #include #include #endif -#if HAVE_TRIPLEDRAGON +#if USE_STB_HAL #include -#include +#include #endif diff --git a/src/zapit/include/zapit/client/zapitclient.h b/src/zapit/include/zapit/client/zapitclient.h index 0995abf1f..d81334ec9 100644 --- a/src/zapit/include/zapit/client/zapitclient.h +++ b/src/zapit/include/zapit/client/zapitclient.h @@ -492,11 +492,11 @@ class CZapitClient:public CBasicClient /****************************************/ void setStandby(const bool enable); - void startPlayBack(); - void stopPlayBack(); + void startPlayBack(const bool sendpmt = false); + void stopPlayBack(const bool sendpmt = false); void stopPip(); - void lockPlayBack(); - void unlockPlayBack(); + void lockPlayBack(const bool sendpmt = true); + void unlockPlayBack(const bool sendpmt = true); bool tune_TP(TP_params TP); bool isPlayBackActive(); //void setDisplayFormat(const video_display_format_t mode); diff --git a/src/zapit/include/zapit/femanager.h b/src/zapit/include/zapit/femanager.h index 0eb2d3d3b..aaf063620 100644 --- a/src/zapit/include/zapit/femanager.h +++ b/src/zapit/include/zapit/femanager.h @@ -44,6 +44,8 @@ typedef fe_map_t::iterator fe_map_iterator_t; typedef std::map fe_channel_map_t; typedef fe_channel_map_t::iterator fe_channel_map_iterator_t; +typedef std::set fe_type_list_t; + typedef struct common_fe_config { double gotoXXLatitude, gotoXXLongitude; int gotoXXLaDirection, gotoXXLoDirection; diff --git a/src/zapit/include/zapit/frontend_c.h b/src/zapit/include/zapit/frontend_c.h index 1fd509ad9..c513ced15 100644 --- a/src/zapit/include/zapit/frontend_c.h +++ b/src/zapit/include/zapit/frontend_c.h @@ -4,6 +4,7 @@ * (C) 2002-2003 Andreas Oberritter * * Copyright (C) 2011 CoolStream International Ltd + * Copyright (C) 2009,2010,2012,2013 Stefan Seyfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -112,8 +113,6 @@ class CFrontend /* current adapter where this frontend is on */ int adapter; bool locked; - /* tuning finished flag */ - bool tuned; /* information about the used frontend type */ struct dvb_frontend_info info; /* current 22kHz tone mode */ @@ -181,6 +180,9 @@ class CFrontend friend class CFEManager; public: + /* tuning finished flag */ + bool tuned; + ~CFrontend(void); static fe_code_rate_t getCodeRate(const uint8_t fec_inner, delivery_system_t delsys); @@ -205,7 +207,7 @@ class CFrontend uint16_t getSignalStrength(void) const; fe_status_t getStatus(void) const; uint32_t getUncorrectedBlocks(void) const; - void getDelSys(int f, int m, char * &fec, char * &sys, char * &mod); + void getDelSys(int f, int m, const char * &fec, const char * &sys, const char * &mod); void getFEInfo(void); int32_t getCurrentSatellitePosition() { return currentSatellitePosition; } @@ -270,7 +272,7 @@ class CFrontend satellite_map_t & getSatellites() { return satellites; } void setSatellites(satellite_map_t satmap) { satellites = satmap; } int getNumber() { return fenumber; }; - static void getDelSys(delivery_system_t delsys, int f, int m, char * &fec, char * &sys, char * &mod); + static void getDelSys(delivery_system_t delsys, int f, int m, const char * &fec, const char * &sys, const char * &mod); fe_work_mode_t getMode() { return femode; } void setMode(int mode) {femode = (fe_work_mode_t) mode; } int getMaster() { return masterkey; } @@ -299,6 +301,7 @@ class CFrontend static fe_delivery_system_t getFEDeliverySystem(delivery_system_t Delsys); static uint32_t getFEBandwidth(fe_bandwidth_t bandwidth); const char* getName(void) const { return info.name; } + void setName(const char* _name); private: // DEPRECATED fe_type_t getType() { return info.type; } diff --git a/src/zapit/include/zapit/frontend_types.h b/src/zapit/include/zapit/frontend_types.h index 3ced4139c..51d164f5d 100644 --- a/src/zapit/include/zapit/frontend_types.h +++ b/src/zapit/include/zapit/frontend_types.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 CoolStream International Ltd + * Copyright (C) 2013,2015 Stefan Seyfried * * License: GPLv2 * @@ -20,6 +21,7 @@ #ifndef __FRONTEND_TYPES_H__ #define __FRONTEND_TYPES_H__ +#include #include #include @@ -58,6 +60,24 @@ #define ZAPIT_DS_IS_TERR(ds) (((ds) & ZAPIT_DM_TERR) != 0) #define ZAPIT_DS_IS_CABLE(ds) (((ds) & ZAPIT_DM_CABLE) != 0) #define ZAPIT_DS_BIT_MASK(ds) ((1 << (ds)) & ZAPIT_DS_MASK) + +/* compat stuff for building with older DVB-API versions */ +/* actually, DVB-T2 is available from API 5.3, and SYS_TURBO is available from 5.4, + * but all this is pretty much unused anyway, so we can stick it under one #define */ +#if ((DVB_API_VERSION > 5) || (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR > 6)) +#define _HAVE_DVB57 1 +#else +#if HAVE_SPARK_HARDWARE +#ifdef WARN_DVBAPI +#warning DVB_API < 5.7 -- no DVB-T2/DTMB support. +#endif +#else +#error DVB_API < 5.7 => fix your toolchain +#endif +/* this is actually needed before 5.5, not 5.7, but this works for now */ +#define SYS_DVBC_ANNEX_A SYS_DVBC_ANNEX_AC +#endif + /* dvb transmission types */ typedef enum { UNKNOWN_DS = ZAPIT_DS_UNKNOWN, @@ -103,9 +123,9 @@ typedef struct { zapit_pilot_t pilot; fe_rolloff_t rolloff; - +#if _HAVE_DVB57 enum fe_interleaving interleaving; - +#endif uint8_t polarization; } FrontendParameters; @@ -115,6 +135,7 @@ typedef struct frontend_config { int uni_scr; int uni_qrg; int uni_lnb; + int uni_pin; int motorRotationSpeed; int highVoltage; int diseqc_order; diff --git a/src/zapit/include/zapit/settings.h b/src/zapit/include/zapit/settings.h index 1602d6c6f..072b95659 100644 --- a/src/zapit/include/zapit/settings.h +++ b/src/zapit/include/zapit/settings.h @@ -52,10 +52,12 @@ #define WEBTVDIR DATADIR "/neutrino/webtv" //NI #define WEBTVDIR_VAR "/var/tuxbox/webtv" //NI +#if HAVE_TRIPLEDRAGON == 0 #define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" #define DEMUX_DEVICE "/dev/dvb/adapter0/demux0" #define FRONTEND_DEVICE "/dev/dvb/adapter0/frontend0" #define VIDEO_DEVICE "/dev/dvb/adapter0/video0" +#endif #define CAMD_UDS_NAME "/tmp/camd.socket" diff --git a/src/zapit/include/zapit/zapit.h b/src/zapit/include/zapit/zapit.h index d1f08fd70..6c359e368 100644 --- a/src/zapit/include/zapit/zapit.h +++ b/src/zapit/include/zapit/zapit.h @@ -68,9 +68,6 @@ typedef struct Zapit_config { /* FE specific */ int highVoltage; int motorRotationSpeed; - int uni_scr; - int uni_qrg; /* the unicable frequency in MHz */ - int uni_lnb; /* the input (0/1) of a twin-position switch */ } t_zapit_config; @@ -202,7 +199,7 @@ class CZapit : public OpenThreads::Thread void LoadVolumeMap(); void SaveChannelPids(CZapitChannel* channel); virtual void ConfigFrontend(); - bool StopPlayBack(bool send_pmt); + bool StopPlayBack(bool send_pmt, bool blank = true); virtual void leaveStandby(); static CZapit * zapit; diff --git a/src/zapit/lib/Makefile.am b/src/zapit/lib/Makefile.am index 2d884b259..e62c50637 100644 --- a/src/zapit/lib/Makefile.am +++ b/src/zapit/lib/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = -fno-rtti -fno-exceptions AM_CPPFLAGS += \ + @HWLIB_CFLAGS@ \ -I$(top_builddir) \ -I$(top_srcdir) \ -I$(top_srcdir)/src/zapit/include \ diff --git a/src/zapit/lib/zapitclient.cpp b/src/zapit/lib/zapitclient.cpp index a7f3ba252..d32c4cac2 100644 --- a/src/zapit/lib/zapitclient.cpp +++ b/src/zapit/lib/zapitclient.cpp @@ -4,6 +4,7 @@ * Zapit client interface - DBoxII-Project * * (C) 2002 by thegoodguy & the DBoxII-Project + * (C) 2007-2012 Stefan Seyfried * * License: GPL * @@ -37,6 +38,12 @@ #include #include +#ifdef PEDANTIC_VALGRIND_SETUP +#define VALGRIND_PARANOIA memset(&msg, 0, sizeof(msg)) +#else +#define VALGRIND_PARANOIA {} +#endif + unsigned char CZapitClient::getVersion() const { return CZapitMessages::ACTVERSION; @@ -64,6 +71,7 @@ void CZapitClient::shutdown() void CZapitClient::zapTo(const unsigned int bouquet, const unsigned int channel) { CZapitMessages::commandZapto msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.channel = channel - 1; @@ -78,6 +86,7 @@ void CZapitClient::zapTo(const unsigned int bouquet, const unsigned int channel) void CZapitClient::zapTo(const unsigned int channel) { CZapitMessages::commandZaptoChannelNr msg; + VALGRIND_PARANOIA; msg.channel = channel - 1; @@ -144,6 +153,7 @@ int32_t CZapitClient::getCurrentSatellitePosition(void) void CZapitClient::setAudioChannel(const unsigned int channel) { CZapitMessages::commandSetAudioChannel msg; + VALGRIND_PARANOIA; msg.channel = channel; @@ -157,6 +167,7 @@ void CZapitClient::setAudioChannel(const unsigned int channel) unsigned int CZapitClient::zapTo_serviceID(const t_channel_id channel_id) { CZapitMessages::commandZaptoServiceID msg; + VALGRIND_PARANOIA; msg.channel_id = channel_id; msg.record = false; @@ -177,6 +188,7 @@ unsigned int CZapitClient::zapTo_serviceID(const t_channel_id channel_id) unsigned int CZapitClient::zapTo_record(const t_channel_id channel_id) { CZapitMessages::commandZaptoServiceID msg; + VALGRIND_PARANOIA; msg.channel_id = channel_id; msg.record = true; @@ -235,6 +247,7 @@ unsigned int CZapitClient::zapTo_epg(const t_channel_id channel_id, bool standby unsigned int CZapitClient::zapTo_subServiceID(const t_channel_id channel_id) { CZapitMessages::commandZaptoServiceID msg; + VALGRIND_PARANOIA; msg.channel_id = channel_id; msg.record = false; @@ -256,6 +269,7 @@ unsigned int CZapitClient::zapTo_subServiceID(const t_channel_id channel_id) void CZapitClient::zapTo_serviceID_NOWAIT(const t_channel_id channel_id) { CZapitMessages::commandZaptoServiceID msg; + VALGRIND_PARANOIA; msg.channel_id = channel_id; msg.record = false; @@ -272,6 +286,7 @@ void CZapitClient::zapTo_serviceID_NOWAIT(const t_channel_id channel_id) void CZapitClient::zapTo_subServiceID_NOWAIT(const t_channel_id channel_id) { CZapitMessages::commandZaptoServiceID msg; + VALGRIND_PARANOIA; msg.channel_id = channel_id; msg.record = false; @@ -288,6 +303,7 @@ void CZapitClient::zapTo_subServiceID_NOWAIT(const t_channel_id channel_id) void CZapitClient::setMode(const channelsMode mode) { CZapitMessages::commandSetMode msg; + VALGRIND_PARANOIA; msg.mode = mode; @@ -351,6 +367,7 @@ void CZapitClient::getPIDS(responseGetPIDs& pids) void CZapitClient::zaptoNvodSubService(const int num) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; msg.val = num; @@ -367,6 +384,7 @@ void CZapitClient::getBouquets(BouquetList& bouquets, const bool emptyBouquetsTo char buffer[30 + 1]; CZapitMessages::commandGetBouquets msg; + VALGRIND_PARANOIA; msg.emptyBouquetsToo = emptyBouquetsToo; msg.mode = mode; @@ -454,6 +472,7 @@ bool CZapitClient::getBouquetChannels(const unsigned int bouquet, BouquetChannel { bool return_value; CZapitMessages::commandGetBouquetChannels msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.mode = mode; @@ -485,6 +504,7 @@ bool CZapitClient::getChannels( BouquetChannelList& channels, channelsMode mode, { bool return_value; CZapitMessages::commandGetChannels msg; + VALGRIND_PARANOIA; msg.mode = mode; msg.order = order; @@ -565,6 +585,7 @@ void CZapitClient::reloadCurrentServices() void CZapitClient::muteAudio(const bool mute) { CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; msg.truefalse = mute; @@ -577,6 +598,7 @@ void CZapitClient::muteAudio(const bool mute) bool CZapitClient::getMuteStatus() { CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_GET_MUTE_STATUS, (char*)&msg, sizeof(msg)); @@ -588,6 +610,7 @@ bool CZapitClient::getMuteStatus() void CZapitClient::setVolume(const unsigned int left, const unsigned int right) { CZapitMessages::commandVolume msg; + VALGRIND_PARANOIA; msg.left = left; msg.right = right; @@ -601,6 +624,7 @@ void CZapitClient::setVolume(const unsigned int left, const unsigned int right) void CZapitClient::getVolume(unsigned int *left, unsigned int *right) { CZapitMessages::commandVolume msg; + VALGRIND_PARANOIA; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_GET_VOLUME, 0, 0); @@ -644,6 +668,7 @@ bool CZapitClient::get_current_TP(transponder* TP) void CZapitClient::sendMotorCommand(uint8_t cmdtype, uint8_t address, uint8_t cmd, uint8_t num_parameters, uint8_t param1, uint8_t param2) { CZapitMessages::commandMotor msg; + VALGRIND_PARANOIA; msg.cmdtype = cmdtype; msg.address = address; @@ -865,6 +890,7 @@ void CZapitClient::addBouquet(const char * const name) void CZapitClient::moveBouquet(const unsigned int bouquet, const unsigned int newPos) { CZapitMessages::commandMoveBouquet msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.newPos = newPos; @@ -879,6 +905,7 @@ void CZapitClient::moveBouquet(const unsigned int bouquet, const unsigned int ne void CZapitClient::deleteBouquet(const unsigned int bouquet) { CZapitMessages::commandDeleteBouquet msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; @@ -893,6 +920,7 @@ void CZapitClient::deleteBouquet(const unsigned int bouquet) void CZapitClient::renameBouquet(const unsigned int bouquet, const char * const newName) { CZapitMessages::commandRenameBouquet msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; @@ -966,6 +994,7 @@ void CZapitClient::moveChannel( unsigned int bouquet, unsigned int oldPos, unsig void CZapitClient::addChannelToBouquet(const unsigned int bouquet, const t_channel_id channel_id) { CZapitMessages::commandAddChannelToBouquet msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.channel_id = channel_id; @@ -981,6 +1010,7 @@ void CZapitClient::addChannelToBouquet(const unsigned int bouquet, const t_chann void CZapitClient::removeChannelFromBouquet(const unsigned int bouquet, const t_channel_id channel_id) { CZapitMessages::commandRemoveChannelFromBouquet msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.channel_id = channel_id; @@ -996,6 +1026,7 @@ void CZapitClient::removeChannelFromBouquet(const unsigned int bouquet, const t_ void CZapitClient::setBouquetLock(const unsigned int bouquet, const bool b) { CZapitMessages::commandBouquetState msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.state = b; @@ -1011,6 +1042,7 @@ void CZapitClient::setBouquetLock(const unsigned int bouquet, const bool b) void CZapitClient::setBouquetHidden(const unsigned int bouquet, const bool hidden) { CZapitMessages::commandBouquetState msg; + VALGRIND_PARANOIA; msg.bouquet = bouquet; msg.state = hidden; @@ -1035,6 +1067,7 @@ void CZapitClient::renumChannellist() void CZapitClient::saveBouquets(const bool saveall) { CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; msg.truefalse = saveall; OpenThreads::ScopedLock lock(mutex); @@ -1049,36 +1082,42 @@ void CZapitClient::saveBouquets(const bool saveall) void CZapitClient::setStandby(const bool enable) { CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; msg.truefalse = enable; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_STANDBY, (char*)&msg, sizeof(msg)); - if(enable) { - CZapitMessages::responseCmd response; - CBasicClient::receive_data((char* )&response, sizeof(response)); - } + CZapitMessages::responseCmd response; + CBasicClient::receive_data((char* )&response, sizeof(response)); close_connection(); } void CZapitClient::setVideoSystem(int video_system) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; msg.val = video_system; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_VIDEO_SYSTEM, (char*)&msg, sizeof(msg)); close_connection(); } -void CZapitClient::startPlayBack() +void CZapitClient::startPlayBack(const bool sendpmt) { + CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; + msg.truefalse = sendpmt; OpenThreads::ScopedLock lock(mutex); - send(CZapitMessages::CMD_SB_START_PLAYBACK); + send(CZapitMessages::CMD_SB_START_PLAYBACK, (char*)&msg, sizeof(msg)); close_connection(); } -void CZapitClient::stopPlayBack() +void CZapitClient::stopPlayBack(const bool sendpmt) { + CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; + msg.truefalse = sendpmt; OpenThreads::ScopedLock lock(mutex); - send(CZapitMessages::CMD_SB_STOP_PLAYBACK); + send(CZapitMessages::CMD_SB_STOP_PLAYBACK, (char*)&msg, sizeof(msg)); CZapitMessages::responseCmd response; CBasicClient::receive_data((char* )&response, sizeof(response)); close_connection(); @@ -1093,18 +1132,24 @@ void CZapitClient::stopPip() close_connection(); } -void CZapitClient::lockPlayBack() +void CZapitClient::lockPlayBack(const bool sendpmt) { + CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; + msg.truefalse = sendpmt; OpenThreads::ScopedLock lock(mutex); - send(CZapitMessages::CMD_SB_LOCK_PLAYBACK); + send(CZapitMessages::CMD_SB_LOCK_PLAYBACK, (char*)&msg, sizeof(msg)); CZapitMessages::responseCmd response; CBasicClient::receive_data((char* )&response, sizeof(response)); close_connection(); } -void CZapitClient::unlockPlayBack() +void CZapitClient::unlockPlayBack(const bool sendpmt) { + CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; + msg.truefalse = sendpmt; OpenThreads::ScopedLock lock(mutex); - send(CZapitMessages::CMD_SB_UNLOCK_PLAYBACK); + send(CZapitMessages::CMD_SB_UNLOCK_PLAYBACK, (char*)&msg, sizeof(msg)); CZapitMessages::responseCmd response; CBasicClient::receive_data((char* )&response, sizeof(response)); close_connection(); @@ -1133,6 +1178,7 @@ void CZapitClient::setDisplayFormat(const video_display_format_t format) void CZapitClient::setAudioMode(const int mode) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; msg.val = mode; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_AUDIO_MODE, (char*)&msg, sizeof(msg)); @@ -1153,6 +1199,7 @@ void CZapitClient::getAudioMode(int * mode) void CZapitClient::setRecordMode(const bool activate) { CZapitMessages::commandSetRecordMode msg; + VALGRIND_PARANOIA; msg.activate = activate; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_RECORD_MODE, (char*)&msg, sizeof(msg)); @@ -1193,6 +1240,7 @@ void CZapitClient::getAspectRatio(int *ratio) void CZapitClient::setAspectRatio(int ratio) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; msg.val = ratio; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_ASPECTRATIO, (char*)&msg, sizeof(msg)); @@ -1202,6 +1250,7 @@ void CZapitClient::setAspectRatio(int ratio) void CZapitClient::getMode43(int *m43) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_GET_MODE43, 0, 0); CBasicClient::receive_data((char* )&msg, sizeof(msg)); @@ -1212,6 +1261,7 @@ void CZapitClient::getMode43(int *m43) void CZapitClient::setMode43(int m43) { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA; msg.val = m43; OpenThreads::ScopedLock lock(mutex); send(CZapitMessages::CMD_SET_MODE43, (char*)&msg, sizeof(msg)); @@ -1221,6 +1271,7 @@ void CZapitClient::setMode43(int m43) void CZapitClient::registerEvent(const unsigned int eventID, const unsigned int clientID, const char * const udsName) { CEventServer::commandRegisterEvent msg; + VALGRIND_PARANOIA; msg.eventID = eventID; msg.clientID = clientID; @@ -1236,6 +1287,7 @@ void CZapitClient::registerEvent(const unsigned int eventID, const unsigned int void CZapitClient::unRegisterEvent(const unsigned int eventID, const unsigned int clientID) { CEventServer::commandUnRegisterEvent msg; + VALGRIND_PARANOIA; msg.eventID = eventID; msg.clientID = clientID; diff --git a/src/zapit/src/bouquets.cpp b/src/zapit/src/bouquets.cpp index 271751cd0..c5cc7e0ec 100644 --- a/src/zapit/src/bouquets.cpp +++ b/src/zapit/src/bouquets.cpp @@ -7,7 +7,7 @@ * rasc , * thegoodguy * - * (C) 2009, 2011, 2013 Stefan Seyfried + * (C) 2009, 2011-2013 Stefan Seyfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/zapit/src/capmt.cpp b/src/zapit/src/capmt.cpp index 84dddac03..552c4f9bd 100644 --- a/src/zapit/src/capmt.cpp +++ b/src/zapit/src/capmt.cpp @@ -3,7 +3,7 @@ * thegoodguy * * Copyright (C) 2011-2012 CoolStream International Ltd - * Copyright (C) 2012 Stefan Seyfried + * Copyright (C) 2012-2014 Stefan Seyfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -90,7 +90,7 @@ bool CCam::makeCaPmt(CZapitChannel * channel, bool add_private, uint8_t list, co int len; unsigned char * buffer = channel->getRawPmt(len); - INFO("cam %x source %d camask %d list %02x buffer", (int) this, source_demux, camask, list); + DBG("cam %p source %d camask %d list %02x buffer\n", this, source_demux, camask, list); if(!buffer) return false; @@ -230,15 +230,33 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start //INFO("channel %llx [%s] mode %d %s update %d", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update); /* FIXME until proper demux management */ +#if ! HAVE_COOL_HARDWARE + CFrontend *dfe = CFEManager::getInstance()->allocateFE(channel); + int fenum = -1; + if (dfe) + fenum = dfe->getNumber(); +#endif switch(mode) { case PLAY: +#if HAVE_COOL_HARDWARE source = DEMUX_SOURCE_0; demux = LIVE_DEMUX; +#else + source = cDemux::GetSource(0); + demux = cDemux::GetSource(0); + INFO("PLAY: fe_num %d dmx_src %d", fenum, cDemux::GetSource(0)); +#endif break; case STREAM: case RECORD: +#if HAVE_COOL_HARDWARE source = channel->getRecordDemux(); demux = channel->getRecordDemux(); +#else + source = cDemux::GetSource(channel->getRecordDemux()); + demux = source; + INFO("RECORD/STREAM(%d): fe_num %d rec_dmx %d dmx_src %d", mode, fenum, channel->getRecordDemux(), demux); +#endif break; case PIP: source = channel->getRecordDemux(); @@ -259,6 +277,14 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start mode, start ? "START" : "STOP", source, oldmask, newmask, force_update); //INFO("source %d old mask %d new mask %d force update %s", source, oldmask, newmask, force_update ? "yes" : "no"); + + /* stop decoding if record stops unless it's the live channel. TODO:PIP? */ + if (mode == RECORD && start == false && source != cDemux::GetSource(0)) { + INFO("MODE!=record(%d) start=false, src %d getsrc %d", mode, source, cDemux::GetSource(0)); + cam->sendMessage(NULL, 0, false); + cam->sendCaPmt(channel->getChannelID(), NULL, 0, CA_SLOT_TYPE_ALL); + } + if((oldmask != newmask) || force_update) { cam->setCaMask(newmask); cam->setSource(source); diff --git a/src/zapit/src/fastscan.cpp b/src/zapit/src/fastscan.cpp index 96e5ed532..e91034db0 100644 --- a/src/zapit/src/fastscan.cpp +++ b/src/zapit/src/fastscan.cpp @@ -364,7 +364,7 @@ bool CServiceScan::ReadFst(unsigned short pid, unsigned short operator_id, bool } while(!one_section && (sectotal < last)); delete dmx; - printf("[FST] %d sections\n", fst_sections.size()); + printf("[FST] %zd sections\n", fst_sections.size()); return !fst_sections.empty(); } @@ -808,7 +808,7 @@ void CServiceScan::process_satellite_delivery_system_descriptor(const unsigned c if (feparams->symbol_rate >= 50000000) feparams->symbol_rate /= 10; - feparams->frequency = (int) 1000 * (int) round ((double) feparams->frequency / (double) 1000); + feparams->frequency = 1000 * ((feparams->frequency + 500) / 1000); #ifdef SCAN_DEBUG printf("[FNT] new TP: sat %d delsys %d freq %d SR %d fec %d pol %d\n", diff --git a/src/zapit/src/femanager.cpp b/src/zapit/src/femanager.cpp index 19ce3e70a..590023cf6 100644 --- a/src/zapit/src/femanager.cpp +++ b/src/zapit/src/femanager.cpp @@ -2,7 +2,7 @@ Neutrino-GUI - DBoxII-Project Copyright (C) 2011 CoolStream International Ltd - Copyright (C) 2012 Stefan Seyfried + Copyright (C) 2012,2013,2014 Stefan Seyfried License: GPLv2 @@ -47,9 +47,7 @@ static int unused_demux; #define FEDEBUG(fmt, args...) \ do { \ if (fedebug) \ - fprintf(stdout, "[%s:%s:%d] " fmt "\n", \ - __file__, __func__, \ - __LINE__ , ## args); \ + INFO(fmt, ##args); \ } while (0) CFeDmx::CFeDmx(int i) @@ -116,6 +114,15 @@ bool CFEManager::Init() dmap.push_back(CFeDmx(i)); INFO("found %d frontends, %d demuxes\n", (int)femap.size(), (int)dmap.size()); + /* for testing without a frontend, export SIMULATE_FE=1 */ + if (femap.empty() && getenv("SIMULATE_FE")) { + INFO("SIMULATE_FE is set, adding dummy frontend for testing"); + fe = new CFrontend(0,0); + fe->setName("DuTu - The dummy tuner"); + fekey = MAKE_FE_KEY(0, 0); + femap.insert(std::pair (fekey, fe)); + livefe = fe; + } if (femap.empty()) return false; @@ -239,8 +246,9 @@ bool CFEManager::loadSettings() fe_config.diseqcRepeats = getConfigValue(fe, "diseqcRepeats", 0); fe_config.motorRotationSpeed = getConfigValue(fe, "motorRotationSpeed", 18); fe_config.highVoltage = getConfigValue(fe, "highVoltage", 0); - fe_config.uni_scr = getConfigValue(fe, "uni_scr", -1); + fe_config.uni_scr = getConfigValue(fe, "uni_scr", 0); fe_config.uni_qrg = getConfigValue(fe, "uni_qrg", 0); + fe_config.uni_pin = getConfigValue(fe, "uni_pin", -1); fe_config.diseqc_order = getConfigValue(fe, "diseqc_order", UNCOMMITED_FIRST); fe_config.use_usals = getConfigValue(fe, "use_usals", 0); fe_config.rotor_swap = getConfigValue(fe, "rotor_swap", 0); @@ -339,6 +347,7 @@ void CFEManager::saveSettings(bool write) setConfigValue(fe, "highVoltage", fe_config.highVoltage); setConfigValue(fe, "uni_scr", fe_config.uni_scr); setConfigValue(fe, "uni_qrg", fe_config.uni_qrg); + setConfigValue(fe, "uni_pin", fe_config.uni_pin); setConfigValue(fe, "diseqc_order", fe_config.diseqc_order); setConfigValue(fe, "use_usals", fe_config.use_usals); setConfigValue(fe, "rotor_swap", fe_config.rotor_swap); @@ -453,11 +462,15 @@ void CFEManager::linkFrontends(bool init) } if (init && femode != CFrontend::FE_MODE_UNUSED) fe->Init(); - if (femode != CFrontend::FE_MODE_UNUSED) { + if (femode != CFrontend::FE_MODE_UNUSED) + { enabled_count++; if ((fe->fenumber + 1) < (int) MAX_DMX_UNITS) demuxes[fe->fenumber + 1] = 1; } + else { /* unused -> no need to keep open */ + fe->Close(); + } } for(unsigned i = 0; i < MAX_DMX_UNITS; i++) { if (demuxes[i] == 0) { @@ -472,7 +485,7 @@ void CFEManager::Open() { for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { CFrontend * fe = it->second; - if(!fe->Locked()) + if (!fe->Locked() && fe->getMode() != CFrontend::FE_MODE_UNUSED) fe->Open(true); } } @@ -491,8 +504,15 @@ void CFEManager::Close() CFrontend * CFEManager::getFE(int index) { - if((unsigned int) index < femap.size()) - return femap[index]; + int i = 0; + /* the naive approach of just returning "femap[index]" does not work, since + * the first frontend (index = 0) does not necessary live on adapter0/frontend0 */ + for (fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) + { + if (index == i) + return it->second; + i++; + } INFO("Frontend #%d not found", index); return NULL; } @@ -642,7 +662,6 @@ CFrontend * CFEManager::allocateFE(CZapitChannel * channel, bool forrecord) { OpenThreads::ScopedLock m_lock(mutex); - fedebug = 1; if (forrecord) fedebug = 1; CFrontend * frontend = getFrontend(channel); @@ -659,7 +678,10 @@ CFrontend * CFEManager::allocateFE(CZapitChannel * channel, bool forrecord) #else channel->setRecordDemux(frontend->fenumber+1); channel->setPipDemux(frontend->fenumber+1); +#if HAVE_COOL_HARDWARE + /* I don't know if this check is necessary on cs, but it hurts on other hardware */ if(femap.size() > 1) +#endif cDemux::SetSource(frontend->fenumber+1, frontend->fenumber); #ifdef ENABLE_PIP /* FIXME until proper demux management */ @@ -677,7 +699,9 @@ void CFEManager::setLiveFE(CFrontend * fe) { OpenThreads::ScopedLock m_lock(mutex); livefe = fe; +#if HAVE_COOL_HARDWARE if(femap.size() > 1) +#endif cDemux::SetSource(0, livefe->fenumber); } diff --git a/src/zapit/src/frontend.cpp b/src/zapit/src/frontend.cpp index dcad640e0..9c6fee4aa 100644 --- a/src/zapit/src/frontend.cpp +++ b/src/zapit/src/frontend.cpp @@ -3,6 +3,7 @@ * * (C) 2002-2003 Andreas Oberritter * + * (C) 2007-2013,2015 Stefan Seyfried * Copyright (C) 2011 CoolStream International Ltd * * This program is free software; you can redistribute it and/or modify @@ -166,6 +167,8 @@ typedef enum dvb_fec { fNone = 15 } dvb_fec_t; +static fe_sec_voltage_t unicable_lowvolt = SEC_VOLTAGE_13; + #define TIME_STEP 200 #define TIMEOUT_MAX_MS (feTimeout*100) @@ -173,11 +176,11 @@ typedef enum dvb_fec { CFrontend::CFrontend(int Number, int Adapter) { - printf("[fe%d] New frontend on adapter %d\n", Number, Adapter); + DBG("[fe%d] New frontend on adapter %d\n", Number, Adapter); fd = -1; fenumber = Number; adapter = Adapter; - slave = false; //(Number != 0); //false; + slave = false; /* is set in frontend->setMasterSlave() */ standby = true; locked = false; usecount = 0; @@ -194,12 +197,20 @@ CFrontend::CFrontend(int Number, int Adapter) config.uni_scr = 0; /* the unicable SCR address 0-7 */ config.uni_qrg = 0; /* the unicable frequency in MHz */ config.uni_lnb = 0; /* for two-position switches */ + config.uni_pin = -1; /* for MDU setups */ config.highVoltage = false; config.motorRotationSpeed = 0; //in 0.1 degrees per second feTimeout = 40; currentVoltage = SEC_VOLTAGE_OFF; currentToneMode = SEC_TONE_ON; + /* some broken hardware (a coolstream neo on my desk) does not lower + * the voltage below 18V without enough DC load on the coax cable. + * with unicable bus setups, there is no DC load on the coax... leading + * to a completely blocked bus due to this broken hardware. + * Switching off the voltage completely works around this issue */ + if (getenv("UNICABLE_BROKEN_FRONTEND") != NULL) + unicable_lowvolt = SEC_VOLTAGE_OFF; memset(&info, 0, sizeof(info)); deliverySystemMask = UNKNOWN_DS; @@ -207,7 +218,7 @@ CFrontend::CFrontend(int Number, int Adapter) CFrontend::~CFrontend(void) { - printf("[fe%d] close frontend fd %d\n", fenumber, fd); + DBG("[fe%d] close frontend fd %d\n", fenumber, fd); if(fd >= 0) Close(); } @@ -219,7 +230,7 @@ bool CFrontend::Open(bool init) char filename[128]; snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend%d", adapter, fenumber); - printf("[fe%d] open %s\n", fenumber, filename); + DBG("[fe%d] open %s\n", fenumber, filename); mutex.lock(); if (fd < 0) { @@ -331,6 +342,8 @@ void CFrontend::getFEInfo(void) void CFrontend::Init(void) { + /* if frontend was not enabled before, it might not be opened */ + Open(); mutex.lock(); // Set the voltage to On, and wait voltage to become stable // and wait for diseqc equipment to be ready. @@ -346,7 +359,7 @@ void CFrontend::Close(void) if(standby) return; - printf("[fe%d] close frontend\n", fenumber); + INFO("[fe%d] close frontend fd %d", fenumber, fd); if (!slave && config.diseqcType > MINI_DISEQC) sendDiseqcStandby(); @@ -389,14 +402,14 @@ void CFrontend::reset(void) void CFrontend::Lock() { usecount++; - INFO("[fe%d] usecount %d tp %" PRIx64 "\n", fenumber, usecount, getTsidOnid()); + INFO("[fe%d] usecount %d tp %" PRIx64, fenumber, usecount, getTsidOnid()); } void CFrontend::Unlock() { if(usecount > 0) usecount--; - INFO("[fe%d] usecount %d tp %" PRIx64 "\n", fenumber, usecount, getTsidOnid()); + INFO("[fe%d] usecount %d tp %" PRIx64, fenumber, usecount, getTsidOnid()); } fe_code_rate_t CFrontend::getCFEC() @@ -539,8 +552,10 @@ fe_bandwidth_t CFrontend::getBandwidth(const uint8_t bandwidth) return BANDWIDTH_7_MHZ; case 0x02: return BANDWIDTH_6_MHZ; +#if _HAVE_DVB57 case 0x03: return BANDWIDTH_5_MHZ; +#endif default: return BANDWIDTH_AUTO; // AUTO } @@ -619,6 +634,8 @@ uint32_t CFrontend::getBitErrorRate(void) const { uint32_t ber = 0; fop(ioctl, FE_READ_BER, &ber); + if (ber > 100000000) /* azbox minime driver has useless values around 500.000.000 */ + ber = 0; return ber; } @@ -668,7 +685,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) while ((int) timer_msec < TIMEOUT_MAX_MS) { int ret = poll(&pfd, 1, TIMEOUT_MAX_MS - timer_msec); if (ret < 0) { - perror("CFrontend::getEvent poll"); + ERROR("poll"); continue; } if (ret == 0) { @@ -677,24 +694,27 @@ struct dvb_frontend_event CFrontend::getEvent(void) } if (pfd.revents & (POLLIN | POLLPRI)) { - FE_TIMER_STOP("poll has event after"); + //FE_TIMER_STOP("poll has event after"); + timer_msec = time_monotonic_ms() - timer_start; /* FE_TIMER_STOP does this :( */ memset(&event, 0, sizeof(struct dvb_frontend_event)); ret = ioctl(fd, FE_GET_EVENT, &event); if (ret < 0) { - perror("CFrontend::getEvent ioctl"); + ERROR("ioctl"); continue; } //printf("[fe%d] poll events %d status %x\n", fenumber, pfd.revents, event.status); + if (event.status == 0) /* some drivers always deliver an empty event after tune */ + continue; if (event.status & FE_HAS_LOCK) { - printf("[fe%d] ****************************** FE_HAS_LOCK: freq %lu\n", fenumber, (long unsigned int)event.parameters.frequency); + INFO("[fe%d] ******** FE_HAS_LOCK: freq %lu", fenumber, (long unsigned int)event.parameters.frequency); tuned = true; break; } else if (event.status & FE_TIMEDOUT) { if(timedout < timer_msec) timedout = timer_msec; - printf("[fe%d] ############################## FE_TIMEDOUT (max %u)\n", fenumber, timedout); + INFO("[fe%d] ######## FE_TIMEDOUT (max %d)", fenumber, timedout); /*break;*/ } else { if (event.status & FE_HAS_SIGNAL) @@ -718,7 +738,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) return event; } -void CFrontend::getDelSys(int f, int m, char *&fec, char *&sys, char *&mod) +void CFrontend::getDelSys(int f, int m, const char *&fec, const char *&sys, const char *&mod) { return getDelSys(getCurrentDeliverySystem(), f, m, fec, sys, mod); } @@ -792,25 +812,25 @@ void CFrontend::getXMLDelsysFEC(fe_code_rate_t xmlfec, delivery_system_t & delsy } } -void CFrontend::getDelSys(delivery_system_t delsys, int f, int m, char *&fec, char *&sys, char *&mod) +void CFrontend::getDelSys(delivery_system_t delsys, int f, int m, const char *&fec, const char *&sys, const char *&mod) { switch (delsys) { case DVB_S: - sys = (char *)"DVB"; - mod = (char *)"QPSK"; + sys = "DVB"; + mod = "QPSK"; break; case DVB_S2: - sys = (char *)"DVB-S2"; + sys = "DVB-S2"; switch (m) { case QPSK: - mod = (char *)"QPSK"; + mod = "QPSK"; break; case PSK_8: - mod = (char *)"8PSK"; + mod = "8PSK"; break; default: printf("[frontend] unknown modulation %d!\n", m); - mod = (char *)"UNKNOWN"; + mod = "UNKNOWN"; } break; case DVB_C: @@ -818,99 +838,103 @@ void CFrontend::getDelSys(delivery_system_t delsys, int f, int m, char *&fec, ch case DTMB: switch(delsys) { case DVB_C: - sys = (char *)"DVB-C(Annex A)"; + sys = "DVB-C(Annex A)"; break; case DVB_T: - sys = (char *)"DVB-T"; + sys = "DVB-T"; break; case DVB_T2: - sys = (char *)"DVB-T2"; + sys = "DVB-T2"; break; case DTMB: - sys = (char *)"DTMB"; + sys = "DTMB"; break; default: printf("[frontend] unknown delsys %d!\n", delsys); - sys = (char *)"UNKNOWN"; + sys = "UNKNOWN"; break; } switch (m) { case QAM_16: - mod = (char *)"QAM_16"; + mod = "QAM_16"; break; case QAM_32: - mod = (char *)"QAM_32"; + mod = "QAM_32"; break; case QAM_64: - mod = (char *)"QAM_64"; + mod = "QAM_64"; break; case QAM_128: - mod = (char *)"QAM_128"; + mod = "QAM_128"; break; case QAM_256: - mod = (char *)"QAM_256"; + mod = "QAM_256"; break; +#if _HAVE_DVB57 case QAM_4_NR: - mod = (char *)"QAM_4_NR"; + mod = "QAM_4_NR"; break; +#endif case QPSK: if (delsys == DVB_T || delsys == DVB_T2 || delsys == DTMB) { - mod = (char *)"QPSK"; // AKA QAM_4 + mod = "QPSK"; // AKA QAM_4 break; } /* fallthrouh for FE_QAM... */ case QAM_AUTO: default: - mod = (char *)"QAM_AUTO"; + mod = "QAM_AUTO"; break; } break; default: - printf("[frontend] unknown delsys %d!\n", delsys); - sys = (char *)"UNKNOWN"; - mod = (char *)"UNKNOWN"; + INFO("unknown delsys %d!", delsys); + sys = "UNKNOWN"; + mod = "UNKNOWN"; break; } switch (f) { case FEC_1_2: - fec = (char *)"1/2"; + fec = "1/2"; break; case FEC_2_3: - fec = (char *)"2/3"; + fec = "2/3"; break; case FEC_3_4: - fec = (char *)"3/4"; + fec = "3/4"; break; case FEC_4_5: - fec = (char *)"4/5"; + fec = "4/5"; break; case FEC_5_6: - fec = (char *)"5/6"; + fec = "5/6"; break; case FEC_6_7: - fec = (char *)"6/7"; + fec = "6/7"; break; case FEC_7_8: - fec = (char *)"7/8"; + fec = "7/8"; break; case FEC_8_9: - fec = (char *)"8/9"; + fec = "8/9"; break; case FEC_3_5: - fec = (char *)"3/5"; + fec = "3/5"; break; case FEC_9_10: - fec = (char *)"9/10"; + fec = "9/10"; break; +#if _HAVE_DVB57 case FEC_2_5: - fec = (char *)"2/3"; + fec = "2/5"; break; +#endif default: - printf("[frontend] getDelSys: unknown FEC: %d !!!\n", f); + INFO("unknown FEC: %d!", f); case FEC_AUTO: - fec = (char *)"AUTO"; + fec = "AUTO"; break; } } @@ -929,9 +953,11 @@ fe_delivery_system_t CFrontend::getFEDeliverySystem(delivery_system_t Delsys) case DVB_T: delsys = SYS_DVBT; break; +#if _HAVE_DVB57 case DVB_T2: delsys = SYS_DVBT2; break; +#endif case DVB_C: delsys = SYS_DVBC_ANNEX_A; break; @@ -947,15 +973,17 @@ fe_delivery_system_t CFrontend::getFEDeliverySystem(delivery_system_t Delsys) case ISDBS: delsys = SYS_ISDBS; break; - case DTMB: - delsys = SYS_DTMB; - break; case DSS: delsys = SYS_DSS; break; +#if _HAVE_DVB57 + case DTMB: + delsys = SYS_DTMB; + break; case TURBO: delsys = SYS_TURBO; break; +#endif default: delsys = SYS_UNDEFINED; break; @@ -1035,14 +1063,22 @@ uint32_t CFrontend::getFEBandwidth(fe_bandwidth_t bandwidth) case BANDWIDTH_6_MHZ: bandwidth_hz = 6000000; break; +#if HAVE_DVBT2 case BANDWIDTH_5_MHZ: bandwidth_hz = 5000000; break; +#endif } return bandwidth_hz; } +void CFrontend::setName(const char* _name) +{ + memset(info.name, '\0', sizeof(info.name)); + snprintf(info.name, sizeof(info.name)-1, "%s", _name); +} + bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_properties& cmdseq) { fe_pilot_t pilot = PILOT_OFF; @@ -1090,11 +1126,13 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p case FEC_9_10: fec = FEC_9_10; break; +#if HAVE_DTMB case FEC_2_5: fec = FEC_2_5; break; +#endif default: - printf("[fe%d] DEMOD: unknown FEC: %d\n", fenumber, fec_inner); + INFO("[fe%d] unknown FEC: %d", fenumber, fec_inner); case FEC_AUTO: fec = FEC_AUTO; break; @@ -1126,7 +1164,7 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p cmdseq.props[MODULATION].u.data = feparams->modulation; cmdseq.props[ROLLOFF].u.data = feparams->rolloff; cmdseq.props[PILOTS].u.data = pilot; - printf("[fe%d] tuner pilot %d (feparams %d)\n", fenumber, pilot, feparams->pilot); + if (zapit_debug) printf("[fe%d] tuner pilot %d (feparams %d)\n", fenumber, pilot, feparams->pilot); } else { memcpy(cmdseq.props, dvbs_cmdargs, sizeof(dvbs_cmdargs)); nrOfProps = FE_DVBS_PROPS; @@ -1160,7 +1198,7 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p cmdseq.props[BANDWIDTH].u.data = getFEBandwidth(feparams->bandwidth); break; default: - printf("frontend: unknown frontend type, exiting\n"); + INFO("unknown frontend type, exiting"); return false; } @@ -1180,6 +1218,10 @@ int CFrontend::setFrontend(const FrontendParameters *feparams, bool nowait) { struct dtv_property cmdargs[FE_COMMON_PROPS + FE_DVBT_PROPS]; // WARNING: increase when needed more space struct dtv_properties cmdseq; +#ifdef PEDANTIC_VALGRIND_SETUP + memset(&cmdargs, 0, sizeof(cmdargs)); + memset(&cmdseq, 0, sizeof(cmdseq)); +#endif cmdseq.num = FE_COMMON_PROPS; cmdseq.props = cmdargs; @@ -1200,13 +1242,13 @@ int CFrontend::setFrontend(const FrontendParameters *feparams, bool nowait) return 0; { - FE_TIMER_INIT(); - FE_TIMER_START(); + //FE_TIMER_INIT(); + //FE_TIMER_START(); if ((ioctl(fd, FE_SET_PROPERTY, &cmdseq)) < 0) { - perror("FE_SET_PROPERTY failed"); + ERROR("FE_SET_PROPERTY"); return false; } - FE_TIMER_STOP("FE_SET_PROPERTY took"); + //FE_TIMER_STOP("FE_SET_PROPERTY took"); } if (nowait) return 0; @@ -1243,12 +1285,12 @@ void CFrontend::secSetTone(const fe_sec_tone_mode_t toneMode, const uint32_t ms) return; } - printf("[fe%d] tone %s\n", fenumber, toneMode == SEC_TONE_ON ? "on" : "off"); - FE_TIMER_INIT(); - FE_TIMER_START(); + if (zapit_debug) printf("[fe%d] tone %s\n", fenumber, toneMode == SEC_TONE_ON ? "on" : "off"); + //FE_TIMER_INIT(); + //FE_TIMER_START(); if (fop(ioctl, FE_SET_TONE, toneMode) == 0) { currentToneMode = toneMode; - FE_TIMER_STOP("FE_SET_TONE took"); + //FE_TIMER_STOP("FE_SET_TONE took"); usleep(1000 * ms); } } @@ -1261,11 +1303,11 @@ void CFrontend::secSetVoltage(const fe_sec_voltage_t voltage, const uint32_t ms) if (currentVoltage == voltage) return; - printf("[fe%d] voltage %s\n", fenumber, voltage == SEC_VOLTAGE_OFF ? "OFF" : voltage == SEC_VOLTAGE_13 ? "13" : "18"); - if (config.diseqcType == DISEQC_UNICABLE) { + if (zapit_debug) printf("[fe%d] voltage %s\n", fenumber, voltage == SEC_VOLTAGE_OFF ? "OFF" : voltage == SEC_VOLTAGE_13 ? "13" : "18"); + if (config.diseqcType == DISEQC_UNICABLE && voltage != SEC_VOLTAGE_OFF) { /* see my comment in secSetTone... */ currentVoltage = voltage; /* need to know polarization for unicable */ - fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_13); /* voltage must not be 18V */ + fop(ioctl, FE_SET_VOLTAGE, unicable_lowvolt); /* voltage must not be 18V */ return; } @@ -1342,7 +1384,7 @@ void CFrontend::setDiseqcType(const diseqc_t newDiseqcType, bool force) if (newDiseqcType == DISEQC_UNICABLE) { secSetTone(SEC_TONE_OFF, 0); - secSetVoltage(SEC_VOLTAGE_13, 0); + secSetVoltage(unicable_lowvolt, 0); } else if ((force && (newDiseqcType != NO_DISEQC)) || ((config.diseqcType <= MINI_DISEQC) && (newDiseqcType > MINI_DISEQC))) { @@ -1454,7 +1496,6 @@ void CFrontend::setInput(t_satellite_position satellitePosition, uint32_t freque if (config.diseqcType == DISEQC_UNICABLE) return; - if (config.diseqcType != DISEQC_ADVANCED) { setDiseqc(sit->second.diseqc, polarization, frequency); return; @@ -1472,36 +1513,50 @@ void CFrontend::setInput(t_satellite_position satellitePosition, uint32_t freque /* frequency is the IF-frequency (950-2100), what a stupid spec... high_band, horizontal, bank are actually bool (0/1) - bank specifies the "switch bank" (as in Mini-DiSEqC A/B) */ + bank specifies the "switch bank" (as in Mini-DiSEqC A/B) + bank == 2 => send standby command */ uint32_t CFrontend::sendEN50494TuningCommand(const uint32_t frequency, const int high_band, const int horizontal, const int bank) { uint32_t bpf = config.uni_qrg; + int pin = config.uni_pin; + if (config.uni_scr < 0 || config.uni_scr > 7) { + WARN("uni_scr out of range (%d)", config.uni_scr); + return 0; + } + struct dvb_diseqc_master_cmd cmd = { {0xe0, 0x10, 0x5a, 0x00, 0x00, 0x00}, 5 }; unsigned int t = (frequency / 1000 + bpf + 2) / 4 - 350; - if (t < 1024 && config.uni_scr >= 0 && config.uni_scr < 8) + if (bank < 2 && t >= 1024) { - uint32_t ret = (t + 350) * 4000 - frequency; - INFO("[unicable] 18V=%d TONE=%d, freq=%d qrg=%d scr=%d bank=%d ret=%d", currentVoltage == SEC_VOLTAGE_18, currentToneMode == SEC_TONE_ON, frequency, bpf, config.uni_scr, bank, ret); - if (!slave && info.type == FE_QPSK) { - cmd.msg[3] = (t >> 8) | /* highest 3 bits of t */ - (config.uni_scr << 5) | /* adress */ + WARN("ooops. t > 1024? (%d)", t); + return 0; + } + if (pin >= 0 && pin < 0x100) { + cmd.msg[2] = 0x5c; + cmd.msg[5] = config.uni_pin; + cmd.msg_len = 6; + } + uint32_t ret = (t + 350) * 4000 - frequency; + INFO("[fe%d] 18V=%d 22k=%d freq=%d qrg=%d scr=%d bank=%d pin=%d ret=%d", + fenumber, horizontal, high_band, frequency, bpf, config.uni_scr, bank, pin, ret); + if (!slave && info.type == FE_QPSK) { + cmd.msg[3] = (config.uni_scr << 5); /* adress */ + if (bank < 2) { /* bank = 0/1 => tune, bank = 2 => standby */ + cmd.msg[3] |= (t >> 8) | /* highest 3 bits of t */ (bank << 4) | /* input 0/1 */ (horizontal << 3) | /* horizontal == 0x08 */ (high_band) << 2; /* high_band == 0x04 */ cmd.msg[4] = t & 0xFF; - fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_18); - usleep(15 * 1000); /* en50494 says: >4ms and < 22 ms */ - sendDiseqcCommand(&cmd, 50); /* en50494 says: >2ms and < 60 ms */ - fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_13); } - return ret; + fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_18); + usleep(15 * 1000); /* en50494 says: >4ms and < 22 ms */ + sendDiseqcCommand(&cmd, 50); /* en50494 says: >2ms and < 60 ms */ + fop(ioctl, FE_SET_VOLTAGE, unicable_lowvolt); } - - WARN("ooops. t > 1024? (%d) or uni_scr out of range? (%d)", t, config.uni_scr); - return 0; + return ret; } bool CFrontend::tuneChannel(CZapitChannel * /*channel*/, bool /*nvod*/) @@ -1549,7 +1604,7 @@ int CFrontend::setParameters(transponder *TP, bool nowait) freq = (int) feparams.frequency; - char * f, *s, *m; + const char *f, *s, *m; bool high_band; switch (feparams.delsys) { @@ -1654,7 +1709,7 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc if ((config.diseqcType == NO_DISEQC) || sat_no < 0) return; - printf("[fe%d] diseqc input %d -> %d\n", fenumber, currentDiseqc, sat_no); + if (zapit_debug) printf("[fe%d] diseqc input %d -> %d\n", fenumber, currentDiseqc, sat_no); currentDiseqc = sat_no; if (slave) return; @@ -1749,6 +1804,9 @@ void CFrontend::sendDiseqcReset(uint32_t ms) void CFrontend::sendDiseqcStandby(uint32_t ms) { printf("[fe%d] diseqc standby\n", fenumber); + if (config.diseqcType == DISEQC_UNICABLE) + sendEN50494TuningCommand(0, 0, 0, 2); + /* en50494 switches don't seem to be hurt by this */ // Send power off to 'all' equipment sendDiseqcZeroByteCommand(0xe0, 0x00, 0x02, ms); } @@ -1808,7 +1866,7 @@ int CFrontend::driveToSatellitePosition(t_satellite_position satellitePosition, if (sit != satellites.end()) old_position = sit->second.motor_position; - printf("[fe%d] sat pos %d -> %d motor pos %d -> %d usals %s\n", fenumber, rotorSatellitePosition, satellitePosition, old_position, new_position, use_usals ? "on" : "off"); + if (zapit_debug) printf("[fe%d] sat pos %d -> %d motor pos %d -> %d usals %s\n", fenumber, rotorSatellitePosition, satellitePosition, old_position, new_position, use_usals ? "on" : "off"); if (rotorSatellitePosition == satellitePosition) return 0; diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 96ad485af..6bf61aa9e 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -3,7 +3,7 @@ * * (C) 2002, 2003 by Andreas Oberritter * - * (C) 2007-2009, 2013 Stefan Seyfried + * (C) 2007-2013 Stefan Seyfried * (C) 2014 CoolStream International Ltd. * * This program is free software; you can redistribute it and/or modify @@ -167,7 +167,7 @@ void CServiceManager::RemoveAllChannels() void CServiceManager::RemovePosition(t_satellite_position satellitePosition) { - INFO("delete %d, size before: %d", satellitePosition, allchans.size()); + INFO("delete %d, size before: %zd", satellitePosition, allchans.size()); t_channel_id live_id = CZapit::getInstance()->GetCurrentChannelID(); for (channel_map_iterator_t it = allchans.begin(); it != allchans.end();) { if (it->second.getSatellitePosition() == satellitePosition && live_id != it->first) @@ -176,7 +176,7 @@ void CServiceManager::RemovePosition(t_satellite_position satellitePosition) ++it; } services_changed = true; - INFO("delete %d, size after: %d", satellitePosition, allchans.size()); + INFO("delete %d, size after: %zd", satellitePosition, allchans.size()); } #if 0 @@ -565,7 +565,7 @@ void CServiceManager::FindTransponder(xmlNodePtr search) const char * name = xmlGetAttribute(search, "name"); t_satellite_position satellitePosition = GetSatellitePosition(name); #endif - DBG("going to parse dvb-%c provider %s\n", xmlGetName(search)[0], xmlGetAttribute(search, "name")); + INFO("going to parse dvb-%c provider %s", xmlGetName(search)[0], xmlGetAttribute(search, "name")); ParseTransponders(xmlChildrenNode(search), satellitePosition, delsys); newfound++; search = xmlNextNode(search); @@ -746,11 +746,16 @@ int CServiceManager::LoadMotorPositions(void) printf("[getservices] loading motor positions...\n"); + /* this is only read and never written, so it only serves for + * upgrading from old pre-multituner capable neutrino */ if ((fd = fopen(SATCONFIG, "r"))) { fgets(buffer, 255, fd); while(!feof(fd)) { sscanf(buffer, "%d %d %d %d %d %d %d %d %d %d %d", &spos, &mpos, &diseqc, &com, &uncom, &offL, &offH, &sw, &inuse, &usals, &input); + int configured = 0; + if (diseqc != -1 || com != -1 || uncom != -1 || usals != 0 || mpos != 0) + configured = 1; satellitePosition = spos; sat_iterator_t sit = satellitePositions.find(satellitePosition); if(sit != satellitePositions.end()) { @@ -765,6 +770,7 @@ int CServiceManager::LoadMotorPositions(void) sit->second.use_usals = usals; sit->second.input = input; sit->second.position = satellitePosition; + sit->second.configured = configured; } fgets(buffer, 255, fd); } @@ -932,7 +938,7 @@ bool CServiceManager::LoadServices(bool only_current) printf("[zapit] %d services loaded (%d)...\n", service_count, (int)allchans.size()); TIMER_STOP("[zapit] service loading took"); - if(zapit_debug) {//FIXME + if(0) { //zapit_debug) {//FIXME sat_iterator_t sit; for(sit = satellitePositions.begin(); sit != satellitePositions.end(); ++sit) printf("satelliteName = %s (%d), satellitePosition = %d motor position = %d usals %d\n", sit->second.name.c_str(), (int)sit->second.name.size(), sit->first, sit->second.motor_position, sit->second.use_usals); diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index 150bf5b08..32d6c3088 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -36,6 +36,7 @@ #include #include #include +#include //#define USE_BAT @@ -96,6 +97,7 @@ bool CServiceScan::Stop() void CServiceScan::run() { + set_threadname("zap:servicescan"); running = true; CleanAllMaps(); @@ -118,9 +120,11 @@ void CServiceScan::run() fst_version = 0; ScanTransponder(); break; +#if 0 case SCAN_FAST: ScanFast(); break; +#endif default: break; } @@ -148,8 +152,22 @@ bool CServiceScan::tuneFrequency(FrontendParameters *feparams, t_satellite_posit return false; } } - - return frontend->tuneFrequency(feparams, false); + /* for unicable, retry tuning two times before assuming it failed */ + int retry = (frontend->getDiseqcType() == DISEQC_UNICABLE) * 2 + 1; + do { + ret = frontend->tuneFrequency(feparams, false); + if (ret) + return true; + if (abort_scan) + break; + retry--; + if (retry) { + int rand_us = (rand() * 1000000LL / RAND_MAX); + printf("[scan] SCR retrying tune, retry=%d after %dms\n", retry, rand_us/1000); + usleep(rand_us); + } + } while (retry > 0); + return false; } bool CServiceScan::AddTransponder(transponder_id_t TsidOnid, FrontendParameters *feparams, bool fromnit) @@ -526,7 +544,7 @@ void CServiceScan::SaveServices() bool CServiceScan::ScanProviders() { - flags = (int) scan_arg; + flags = *((int *)scan_arg); scanBouquetManager = new CBouquetManager(); printf("[scan] NIT %s, fta only: %s, satellites %s\n", flags & SCAN_NIT ? "yes" : "no", @@ -661,8 +679,10 @@ bool CServiceScan::ReplaceTransponderParams(freq_id_t freq, t_satellite_position void CServiceScan::SendTransponderInfo(transponder &t) { CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_NUM_SCANNED_TRANSPONDERS, &processed_transponders, sizeof(processed_transponders)); +#if 0 CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_PROVIDER, (void *) " ", 2); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SERVICENAME, (void *) " ", 2); +#endif CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_FREQUENCYP, &t.feparams, sizeof(FrontendParameters)); } diff --git a/src/zapit/src/scanbat.cpp b/src/zapit/src/scanbat.cpp index 01d655599..49e731568 100644 --- a/src/zapit/src/scanbat.cpp +++ b/src/zapit/src/scanbat.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #define DEBUG_BAT #define DEBUG_BAT_UNUSED @@ -68,6 +69,7 @@ bool CBat::Stop() void CBat::run() { + set_threadname("zap:bat"); if(Parse()) printf("[scan] BAT finished.\n"); else diff --git a/src/zapit/src/scannit.cpp b/src/zapit/src/scannit.cpp index dc47c6686..cb7a81b0b 100644 --- a/src/zapit/src/scannit.cpp +++ b/src/zapit/src/scannit.cpp @@ -29,6 +29,7 @@ #include #include #include +#include //#define DEBUG_NIT //#define DEBUG_NIT_UNUSED @@ -65,6 +66,7 @@ bool CNit::Stop() void CNit::run() { + set_threadname("zap:nit"); if(Parse()) printf("[scan] NIT finished.\n"); else diff --git a/src/zapit/src/scanpmt.cpp b/src/zapit/src/scanpmt.cpp index 0229e583b..0184f2f38 100644 --- a/src/zapit/src/scanpmt.cpp +++ b/src/zapit/src/scanpmt.cpp @@ -93,7 +93,7 @@ bool CPmt::Parse(CZapitChannel * const channel) ProgramMapSection pmt(buffer); - printf("[pmt] pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), pmt.getPcrPid()); + DBG("pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), pmt.getPcrPid()); channel->resetPids(); @@ -182,14 +182,14 @@ bool CPmt::ParseEsInfo(ElementaryStreamInfo *esinfo, CZapitChannel * const chann TeletextDescriptor *td = (TeletextDescriptor*)d; const VbiTeletextList *vbilist = td->getVbiTeletexts(); VbiTeletextConstIterator it; - printf("[pmt] teletext pid %04x\n", esinfo->getPid()); + DBG("teletext pid %04x\n", esinfo->getPid()); for (it = vbilist->begin(); it != vbilist->end(); ++it) { VbiTeletext * vbi = *it; std::string lang = vbi->getIso639LanguageCode(); uint8_t page = vbi->getTeletextPageNumber(); uint8_t magazine = vbi->getTeletextMagazineNumber(); - printf("[pmt] teletext type %d mag %d page %d lang [%s]\n", + DBG("teletext type %d mag %d page %d lang [%s]\n", vbi->getTeletextType(), magazine, page, lang.c_str()); if (vbi->getTeletextType() == 0x01) channel->setTeletextLang(lang); @@ -317,7 +317,7 @@ bool CPmt::ParseEsInfo(ElementaryStreamInfo *esinfo, CZapitChannel * const chann snprintf(str, DESC_MAX_LEN, "Unknown"); description = str; } - printf("[pmt] apid %04x stream %02x type %d [%s]\n", esinfo->getPid(), stream_type, + DBG("apid %04x stream %02x type %d [%s]\n", esinfo->getPid(), stream_type, (int) audio_type, description.c_str()); if(CServiceScan::getInstance()->Scanning()) { if(channel->getPreAudioPid() == 0) @@ -413,7 +413,7 @@ int pmt_set_update_filter(CZapitChannel * const channel, int * fd) int pmt_stop_update_filter(int * fd) { - printf("[pmt] stop update filter\n"); + DBG("\n"); #if HAVE_TRIPLEDRAGON if (pmtDemux) delete pmtDemux; diff --git a/src/zapit/src/transponder.cpp b/src/zapit/src/transponder.cpp index 8aaca5a1c..9ad962dc0 100644 --- a/src/zapit/src/transponder.cpp +++ b/src/zapit/src/transponder.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 CoolStream International Ltd - * Copyright (C) 2012 Stefan Seyfried + * Copyright (C) 2012,2014 Stefan Seyfried * * License: GPLv2 * @@ -162,7 +162,7 @@ void transponder::dump(std::string label) getFEParams()->modulation, getFEParams()->delsys); } else if (CFrontend::isTerr(feparams.delsys)) { - printf("%s tp-id %016llx freq %d bw %d coderate_HP %d coderate_LP %d const %d guard %d %d\n", label.c_str(), + printf("%s tp-id %016" PRIx64 " freq %d bw %d coderate_HP %d coderate_LP %d const %d guard %d %d\n", label.c_str(), transponder_id, getFEParams()->frequency, getFEParams()->bandwidth, @@ -198,7 +198,7 @@ char transponder::pol(unsigned char p) std::string transponder::description() { char buf[128] = {0}; - char *f, *s, *m, *f2; + const char *f, *s, *m, *f2; if (CFrontend::isSat(feparams.delsys)) { CFrontend::getDelSys(feparams.delsys, getFEParams()->fec_inner, getFEParams()->modulation, f, s, m); diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index 9d2dbc4b4..2815e66b1 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -4,6 +4,7 @@ * zapit - d-box2 linux project * * (C) 2001, 2002 by Philipp Leusmann + * (C) 2007-2013 Stefan Seyfried * Copyright (C) 2011 CoolStream International Ltd * * This program is free software; you can redistribute it and/or modify @@ -45,7 +46,7 @@ #include #include #include -#include +//#include #include #include #include @@ -64,17 +65,24 @@ #include #include #endif -#if HAVE_TRIPLEDRAGON -#include -#include +#if USE_STB_HAL +#include +#include #endif #include +#include #include #include #include #include +#ifdef PEDANTIC_VALGRIND_SETUP +#define VALGRIND_PARANOIA(x) memset(&x, 0, sizeof(x)) +#else +#define VALGRIND_PARANOIA(x) {} +#endif + /* globals */ int sig_delay = 2; // seconds between signal check @@ -564,11 +572,25 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay lock_channel_id = live_channel_id; last_channel_id = live_channel_id; SaveSettings(false); + srand(time(NULL)); + /* retry tuning twice when using unicable, TODO: EN50494 sect.8 specifies 4 retries... */ + int retry = (live_fe->getDiseqcType() == DISEQC_UNICABLE) * 2; + again: if(!TuneChannel(live_fe, newchannel, transponder_change)) { - t_channel_id chid = 0; - SendEvent(CZapitClient::EVT_TUNE_COMPLETE, &chid, sizeof(t_channel_id)); - return false; + if (retry < 1) { + t_channel_id chid = 0; + SendEvent(CZapitClient::EVT_TUNE_COMPLETE, &chid, sizeof(t_channel_id)); + return false; + } + int rand_us = (rand() * 1000000LL / RAND_MAX); /* max. 1 second delay */ + printf("[zapit] %s:1 SCR retry tuning %d after %dms\n", __func__, retry, rand_us / 1000); + /* EN50494 sect.8 specifies an elaborated way of calculating the delay, but I'm + * pretty sure rand() is not much worse :-) */ + usleep(rand_us); + live_fe->tuned = false; + retry--; + goto again; } SendEvent(CZapitClient::EVT_TUNE_COMPLETE, &live_channel_id, sizeof(t_channel_id)); @@ -589,6 +611,15 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay failed = !ParsePatPmt(current_channel); + if (failed && retry > 0) { + int rand_us = (rand() * 1000000LL / RAND_MAX); + printf("[zapit] %s:2 SCR retry tuning %d after %dms\n", __func__, retry, rand_us / 1000); + usleep(rand_us); + live_fe->tuned = false; + retry--; + goto again; + } + if ((!failed) && (current_channel->getAudioPid() == 0) && (current_channel->getVideoPid() == 0)) { printf("[zapit] neither audio nor video pid found\n"); failed = true; @@ -609,7 +640,7 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay if (startplayback /* && !we_playing*/) StartPlayBack(current_channel); - printf("[zapit] sending capmt....\n"); + //printf("[zapit] sending capmt....\n"); SendPMT(forupdate); //play: @@ -712,6 +743,8 @@ bool CZapit::ZapForRecord(const t_channel_id channel_id) { CZapitChannel* newchannel; bool transponder_change; + /* retry tuning twice when using unicable */ + int retry = (live_fe->getDiseqcType() == DISEQC_UNICABLE) * 2; if((newchannel = CServiceManager::getInstance()->FindChannel(channel_id)) == NULL) { INFO("channel_id " PRINTF_CHANNEL_ID_TYPE " not found", channel_id); @@ -724,15 +757,30 @@ bool CZapit::ZapForRecord(const t_channel_id channel_id) ERROR("Cannot get frontend\n"); return false; } + again: if(!TuneChannel(frontend, newchannel, transponder_change)) - return false; + { + if (retry < 1) + return false; + printf("[zapit] %s:1 unicable retry tuning %d\n", __func__, retry); + live_fe->tuned = false; + retry--; + goto again; + } #ifdef ENABLE_PIP if (transponder_change && (frontend == pip_fe)) StopPip(); #endif if(!ParsePatPmt(newchannel)) - return false; + { + if (retry < 1) + return false; + printf("[zapit] %s:2 unicable retry tuning %d\n", __func__, retry); + live_fe->tuned = false; + retry--; + goto again; + } return true; } @@ -915,7 +963,7 @@ void CZapit::SetAudioStreamType(CZapitAudioChannel::ZapitAudioChannelType audioC int newpercent = GetPidVolume(0, 0, audioChannelType == CZapitAudioChannel::AC3); SetVolumePercent(newpercent); - printf("[zapit] starting %s audio\n", audioStr); + DBG("starting %s audio\n", audioStr); } bool CZapit::ChangeAudioPid(uint8_t index) @@ -1024,7 +1072,7 @@ bool CZapit::StartScan(int scan_mode) { PrepareScan(); - CServiceScan::getInstance()->Start(CServiceScan::SCAN_PROVIDER, (void *) scan_mode); + CServiceScan::getInstance()->Start(CServiceScan::SCAN_PROVIDER, &scan_mode); return true; } @@ -1050,6 +1098,7 @@ bool CZapit::StartFastScan(int scan_mode, int opid) void CZapit::SendCmdReady(int connfd) { CZapitMessages::responseCmd response; + VALGRIND_PARANOIA(response); response.cmd = CZapitMessages::CMD_READY; CBasicServer::send_data(connfd, &response, sizeof(response)); } @@ -1124,6 +1173,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_ZAPTO_SUBSERVICEID: { CZapitMessages::commandZaptoServiceID msgZaptoServiceID; CZapitMessages::responseZapComplete msgResponseZapComplete; + VALGRIND_PARANOIA(msgResponseZapComplete); CBasicServer::receive_data(connfd, &msgZaptoServiceID, sizeof(msgZaptoServiceID)); if(msgZaptoServiceID.record) msgResponseZapComplete.zapStatus = ZapForRecord(msgZaptoServiceID.channel_id); @@ -1195,6 +1245,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_MODE: { CZapitMessages::responseGetMode msgGetMode; + VALGRIND_PARANOIA(msgGetMode); msgGetMode.mode = (CZapitClient::channelsMode) getMode(); CBasicServer::send_data(connfd, &msgGetMode, sizeof(msgGetMode)); break; @@ -1202,6 +1253,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_CURRENT_SERVICEID: { CZapitMessages::responseGetCurrentServiceID msgCurrentSID; + VALGRIND_PARANOIA(msgCurrentSID); msgCurrentSID.channel_id = (current_channel != 0) ? current_channel->getChannelID() : 0; CBasicServer::send_data(connfd, &msgCurrentSID, sizeof(msgCurrentSID)); break; @@ -1209,6 +1261,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_CURRENT_SERVICEINFO: { CZapitClient::CCurrentServiceInfo msgCurrentServiceInfo; + VALGRIND_PARANOIA(msgCurrentServiceInfo); memset(&msgCurrentServiceInfo, 0, sizeof(CZapitClient::CCurrentServiceInfo)); if(current_channel) { msgCurrentServiceInfo.onid = current_channel->getOriginalNetworkId(); @@ -1239,6 +1292,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_DELIVERY_SYSTEM: { CZapitMessages::responseDeliverySystem response; + VALGRIND_PARANOIA(response); response.system = live_fe->getCurrentDeliverySystem(); CBasicServer::send_data(connfd, &response, sizeof(response)); break; @@ -1275,6 +1329,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_CHANNEL_NAME: { t_channel_id requested_channel_id; CZapitMessages::responseGetChannelName response; + VALGRIND_PARANOIA(response); CBasicServer::receive_data(connfd, &requested_channel_id, sizeof(requested_channel_id)); response.name[0] = 0; CZapitChannel * channel = (requested_channel_id == 0) ? current_channel : @@ -1406,6 +1461,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_SCANREADY: { CZapitMessages::responseIsScanReady msgResponseIsScanReady; + VALGRIND_PARANOIA(msgResponseIsScanReady); #if 0 //FIXME used only when scanning done using pzapit client, is it really needed ? msgResponseIsScanReady.satellite = curr_sat; msgResponseIsScanReady.transponder = found_transponders; @@ -1420,6 +1476,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_SCANGETSATLIST: { uint32_t satlength; CZapitClient::responseGetSatelliteList sat; + VALGRIND_PARANOIA(sat); satlength = sizeof(sat); satellite_map_t satmap = CServiceManager::getInstance()->SatelliteList(); @@ -1505,6 +1562,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_RECORD_MODE: { CZapitMessages::responseGetRecordModeState msgGetRecordModeState; + VALGRIND_PARANOIA(msgGetRecordModeState); msgGetRecordModeState.activated = (currentMode & RECORD_MODE); CBasicServer::send_data(connfd, &msgGetRecordModeState, sizeof(msgGetRecordModeState)); break; @@ -1513,6 +1571,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_SB_GET_PLAYBACK_ACTIVE: { /* FIXME check if needed */ CZapitMessages::responseGetPlaybackState msgGetPlaybackState; + VALGRIND_PARANOIA(msgGetPlaybackState); msgGetPlaybackState.activated = playing; msgGetPlaybackState.activated = videoDecoder->getPlayState(); CBasicServer::send_data(connfd, &msgGetPlaybackState, sizeof(msgGetPlaybackState)); @@ -1547,6 +1606,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_BQ_EXISTS_BOUQUET: { CZapitMessages::responseGeneralInteger responseInteger; + VALGRIND_PARANOIA(responseInteger); char * name = CBasicServer::receive_string(connfd); responseInteger.number = g_bouquetManager->existsBouquet(name); @@ -1668,14 +1728,24 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) } #endif case CZapitMessages::CMD_SB_START_PLAYBACK: + { + CZapitMessages::commandBoolean msgBool; + CBasicServer::receive_data(connfd, &msgBool, sizeof(msgBool)); //playbackStopForced = false; StartPlayBack(current_channel); + if (msgBool.truefalse) + SendPMT(); break; + } case CZapitMessages::CMD_SB_STOP_PLAYBACK: - StopPlayBack(false); + { + CZapitMessages::commandBoolean msgBool; + CBasicServer::receive_data(connfd, &msgBool, sizeof(msgBool)); + StopPlayBack(msgBool.truefalse); SendCmdReady(connfd); break; + } #ifdef ENABLE_PIP case CZapitMessages::CMD_STOP_PIP: @@ -1685,6 +1755,12 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) #endif case CZapitMessages::CMD_SB_LOCK_PLAYBACK: + { +#ifdef CHECK_MERGE + CZapitMessages::commandBoolean msgBool; + CBasicServer::receive_data(connfd, &msgBool, sizeof(msgBool)); + StopPlayBack(msgBool.truefalse, false); +#endif #if 0 /* hack. if standby true, dont blank video */ standby = true; @@ -1696,12 +1772,19 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) lockPlayBack(); SendCmdReady(connfd); break; + } case CZapitMessages::CMD_SB_UNLOCK_PLAYBACK: + { +#ifdef CHECK_MERGE + CZapitMessages::commandBoolean msgBool; + CBasicServer::receive_data(connfd, &msgBool, sizeof(msgBool)); +#endif #if 0 playbackStopForced = false; if (lock_channel_id == live_channel_id) { StartPlayBack(current_channel); - SendPMT(); + if (msgBool.truefalse) + SendPMT(); } else { live_fe->setTsidOnid(0); if (!ZapIt(lock_channel_id)) @@ -1712,6 +1795,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) unlockPlayBack(); SendCmdReady(connfd); break; + } #if 0 case CZapitMessages::CMD_SET_DISPLAY_FORMAT: { CZapitMessages::commandInt msg; @@ -1746,6 +1830,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_ASPECTRATIO: { CZapitMessages::commandInt msg; + VALGRIND_PARANOIA(msg); aspectratio=videoDecoder->getAspectRatio(); msg.val = aspectratio; CBasicServer::send_data(connfd, &msg, sizeof(msg)); @@ -1774,6 +1859,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GETPIDS: { if (current_channel) { CZapitClient::responseGetOtherPIDs responseGetOtherPIDs; + VALGRIND_PARANOIA(responseGetOtherPIDs); responseGetOtherPIDs.vpid = current_channel->getVideoPid(); responseGetOtherPIDs.ecmpid = 0; // TODO: remove responseGetOtherPIDs.vtxtpid = current_channel->getTeletextPid(); @@ -1874,6 +1960,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) } case CZapitMessages::CMD_GET_VOLUME: { CZapitMessages::commandVolume msgVolume; + VALGRIND_PARANOIA(msgVolume); #if 0 msgVolume.left = volume_left; msgVolume.right = volume_right; @@ -1884,6 +1971,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) } case CZapitMessages::CMD_GET_MUTE_STATUS: { CZapitMessages::commandBoolean msgBoolean; + VALGRIND_PARANOIA(msgBoolean); msgBoolean.truefalse = audioDecoder->getMuteStatus(); CBasicServer::send_data(connfd, &msgBoolean, sizeof(msgBoolean)); break; @@ -1894,9 +1982,9 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) if (msgBoolean.truefalse) { // if(currentMode & RECORD_MODE) videoDecoder->freeze(); enterStandby(); - SendCmdReady(connfd); } else leaveStandby(); + SendCmdReady(connfd); break; } #if 0 @@ -1945,6 +2033,7 @@ void CZapit::addChannelToBouquet(const unsigned int bouquet, const t_channel_id bool CZapit::send_data_count(int connfd, int data_count) { CZapitMessages::responseGeneralInteger responseInteger; + VALGRIND_PARANOIA(responseInteger); responseInteger.number = data_count; if (CBasicServer::send_data(connfd, &responseInteger, sizeof(responseInteger)) == false) { ERROR("could not send any return"); @@ -1959,6 +2048,7 @@ void CZapit::sendAPIDs(int connfd) return; for (uint32_t i = 0; i < current_channel->getAudioChannelCount(); i++) { CZapitClient::responseGetAPIDs response; + VALGRIND_PARANOIA(response); response.pid = current_channel->getAudioPid(i); strncpy(response.desc, current_channel->getAudioChannel(i)->description.c_str(), DESC_MAX_LEN-1); response.is_ac3 = response.is_aac = response.is_eac3 = 0; @@ -1987,6 +2077,7 @@ void CZapit::internalSendChannels(int connfd, ZapitChannelList* channels, const for (uint32_t i = 0; i < channels->size();i++) { if(nonames) { CZapitClient::responseGetBouquetNChannels response; + VALGRIND_PARANOIA(response); response.nr = first_channel_nr + i; if (CBasicServer::send_data(connfd, &response, sizeof(response)) == false) { @@ -1998,6 +2089,7 @@ void CZapit::internalSendChannels(int connfd, ZapitChannelList* channels, const } } else { CZapitClient::responseGetBouquetChannels response; + VALGRIND_PARANOIA(response); strncpy(response.name, ((*channels)[i]->getName()).c_str(), CHANNEL_NAME_SIZE-1); response.name[CHANNEL_NAME_SIZE-1] = 0; //printf("internalSendChannels: name %s\n", response.name); @@ -2020,6 +2112,7 @@ void CZapit::internalSendChannels(int connfd, ZapitChannelList* channels, const void CZapit::sendBouquets(int connfd, const bool emptyBouquetsToo, CZapitClient::channelsMode mode) { CZapitClient::responseGetBouquets msgBouquet; + VALGRIND_PARANOIA(msgBouquet); int curMode; switch(mode) { case CZapitClient::MODE_TV: @@ -2151,6 +2244,15 @@ bool CZapit::StartPlayBack(CZapitChannel *thisChannel) pcrDemux->Start(); } +#if HAVE_AZBOX_HARDWARE + /* new (> 20130917) AZbox drivers switch to radio mode if audio is started first */ + /* start video */ + if (have_video) { + videoDecoder->Start(0, thisChannel->getPcrPid(), thisChannel->getVideoPid()); + videoDemux->Start(); + } +#endif + /* select audio output and start audio */ if (audio_pid) { SetAudioStreamType(thisChannel->getAudioChannel()->audioChannelType); @@ -2158,11 +2260,13 @@ bool CZapit::StartPlayBack(CZapitChannel *thisChannel) audioDecoder->Start(); } +#if ! HAVE_AZBOX_HARDWARE /* start video */ if (video_pid) { videoDecoder->Start(0, pcr_pid, video_pid); videoDemux->Start(); } +#endif #ifdef USE_VBI if(teletext_pid) videoDecoder->StartVBI(teletext_pid); @@ -2172,7 +2276,7 @@ bool CZapit::StartPlayBack(CZapitChannel *thisChannel) return true; } -bool CZapit::StopPlayBack(bool send_pmt) +bool CZapit::StopPlayBack(bool send_pmt, bool blank) { INFO("standby %d playing %d forced %d send_pmt %d", standby, playing, playbackStopForced, send_pmt); if(send_pmt) @@ -2191,13 +2295,24 @@ bool CZapit::StopPlayBack(bool send_pmt) if (playbackStopForced) return false; +#if HAVE_AZBOX_HARDWARE + pcrDemux->Stop(); + + if (current_channel && current_channel->getVideoPid()) { + videoDemux->Stop(); + videoDecoder->Stop(standby ? false : true); + } + audioDemux->Stop(); + audioDecoder->Stop(); +#else videoDemux->Stop(); audioDemux->Stop(); pcrDemux->Stop(); audioDecoder->Stop(); /* hack. if standby, dont blank video -> for paused timeshift */ - videoDecoder->Stop(standby ? false : true); + videoDecoder->Stop(standby ? false : blank); +#endif #ifdef USE_VBI videoDecoder->StopVBI(); #endif @@ -2362,8 +2477,14 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) pipDecoder = cVideo::GetDecoder(1); pipDecoder->SetDemux(pipDemux); #endif +#else +#if HAVE_COOL_HARDWARE + /* work around broken drivers: when starting up with 720p50 image is pink on hd1 */ + videoDecoder = new cVideo(VIDEO_STD_1080I50, videoDemux->getChannel(), videoDemux->getBuffer()); + videoDecoder->SetVideoSystem(video_mode); #else videoDecoder = new cVideo(video_mode, videoDemux->getChannel(), videoDemux->getBuffer()); +#endif videoDecoder->Standby(false); audioDecoder = new cAudio(audioDemux->getBuffer(), videoDecoder->GetTVEnc(), NULL /*videoDecoder->GetTVEncSD()*/); @@ -2460,6 +2581,7 @@ bool CZapit::Stop() { if(!started) return false; + pmt_stop_update_filter(&pmt_update_fd); started = false; int ret = join(); return (ret == 0); @@ -2477,6 +2599,10 @@ bool CZapit::getUseChannelFilter() void CZapit::run() { +#if HAVE_SPARK_HARDWARE + bool v_stopped = false; +#endif + set_threadname("zap:main"); printf("[zapit] starting... tid %ld\n", syscall(__NR_gettid)); abort_zapit = 0; @@ -2521,6 +2647,32 @@ void CZapit::run() SendEvent(CZapitClient::EVT_PMT_CHANGED, &channel_id, sizeof(channel_id)); } } +#if HAVE_SPARK_HARDWARE + /* hack: stop videodecoder if the tuner looses lock + * at least the h264 decoder seems unhappy if he runs out of data... + * ...until we fix the driver, let's work around it here. + * theoretically, a "retune()" function could also be implemented here + * for the case that the driver cannot re-lock the tuner (DiSEqC problem, + * unicable collision, .... */ + if (live_fe->tuned) + { + if (!live_fe->getStatus() && !v_stopped) + { + fprintf(stderr, "[zapit] LOST LOCK! stopping video...\n"); + videoDecoder->Stop(false); + v_stopped = true; + } + else if (live_fe->getStatus()) + { + if (v_stopped) + { + fprintf(stderr, "[zapit] reacquired LOCK! starting video...\n"); + videoDecoder->Start(); + } + v_stopped = false; + } + } +#endif } /* yuck, don't waste that much cpu time :) */ usleep(0); @@ -2649,6 +2801,7 @@ void CZapitSdtMonitor::run() t_satellite_position satellitePosition = 0; freq_id_t freq = 0; transponder_id_t tpid = 0; + set_threadname("zap:sdtmonitor"); //tstart = time(0); sdt_tp.clear();