diff --git a/.gitignore b/.gitignore index 43dd1585a..4f8e80caf 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,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/configure.ac b/configure.ac index 8abb638ab..63a87f555 100644 --- a/configure.ac +++ b/configure.ac @@ -12,19 +12,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, @@ -126,7 +134,17 @@ 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" = "generic" || + 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) @@ -157,6 +175,12 @@ AC_ARG_ENABLE(viasatepg, [ --enable-viasatepg enable ViaSat EPG code (experimental)], [AC_DEFINE(ENABLE_VIASATEPG,1,[enable ViaSat EPG code])]) +AC_ARG_ENABLE(fastscan, + [ --enable-fastscan enable Fastscan code)], + [AC_DEFINE(ENABLE_FASTSCAN,1,[enable fastscan code])]) + +AM_CONDITIONAL(ENABLE_FASTSCAN, test "$enable_fastscan" = "yes") + AC_ARG_ENABLE(giflib, AS_HELP_STRING(--enable-giflib,use giflib instead of libungif), ,[enable_giflib=no]) @@ -197,10 +221,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 @@ -277,6 +326,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) diff --git a/data/locale/Makefile.am b/data/locale/Makefile.am index 95e3a1165..5f57ba3fe 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 b3cb599a6..4140c42b0 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -2245,8 +2245,8 @@ servicemenu.head Service servicemenu.imageinfo Imageinfo servicemenu.reload Kanallisten neu laden servicemenu.reload_hint Kanallisten werden neu geladen,\nbitte warten ... -servicemenu.restart GUI neu starten -servicemenu.restart_hint GUI wird neu gestartet ... +servicemenu.restart Neutrino neu starten +servicemenu.restart_hint Neutrino wird neu gestartet ... servicemenu.restart_refused_recording Aufnahme läuft. Neustart nicht möglich. servicemenu.scants Kanalsuche servicemenu.update Software-Aktualisierung diff --git a/data/locale/english.locale b/data/locale/english.locale index 2d267ff64..df080ca1a 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -1409,7 +1409,7 @@ menu.hint_sleeptimer Set timer to put your box\nin sleep mode menu.hint_sleeptimer_min Default setting for sleeptimer menu.hint_sms_channel If enabled, numeric buttons in channel list used to search channel in SMS style menu.hint_sms_movie If enabled, numeric buttons in moviebrowser used to search movie in SMS style -menu.hint_soft_restart Restart GUI without reboot +menu.hint_soft_restart Restart Neutrino without reboot menu.hint_softupdate_check Check online update, download and flash firmware menu.hint_softupdate_check_local Select and flash firmware from local file menu.hint_softupdate_createimage_menu Backup of current software, including all settings @@ -2246,7 +2246,7 @@ servicemenu.imageinfo Image info servicemenu.reload Reload channel lists servicemenu.reload_hint Reloading channel lists,\nplease be patient. servicemenu.restart Soft restart -servicemenu.restart_hint Restarting, please wait +servicemenu.restart_hint Restarting, please wait ... servicemenu.restart_refused_recording Cant restart, recording in progress servicemenu.scants Servicescan servicemenu.update Software Update 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/lib/hardware/coolstream/hardware_caps.cpp b/lib/hardware/coolstream/hardware_caps.cpp index 0922eb655..156c6ea5d 100644 --- a/lib/hardware/coolstream/hardware_caps.cpp +++ b/lib/hardware/coolstream/hardware_caps.cpp @@ -34,6 +34,7 @@ hw_caps_t *get_hwcaps(void) { caps.can_ps_14_9 = 1; caps.force_tuner_2G = 0; strcpy(caps.boxvendor, "Coolstream"); + strcpy(caps.boxarch, "Nevis"); switch (rev) { case 6: case 7: // Black Stallion Edition @@ -52,7 +53,6 @@ hw_caps_t *get_hwcaps(void) { break; case 10: strcpy(caps.boxname, "Zee"); - strcpy(caps.boxarch, "Nevis"); caps.force_tuner_2G = 1; break; case 11: 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/sectionsdclient/Makefile.am b/lib/sectionsdclient/Makefile.am index 8a322cd07..df4484b01 100644 --- a/lib/sectionsdclient/Makefile.am +++ b/lib/sectionsdclient/Makefile.am @@ -1,5 +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 a8a3c4648..cd5769996 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 8ba8dfab0..e9d8b16a3 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 96b51f53b..3eddb0fa4 100644 --- a/lib/timerdclient/Makefile.am +++ b/lib/timerdclient/Makefile.am @@ -1,5 +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 abd65735e..376b5fe76 100644 --- a/lib/timerdclient/timerdclient.cpp +++ b/lib/timerdclient/timerdclient.cpp @@ -28,6 +28,12 @@ #include #include +#ifdef PEDANTIC_VALGRIND_SETUP +#define VALGRIND_PARANOIA(x) memset(&x, 0, sizeof(x)) +#else +#define VALGRIND_PARANOIA(x) {} +#endif + unsigned char CTimerdClient::getVersion () const { return CTimerdMsg::ACTVERSION; @@ -43,6 +49,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 +65,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 +173,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 +212,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 +308,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 +381,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 +451,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 +462,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 +535,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 9657a4dab..ae101169f 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_CS_HD2 @@ -166,8 +166,46 @@ bin_PROGRAMS += drivertool drivertool_SOURCES = drivertool.c bin_PROGRAMS += dt dt_SOURCES = dt.c +endif bin_PROGRAMS += rcsim rcsim_SOURCES = rcsim.c rcsim.h bin_PROGRAMS += mdev_helper mdev_helper_SOURCES = mdev_helper.cpp + +if USE_STB_HAL +neutrino_LDADD += \ + -lstb-hal +neutrino_LDFLAGS = \ + $(STB_HAL_LIB) +endif + +if BOXTYPE_TRIPLE +neutrino_LDADD += \ + $(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_CS_HD2 +# 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/remotecontrol.cpp b/src/daemonc/remotecontrol.cpp index 03e515d01..cc38060e9 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 für 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); + const char *iso = getISO639Description(current_PIDs.APIDs[count].desc); +#ifdef APID_DEBUG + 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,7 @@ void CRemoteControl::processAPIDnames() if ( tmp_desc.size() == 3 ) { // unaufgeloeste Sprache... - tmp_desc = getISO639Description( current_PIDs.APIDs[count].desc ); + tmp_desc = iso; } if ( current_PIDs.APIDs[count].is_ac3 ) @@ -542,7 +536,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 +578,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 +730,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 +743,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 +754,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 1daf88a02..f4d708063 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -68,16 +68,23 @@ libneutrino_driver_a_SOURCES += \ lcdd.cpp endif -#if BOXTYPE_SPARK -#libneutrino_driver_a_SOURCES += \ -# fb_accel_sti.cpp \ -# simple_display.cpp -#endif - +if BOXTYPE_SPARK +libneutrino_driver_a_SOURCES += \ + fb_accel_sti.cpp \ + simple_display.cpp +endif +if BOXTYPE_AZBOX +libneutrino_driver_a_SOURCES += \ + simple_display.cpp +endif if BOXTYPE_GENERIC libneutrino_driver_a_SOURCES += \ fb_accel_glfb.cpp \ 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 ab579fcc1..b49f0cdb9 100644 --- a/src/driver/audiodec/Makefile.am +++ b/src/driver/audiodec/Makefile.am @@ -26,7 +26,6 @@ ASOURCES = cdrdec.cpp \ mp3dec.cpp \ oggdec.cpp \ tag.c \ - vis.cpp \ wavdec.cpp endif diff --git a/src/driver/audiodec/ffmpegdec.cpp b/src/driver/audiodec/ffmpegdec.cpp index ef2583775..02ccdb412 100644 --- a/src/driver/audiodec/ffmpegdec.cpp +++ b/src/driver/audiodec/ffmpegdec.cpp @@ -257,11 +257,7 @@ CBaseDec::RetCode CFfmpegDec::Decoder(FILE *_in, int /*OutputFd*/, State* state, mSampleRate = samplerate; mChannels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO); -#if __BYTE_ORDER == __LITTLE_ENDIAN audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 1); -#else - audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 0); -#endif AVFrame *frame = NULL; AVPacket rpacket; 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 c555add3f..789f5f0cd 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 */ @@ -1444,7 +1445,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); } @@ -1453,7 +1454,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); } } @@ -1464,3 +1465,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/fb_accel_sti.cpp b/src/driver/fb_accel_sti.cpp index 721120680..ff67528ab 100644 --- a/src/driver/fb_accel_sti.cpp +++ b/src/driver/fb_accel_sti.cpp @@ -36,8 +36,9 @@ #include #include #include - +#include #include + #include #include @@ -334,10 +335,12 @@ void CFbAccelSTi::run() int64_t last_blit = 0; blit_pending = false; blit_thread = true; - blit_mutex.lock(); set_threadname("stifb::autoblit"); while (blit_thread) { + blit_mutex.lock(); blit_cond.wait(&blit_mutex, blit_pending ? BLIT_INTERVAL_MIN : BLIT_INTERVAL_MAX); + blit_mutex.unlock(); + int64_t now = time_monotonic_ms(); int64_t diff = now - last_blit; if (diff < BLIT_INTERVAL_MIN) @@ -348,20 +351,22 @@ void CFbAccelSTi::run() else { blit_pending = false; - blit_mutex.unlock(); _blit(); - blit_mutex.lock(); last_blit = now; } } - blit_mutex.unlock(); printf(LOGTAG "::run end\n"); } void CFbAccelSTi::blit() { //printf(LOGTAG "::blit\n"); - blit_mutex.lock(); + int status = blit_mutex.trylock(); + if (status) { + printf(LOGTAG "::blit trylock failed: %d (%s)\n", status, + (status > 0) ? strerror(status) : strerror(errno)); + return; + } blit_cond.signal(); blit_mutex.unlock(); } diff --git a/src/driver/fb_generic.cpp b/src/driver/fb_generic.cpp index ad9f77d34..6d6409ff4 100644 --- a/src/driver/fb_generic.cpp +++ b/src/driver/fb_generic.cpp @@ -808,6 +808,7 @@ bool CFrameBuffer::paintIcon(const std::string & filename, const int x, const in return false; int yy = y; + bool freeicondata = false; //printf("CFrameBuffer::paintIcon: load %s\n", filename.c_str());fflush(stdout); /* we cache and check original name */ @@ -892,6 +893,8 @@ bool CFrameBuffer::paintIcon(const std::string & filename, const int x, const in cache_size += dsize; icon_cache.insert(std::pair (filename, tmpIcon)); //printf("Cached %s, cache size %d\n", newname.c_str(), cache_size); + }else{ + freeicondata = true; } } else { data = it->second.data; @@ -900,9 +903,13 @@ bool CFrameBuffer::paintIcon(const std::string & filename, const int x, const in //printf("paintIcon: already cached %s %d x %d\n", newname.c_str(), width, height); } _display: - if(!paint) + if(!paint){ + if(freeicondata){ + free(data); + data = NULL; + } return true; - + } if (h != 0) yy += (h - height) / 2; @@ -1382,7 +1389,7 @@ void CFrameBuffer::useBackground(bool ub) useBackgroundPaint = ub; if(!useBackgroundPaint) { delete[] background; - background=0; + background=NULL; } } @@ -1405,10 +1412,11 @@ void CFrameBuffer::saveBackgroundImage(void) void CFrameBuffer::restoreBackgroundImage(void) { - fb_pixel_t * tmp = background; + fb_pixel_t * tmp = NULL; if (backupBackground != NULL) { + tmp = background; background = backupBackground; backupBackground = NULL; } 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..cab2efc34 --- /dev/null +++ b/src/driver/fbaccel.cpp @@ -0,0 +1,1129 @@ +/* + 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 + +#if HAVE_COOL_HARDWARE || HAVE_TRIPLEDRAGON +#define NEED_BLIT_THREAD 0 +#else +#define NEED_BLIT_THREAD 1 +#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 +#ifdef 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; +#else + 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 +#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; +} diff --git a/src/driver/fbaccel.h b/src/driver/fbaccel.h new file mode 100644 index 000000000..965df48c9 --- /dev/null +++ b/src/driver/fbaccel.h @@ -0,0 +1,94 @@ +/* + 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 +}; + +#endif diff --git a/src/driver/file.h b/src/driver/file.h index f6d1b915c..0f1e3e473 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 3a5e1e5ff..b9927a508 100644 --- a/src/driver/fontrenderer.cpp +++ b/src/driver/fontrenderer.cpp @@ -679,6 +679,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_ng.cpp b/src/driver/framebuffer_ng.cpp new file mode 100644 index 000000000..5bd27337f --- /dev/null +++ b/src/driver/framebuffer_ng.cpp @@ -0,0 +1,1393 @@ +/* + 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 +#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}; + +static inline 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) +{ +/* 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; +} + +static inline int 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 nevis GXA accelerator.\n", xRes, yRes, bpp, stride, +#ifdef USE_NEVIS_GXA + "Using" +#else + "Not using" +#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 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, "[%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(dx*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', dx*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, dx-ofl-ofr, line, dx, col, pixBuf); + line++; + } + } else { + fb_pixel_t *bp = pixBuf; + int line = 0; + while (line < dy) { + for (int pos = 0; pos < dx; pos++) + *(bp + pos) = col; + bp += dx; + 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) +{ +#define MASK 0xFFFFFFFF + + fb_pixel_t* boxBuf = paintBoxRel2Buf(dx, dy, MASK, NULL, radius, type); + fb_pixel_t *bp = boxBuf; + fb_pixel_t *gra = gradientData->gradientBuf; + gradientData->boxBuf = boxBuf; + gradientData->x = x; + gradientData->dx = dx; + + if (gradientData->direction == gradientVertical) { + // vertical + for (int pos = 0; pos < dx; pos++) { + for(int count = 0; count < dy; count++) { + if (*(bp + pos) == MASK) + *(bp + pos) = (fb_pixel_t)(*(gra + count)); + bp += dx; + } + bp = boxBuf; + } + } else { + // horizontal + for (int line = 0; line < dy; line++) { + for (int pos = 0; pos < dx; pos++) { + if (*(bp + pos) == MASK) + *(bp + pos) = (fb_pixel_t)(*(gra + pos)); + } + bp += dx; + } + } + + if ((gradientData->mode & pbrg_noPaint) == pbrg_noPaint) + return boxBuf; + +// blit2FB(boxBuf, dx, dy, x, y); + blitBox2FB(boxBuf, dx, dy, x, 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; + + 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); +} + +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) +{ + paintLine(x, ya, x, yb, col); +} + +void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col) +{ + paintLine(x, y, x, y + dy, col); +} + +void CFrameBuffer::paintHLine(int xa, int xb, int y, const fb_pixel_t col) +{ + paintLine(xa, y, xb, y, col); +} + +void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col) +{ + paintLine(x, y, x + dx, y, col); +} + +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; + int lfd; + fb_pixel_t * data; + struct rawIcon tmpIcon; + std::map::iterator it; + int dsize; + + if (!getActive()) + return false; + + int yy = y; + //printf("CFrameBuffer::paintIcon: load %s\n", filename.c_str());fflush(stdout); + + if (filename.empty()) + return false; /* nothing to do */ + /* 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) { + 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"); + + lfd = open(newname.c_str(), O_RDONLY); + + if (lfd == -1) { + //printf("paintIcon: error while loading icon: %s\n", newname.c_str()); + return false; + } + read(lfd, &header, sizeof(struct rawHeader)); + + tmpIcon.width = width = (header.width_hi << 8) | header.width_lo; + tmpIcon.height = height = (header.height_hi << 8) | header.height_lo; + + 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); + 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) +{ + accel->blit2FB(fbbuff, width, height, xoff, yoff, xp, yp, transp); +} + +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); + + 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); + + 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(); +} diff --git a/src/driver/framebuffer_ng.h b/src/driver/framebuffer_ng.h new file mode 100644 index 000000000..7599c1f76 --- /dev/null +++ b/src/driver/framebuffer_ng.h @@ -0,0 +1,323 @@ +/* + 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 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) {} + sigc::signal OnAfterSetPallette; +}; + +#endif diff --git a/src/driver/lcdd.cpp b/src/driver/lcdd.cpp index 183988a90..85af71262 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 @@ -51,6 +51,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) { @@ -82,6 +84,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() { @@ -107,6 +110,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() @@ -131,17 +145,19 @@ 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) { set_threadname("lcd:time"); - while(1) + ((CLCD *)p)->thread_started = true; + while (((CLCD *)p)->thread_started) { sleep(1); struct stat buf; @@ -151,6 +167,7 @@ void* CLCD::TimeThread(void *) } else CLCD::getInstance()->wake_up(); } + printf("CLCD::TimeThread exit\n"); return NULL; } #else @@ -201,7 +218,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 ; @@ -375,7 +392,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; @@ -544,7 +561,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 @@ -559,11 +576,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; } @@ -606,7 +625,7 @@ void CLCD::setMovieAudio(const bool is_ac3) showPercentOver(percentOver, true, MODE_MOVIE); } -void CLCD::showTime() +void CLCD::showTime(bool) { if (showclock) { @@ -697,11 +716,13 @@ void CLCD::showVolume(const char vol, const bool perform_update) wake_up(); } -void CLCD::showPercentOver(const unsigned char perc, const bool perform_update, const MODES m) +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; percentOver = perc; @@ -884,13 +905,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) @@ -901,6 +923,7 @@ void CLCD::showAudioProgress(const char perc, bool isMuted) else display.draw_line (12,55,72,59, CLCDDisplay::PIXEL_ON); } +#endif displayUpdate(); } } @@ -1119,7 +1142,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/movieinfo.cpp b/src/driver/movieinfo.cpp index 415ef9374..a2fa9eb51 100644 --- a/src/driver/movieinfo.cpp +++ b/src/driver/movieinfo.cpp @@ -326,7 +326,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); @@ -341,7 +341,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); @@ -355,7 +355,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); @@ -370,7 +370,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/driver/netfile.cpp b/src/driver/netfile.cpp index 809b40605..70483a4d7 100644 --- a/src/driver/netfile.cpp +++ b/src/driver/netfile.cpp @@ -427,9 +427,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/png.cpp b/src/driver/pictureviewer/png.cpp index 28cea1670..ab0fb7155 100644 --- a/src/driver/pictureviewer/png.cpp +++ b/src/driver/pictureviewer/png.cpp @@ -52,11 +52,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); @@ -195,11 +191,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/radiotext.cpp b/src/driver/radiotext.cpp index e73207964..a97def1fa 100644 --- a/src/driver/radiotext.cpp +++ b/src/driver/radiotext.cpp @@ -2376,7 +2376,13 @@ void CRadioText::run() uint current_pid = 0; printf("CRadioText::run: ###################### Starting thread ######################\n"); +#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || HAVE_GENERIC_HARDWARE + int buflen = 0; + unsigned char *buf = NULL; + audioDemux = new cDemux(0); // live demux +#else audioDemux = new cDemux(1); +#endif audioDemux->Open(DMX_PES_CHANNEL,0,128*1024); while(running) { @@ -2401,11 +2407,41 @@ void CRadioText::run() } mutex.unlock(); if (pid) { +#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || HAVE_GENERIC_HARDWARE + int n; + unsigned char tmp[6]; + + n = audioDemux->Read(tmp, 6, 500); + if (n != 6) { + usleep(10000); /* save CPU if nothing read */ + continue; + } + if (memcmp(tmp, "\000\000\001\300", 4)) + continue; + int packlen = ((tmp[4] << 8) | tmp[5]) + 6; + + if (buflen < packlen) { + if (buf) + free(buf); + buf = (unsigned char *) calloc(1, packlen); + buflen = packlen; + } + if (!buf) + break; + memcpy(buf, tmp, 6); + + while ((n < packlen) && running) { + int len = audioDemux->Read(buf + n, packlen - n, 500); + if (len < 0) + break; + n += len; + } +#else int n; unsigned char buf[0x1FFFF]; n = audioDemux->Read(buf, sizeof(buf), 500 /*5000*/); - +#endif if (n > 0) { //printf("."); fflush(stdout); mutex.lock(); @@ -2414,6 +2450,10 @@ void CRadioText::run() } } } +#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE || HAVE_GENERIC_HARDWARE + if (buf) + free(buf); +#endif delete audioDemux; audioDemux = NULL; printf("CRadioText::run: ###################### exit ######################\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 4552688e6..1769811b6 100644 --- a/src/driver/rcinput.cpp +++ b/src/driver/rcinput.cpp @@ -259,8 +259,8 @@ void CRCInput::open(bool recheck) //+++++++++++++++++++++++++++++++++++++++ #ifdef KEYBOARD_INSTEAD_OF_REMOTE_CONTROL fd_keyb = STDIN_FILENO; - if (fd_rc[0] < 0) - fd_rc[0] = fd_keyb; + if (indev[0].fd < 0) + indev[0].fd = fd_keyb; #else fd_keyb = 0; #endif /* KEYBOARD_INSTEAD_OF_REMOTE_CONTROL */ @@ -1342,7 +1342,7 @@ void CRCInput::getMsg_us(neutrino_msg_t * msg, neutrino_msg_data_t * data, uint6 } uint32_t trkey = translate(ev.code); - printf("key: %04x value %d, translate: %04x -%s-\n", ev.code, ev.value, trkey, getKeyName(trkey).c_str()); + d_printf("key: %04x value %d, translate: %04x -%s-\n", ev.code, ev.value, trkey, getKeyName(trkey).c_str()); if (trkey == RC_nokey) continue; @@ -1386,13 +1386,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) && -#if HAVE_COOL_HARDWARE - (cs_get_revision() > 7) -#else - (g_info.hw_caps->can_shutdown) -#endif - ))) + (g_settings.shutdown_real_rcdelay && ((trkey == RC_standby) && (g_info.hw_caps->can_shutdown)))) { #ifdef ENABLE_REPEAT_CHECK if (rc_last_repeat_key != trkey) { @@ -1683,9 +1677,14 @@ const char * CRCInput::getSpecialKeyName(const unsigned int key) std::string CRCInput::getKeyName(const unsigned int key) { - std::string res(getKeyNameC(key & ~RC_Repeat)); - if ((key & RC_Repeat) && res != "unknown") - res += " (long)"; + std::string res; + if (key > RC_MaxRC) + res = getKeyNameC(key); /* will only resolve RC_nokey or "unknown" */ + else { + res = (getKeyNameC(key & ~RC_Repeat)); + if ((key & RC_Repeat) && res != "unknown") + res += " (long)"; + } return res; } @@ -1718,6 +1717,10 @@ int CRCInput::translate(int code) return RC_record; case KEY_PLAY: return RC_pause; + case KEY_CHANNELUP: + return RC_page_up; + case KEY_CHANNELDOWN: + return RC_page_down; #endif default: break; diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 83d9bd6a4..dc1d52fe7 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 @@ -294,7 +293,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 8b3c8df00..7466514d4 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 @@ -50,7 +50,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 7a659feff..da91163ea 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 d44eac6ab..ec4a80339 100644 --- a/src/driver/screenshot.cpp +++ b/src/driver/screenshot.cpp @@ -147,7 +147,6 @@ bool CScreenShot::GetData() #endif if (videoDecoder->getBlank()) get_video = false; - #ifdef BOXMODEL_CS_HD2 if (extra_osd && !get_video) { uint32_t memSize = xres * yres * sizeof(fb_pixel_t) * 2; @@ -162,7 +161,7 @@ bool CScreenShot::GetData() } else #endif -#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 @@ -318,11 +317,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 9bba124cf..e8e4ac9ce 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 @@ -40,10 +42,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; @@ -69,9 +82,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..df158909a --- /dev/null +++ b/src/driver/simple_display.cpp @@ -0,0 +1,504 @@ +/* + 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 +#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 + +#include + +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 *) +{ + set_threadname("n:boxdisplay"); /* to not confuse with TV display */ + 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..49a5e5c0a --- /dev/null +++ b/src/driver/stacktrace.h @@ -0,0 +1,93 @@ +// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ +// published under the WTFPL v2.0 + +#ifndef _STACKTRACE_H_ +#define _STACKTRACE_H_ + +#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); +} + +#endif // _STACKTRACE_H_ diff --git a/src/driver/streamts.cpp b/src/driver/streamts.cpp index 79da7d7f0..d67b782ea 100644 --- a/src/driver/streamts.cpp +++ b/src/driver/streamts.cpp @@ -57,7 +57,6 @@ #include #include #include - #include #include @@ -79,7 +78,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; @@ -105,7 +104,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); } @@ -114,7 +113,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); } @@ -141,7 +140,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; } @@ -157,7 +156,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) @@ -165,7 +164,7 @@ 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() @@ -210,7 +209,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; @@ -265,8 +264,11 @@ bool CStreamManager::Stop() if (!running) return false; running = false; - cancel(); - bool ret = (OpenThreads::Thread::join() == 0); + bool ret = false; + if (OpenThreads::Thread::CurrentThread() == this) { + cancel(); + ret = (OpenThreads::Thread::join() == 0); + } StopAll(); return ret; } @@ -296,7 +298,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; } @@ -419,7 +421,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; } @@ -427,7 +429,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; @@ -445,7 +447,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++) diff --git a/src/driver/vfd.cpp b/src/driver/vfd.cpp index b0dc73f50..b081d5b62 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; @@ -436,7 +436,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) { @@ -477,7 +477,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) { @@ -769,7 +769,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) @@ -787,13 +787,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 4a3ec64c0..84039020d 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 d0706fc1b..7095d2641 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]); } else if (msg == NeutrinoMessages::EVT_VOLCHANGED) { diff --git a/src/drivertool.c b/src/drivertool.c index 4e753e868..d756af2af 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..a082b401f 100644 --- a/src/eitd/eitd.h +++ b/src/eitd/eitd.h @@ -296,7 +296,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 0173462da..fccb01f9e 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 * @@ -62,7 +62,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; @@ -153,10 +153,15 @@ static CFreeSatThread threadFSEIT; CSdtThread threadSDT; #endif +#ifdef DEBUG_EVENT_LOCK +static int64_t lockstart = 0; +#endif + static int sectionsd_stop = 0; static bool slow_addevent = true; + inline void readLockServices(void) { pthread_rwlock_rdlock(&servicesLock); @@ -195,10 +200,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) { + int64_t tmp = time_monotonic_ms() - lockstart; + if (tmp > 50) + xprintf("locked ms %" PRId64 "\n", tmp); + lockstart = 0; + } +#endif pthread_rwlock_unlock(&eventsLock); } @@ -219,10 +235,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()) { @@ -238,7 +255,7 @@ static bool deleteEvent(const event_id_t uniqueKey) mySIeventsNVODorderUniqueKey.erase(uniqueKey); ret = true; } - unlockEvents(); + // unlockEvents(); return ret; } @@ -325,7 +342,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)) @@ -448,26 +465,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(); @@ -502,12 +522,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()); @@ -527,9 +543,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 @@ -542,8 +555,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 @@ -571,22 +582,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 = @@ -600,24 +607,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) @@ -627,7 +628,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(); @@ -646,10 +647,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); @@ -1377,7 +1377,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; @@ -1396,8 +1396,6 @@ 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 */ struct timeval oldd; tv.tv_sec = time_t(timediff / 1000000LL); @@ -1408,14 +1406,22 @@ 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"); + errno=0; + if (settimeofday(&tv, NULL) == 0) + return true; + + perror("[sectionsd] settimeofday"); + return errno==EPERM; } void CTimeThread::addFilters() @@ -1427,6 +1433,7 @@ 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()); const std::string tn = ("sd:" + name).c_str(); set_threadname(tn.c_str()); @@ -1471,7 +1478,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 + int64_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) < (int64_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) { @@ -1480,13 +1501,21 @@ void CTimeThread::run() dvb_time = st.getTime(); success = true; } - } + } else + retry = false; /* reset bogon detector after invalid read() */ } /* default sleep time */ 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; @@ -1688,10 +1717,21 @@ bool CCNThread::shouldSleep() if (eit_version != 0xff) return true; - if (++eit_retry > 1) { - xprintf("%s::%s eit_retry > 1 (%d) -> going to sleep\n", name.c_str(), __func__, eit_retry); + /* on first retry, restart the demux. I'm not sure if it is a driver bug + * or a bug in our logic, but without this, I'm sometimes missing CN events + * and / or the eit_version and thus the update filter will stop working */ + if (++eit_retry < 2) { + xprintf("%s::%s first retry (%d) -> restart demux\n", name.c_str(), __func__, eit_retry); + change(0); /* this also resets lastChanged */ + } + /* ugly, this has been checked before. But timeoutsDMX can be < 0 for multiple reasons, + * and only skipTime should send CNThread finally to sleep if eit_version is not found */ + time_t since = time_monotonic() - lastChanged; + if (since > skipTime) { + xprintf("%s::%s timed out after %lds -> going to sleep\n", name.c_str(), __func__, since); return true; } + /* retry */ sendToSleepNow = false; return false; } @@ -2074,10 +2114,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++; @@ -2306,7 +2350,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(); @@ -2803,7 +2852,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!!! */ @@ -2847,7 +2896,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 4332e462a..0eab74a32 100644 --- a/src/eitd/xmlutil.cpp +++ b/src/eitd/xmlutil.cpp @@ -619,7 +619,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 e77a66f98..dc5979882 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -101,7 +101,6 @@ libneutrino_gui_a_SOURCES = \ timeosd.cpp \ tmdb.cpp \ update.cpp \ - update_ext.cpp \ update_menue.cpp \ update_settings.cpp \ user_menue.cpp \ @@ -112,6 +111,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 6c5e3bf7c..33e7ca9e4 100644 --- a/src/gui/audio_setup.cpp +++ b/src/gui/audio_setup.cpp @@ -117,11 +117,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 } }; @@ -149,8 +155,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() //clock rec //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); //--------------------------------------------------------- @@ -224,6 +237,8 @@ int CAudioSetup::showAudioSetup() audioSettings->addItem(st); //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); @@ -231,6 +246,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 fa974d149..ff3b1238d 100644 --- a/src/gui/audioplayer.cpp +++ b/src/gui/audioplayer.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include diff --git a/src/gui/bookmarkmanager.cpp b/src/gui/bookmarkmanager.cpp index 25a4ab6d1..dcb686ca5 100644 --- a/src/gui/bookmarkmanager.cpp +++ b/src/gui/bookmarkmanager.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -252,8 +253,8 @@ const CBookmark * CBookmarkManager::getBookmark(CMenuTarget* parent) int res = -1; uint64_t timeoutEnd = CRCInput::calcTimeoutEnd(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 31da55950..fb62b4b07 100644 --- a/src/gui/bouquetlist.cpp +++ b/src/gui/bouquetlist.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/src/gui/buildinfo.cpp b/src/gui/buildinfo.cpp index fb9d7a3ac..e7e98785b 100644 --- a/src/gui/buildinfo.cpp +++ b/src/gui/buildinfo.cpp @@ -33,6 +33,8 @@ #include #include +#include + using namespace std; CBuildInfo::CBuildInfo(bool show) : CComponentsWindow(0, 0, CCW_PERCENT 85, CCW_PERCENT 85, LOCALE_BUILDINFO_MENU, NEUTRINO_ICON_INFO) diff --git a/src/gui/channellist.cpp b/src/gui/channellist.cpp index efe84b35b..e62a25e9e 100644 --- a/src/gui/channellist.cpp +++ b/src/gui/channellist.cpp @@ -496,7 +496,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) @@ -1421,8 +1425,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 1a2f7d1be..850e32b6a 100644 --- a/src/gui/components/cc_frm.cpp +++ b/src/gui/components/cc_frm.cpp @@ -248,7 +248,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; } @@ -575,7 +575,7 @@ void CComponentsForm::setSelectedItem(int item_id, const fb_pixel_t& sel_frame_c 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_header.cpp b/src/gui/components/cc_frm_header.cpp index 0fcb8aa68..ae347ef6f 100644 --- a/src/gui/components/cc_frm_header.cpp +++ b/src/gui/components/cc_frm_header.cpp @@ -422,7 +422,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 1a069a1dc..9ebb61744 100644 --- a/src/gui/components/cc_item_progressbar.cpp +++ b/src/gui/components/cc_item_progressbar.cpp @@ -248,6 +248,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) const diff --git a/src/gui/dboxinfo.cpp b/src/gui/dboxinfo.cpp index 66e52ecbe..62177d596 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 @@ -52,7 +46,6 @@ #include #include -#include #include #include @@ -338,6 +331,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()) { @@ -359,10 +353,11 @@ void CDBoxInfoWidget::paint() title += ": "; title + cpuinfo["machine"]; } - char ss[17]; - 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; width = std::max(width, g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->getRenderWidth(title, true) + 50); x = getScreenStartX(width); @@ -491,7 +486,6 @@ void CDBoxInfoWidget::paint() const int headSize = 5; int maxWidth[headSize]; memset(maxWidth, 0, headSize * sizeof(int)); - int ypos_mem_head = ypos; ypos += mheight; @@ -567,7 +561,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 f3a04a31a..1db13d966 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/epgview.cpp b/src/gui/epgview.cpp index 72dfb73fe..1fcccbae2 100644 --- a/src/gui/epgview.cpp +++ b/src/gui/epgview.cpp @@ -836,6 +836,15 @@ int CEpgData::show(const t_channel_id channel_id, uint64_t a_id, time_t* a_start if (mp_info && !extMovieInfo.empty()) processTextToArray(extMovieInfo); + /* 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); + } + COSDFader fader(g_settings.theme.menu_Content_alpha); fader.StartFadeIn(); @@ -1474,7 +1483,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 05519d4cb..04230bd79 100644 --- a/src/gui/filebrowser.cpp +++ b/src/gui/filebrowser.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,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 diff --git a/src/gui/hdd_menu.cpp b/src/gui/hdd_menu.cpp index 0bb0fd86b..2baa3a6d6 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 @@ -124,12 +127,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 std::string readlink(const char *path) +{ + char link[PATH_MAX + 1]; + if (realpath(path, link)) + return std::string(link); + return ""; +} + bool CHDDMenuHandler::is_mounted(const char *dev) { bool res = false; @@ -139,14 +150,25 @@ bool CHDDMenuHandler::is_mounted(const char *dev) else snprintf(devpath, sizeof(devpath), "/dev/%s", dev); - int devpathlen = strlen(devpath); char buffer[255]; + std::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 */ + std::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"); @@ -156,7 +178,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) { @@ -217,9 +242,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(std::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)) @@ -366,7 +418,7 @@ void CHDDMenuHandler::setRecordPath(std::string &dev) return; } /* don't annoy if the recordingdir is a symlink pointing to the 'right' location */ - std::string readl = backtick("readlink -f " + g_settings.network_nfs_recordingdir); + std::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", @@ -594,8 +646,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++) { @@ -604,6 +662,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); @@ -615,7 +674,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); @@ -640,9 +699,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); @@ -692,6 +758,7 @@ int CHDDMenuHandler::doMenu() show_menu = false; in_menu = true; + check_kernel_fs(); check_dev_tools(); _show_menu: @@ -739,9 +806,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); @@ -757,6 +826,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); @@ -776,6 +852,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), CMsgBox::mbrOk, CMsgBox::mbOk); @@ -788,6 +991,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); @@ -823,27 +1027,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); @@ -953,20 +1164,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"); @@ -990,7 +1200,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 6a56fd836..1734be4da 100644 --- a/src/gui/hdd_menu.h +++ b/src/gui/hdd_menu.h @@ -62,6 +62,7 @@ class CHDDMenuHandler : public CMenuTarget bool mounted; }; std::vector hdd_list; + std::set kernel_fs_list; struct cmp_hdd_by_name: public std::binary_function { bool operator() (const struct hdd_s &c1, const struct hdd_s &c2) @@ -82,6 +83,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 a42e3612d..04ab15332 100644 --- a/src/gui/infoviewer.cpp +++ b/src/gui/infoviewer.cpp @@ -101,6 +101,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(); InfoHeightY = 0; @@ -141,8 +144,6 @@ void CInfoViewer::Init() recordModeActive = false; is_visible = false; showButtonBar = false; - //gotTime = g_Sectionsd->getIsTimeSet (); - gotTime = timeset; zap_mode = IV_MODE_DEFAULT; newfreq = true; chanready = 1; @@ -535,7 +536,7 @@ void CInfoViewer::show_current_next(bool new_chan, int epgpos) if (!(info_CurrentNext.flags & (CSectionsdClient::epgflags::has_later | CSectionsdClient::epgflags::has_current | CSectionsdClient::epgflags::not_broadcast))) { neutrino_locale_t loc; - if (!gotTime) + if (!timeset) loc = LOCALE_INFOVIEWER_WAITTIME; else if (showButtonBar) loc = LOCALE_INFOVIEWER_EPGWAIT; @@ -571,8 +572,6 @@ void CInfoViewer::showMovieTitle(const int playState, const t_channel_id &Channe fileplay = true; zap_mode = _zap_mode; reset_allScala(); - if (!gotTime) - gotTime = timeset; if (g_settings.radiotext_enable && g_Radiotext) { g_Radiotext->RT_MsgShow = true; @@ -735,8 +734,6 @@ void CInfoViewer::showTitle(CZapitChannel * channel, const bool calledFromNumZap newfreq = true; reset_allScala(); - if (!gotTime) - gotTime = timeset; if(!is_visible && !calledFromNumZap) fader.StartFadeIn(); @@ -794,7 +791,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); @@ -1532,6 +1529,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; @@ -1567,7 +1566,7 @@ int CInfoViewer::handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data) infoViewerBB->showIcon_16_9 (); return messages_return::handled; } else if (msg == NeutrinoMessages::EVT_TIMESET) { - gotTime = true; + // gotTime = true; return messages_return::handled; } #if 0 @@ -1594,43 +1593,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 () @@ -1879,11 +1876,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); @@ -1894,7 +1895,7 @@ void CInfoViewer::show_Data (bool calledFromEvent) int seit = (abs(jetzt - info_CurrentNext.current_zeit.startzeit) + 30) / 60; int rest = (info_CurrentNext.current_zeit.dauer / 60) - seit; runningPercent = 0; - if (!gotTime) + if (!timeset) snprintf(runningRest, sizeof(runningRest), "%d %s", info_CurrentNext.current_zeit.dauer / 60, unit_short_minute); else if (jetzt < info_CurrentNext.current_zeit.startzeit) snprintf(runningRest, sizeof(runningRest), "%s %d %s", g_Locale->getText(LOCALE_WORD_IN), seit, unit_short_minute); @@ -1948,7 +1949,7 @@ void CInfoViewer::show_Data (bool calledFromEvent) (calledFromEvent && !(info_CurrentNext.flags & (CSectionsdClient::epgflags::has_next|CSectionsdClient::epgflags::has_current)))) { // no EPG available - display_Info(g_Locale->getText(gotTime ? LOCALE_INFOVIEWER_NOEPG : LOCALE_INFOVIEWER_WAITTIME), NULL); + display_Info(g_Locale->getText(timeset ? LOCALE_INFOVIEWER_NOEPG : LOCALE_INFOVIEWER_WAITTIME), NULL); /* send message. Parental pin check gets triggered on EPG events... */ /* clear old info in getEPG */ CSectionsdClient::CurrentNextInfo dummy; @@ -2009,7 +2010,7 @@ void CInfoViewer::show_Data (bool calledFromEvent) // no EPG available ChanInfoY += height; frameBuffer->paintBox (ChanInfoX + 10, ChanInfoY, BoxEndX, ChanInfoY + height, COL_INFOBAR_PLUS_0); - g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO]->RenderString (BoxStartX + ChanWidth + 20, ChanInfoY + height, BoxEndX - (BoxStartX + ChanWidth + 20), g_Locale->getText (gotTime ? LOCALE_INFOVIEWER_NOEPG : LOCALE_INFOVIEWER_WAITTIME), COL_INFOBAR_TEXT); + g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO]->RenderString (BoxStartX + ChanWidth + 20, ChanInfoY + height, BoxEndX - (BoxStartX + ChanWidth + 20), g_Locale->getText (timeset ? LOCALE_INFOVIEWER_NOEPG : LOCALE_INFOVIEWER_WAITTIME), COL_INFOBAR_TEXT); } else { // irgendein EPG gefunden int duration1Width = g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO]->getRenderWidth (runningRest); @@ -2231,7 +2232,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; @@ -2305,6 +2306,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) { @@ -2323,11 +2367,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 d5f605e7a..c8df0a74a 100644 --- a/src/gui/infoviewer.h +++ b/src/gui/infoviewer.h @@ -177,7 +177,8 @@ class CInfoViewer void showTitle(t_channel_id channel_id, const bool calledFromNumZap = false, int epgpos = 0, bool forcePaintButtonBar = false); 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 3dcc38ec3..8d7d9e3b2 100644 --- a/src/gui/infoviewer_bb.cpp +++ b/src/gui/infoviewer_bb.cpp @@ -593,8 +593,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: @@ -637,9 +637,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 d238cf05d..2ab5edd5d 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/miscsettings_menu.cpp b/src/gui/miscsettings_menu.cpp index 033854b37..a7601ab0b 100644 --- a/src/gui/miscsettings_menu.cpp +++ b/src/gui/miscsettings_menu.cpp @@ -244,7 +244,7 @@ int CMiscMenue::showMiscSettingsMenu() misc_menue.addItem(mf); //energy, shutdown - if(g_info.hw_caps->can_shutdown) + 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); @@ -269,10 +269,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); @@ -449,7 +457,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, @@ -665,14 +674,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/mb.cpp b/src/gui/moviebrowser/mb.cpp index 77b9f0976..880d2ca63 100644 --- a/src/gui/moviebrowser/mb.cpp +++ b/src/gui/moviebrowser/mb.cpp @@ -30,7 +30,7 @@ Author: Guenther@tuxbox.berlios.org based on code of Steffen Hehn 'McClean' - (C) 2009-2014 Stefan Seyfried + (C) 2009-2015 Stefan Seyfried (C) 2016 Sven Hoefer outsourced: @@ -1553,7 +1553,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/movieplayer.cpp b/src/gui/movieplayer.cpp index c48a1797f..28f249fee 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 @@ -81,6 +82,12 @@ #include #include +#ifndef HAVE_COOL_HARDWARE +#define LCD_MODE CVFD::MODE_MOVIE +#else +#define LCD_MODE CVFD::MODE_MENU_UTF8 +#endif + extern cVideo * videoDecoder; extern CRemoteControl *g_RemoteControl; /* neutrino.cpp */ @@ -164,22 +171,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()) @@ -245,6 +261,14 @@ void CMoviePlayerGui::cutNeutrino() g_Zapit->lockPlayBack(); +#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; @@ -273,6 +297,10 @@ void CMoviePlayerGui::restoreNeutrino() #endif playing = false; +#ifdef HAVE_AZBOX_HARDWARE + g_Zapit->setStandby(false); + CZapit::getInstance()->SetVolume(CZapit::getInstance()->GetVolume()); +#endif if (isUPNP) return; @@ -427,7 +455,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); } @@ -1315,6 +1343,7 @@ void CMoviePlayerGui::PlayFileLoop(void) bool first_start = true; bool update_lcd = true; int eof = 0; + int lastpos = 0; int eof2 = 0; int position_tmp = 0; bool at_eof = !(playstate >= CMoviePlayerGui::PLAY);; @@ -1350,7 +1379,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 */ if(file_prozent > 89 && (playstate == CMoviePlayerGui::PLAY) && (speed == 1)){ @@ -1842,9 +1874,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_CS_HD2 +#if ! defined(HAVE_SPARK_HARDWARE) && ! defined (BOXMODEL_CS_HD2) enabled = false; #endif break; @@ -2018,7 +2051,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/) } else if (msg == (neutrino_msg_t) g_settings.mpkey_stop) { // 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); @@ -2759,6 +2792,7 @@ void CMoviePlayerGui::makeScreenShot(bool autoshot, bool forcover) 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) @@ -2809,6 +2843,9 @@ void CMoviePlayerGui::makeScreenShot(bool autoshot, bool forcover) } } sc->Start(); +#else + (void)forcover; +#endif if (autoshot) autoshot_done = true; } diff --git a/src/gui/network_service.cpp b/src/gui/network_service.cpp index 627c65163..fb0b9d547 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 be5029a3b..14a8c433d 100644 --- a/src/gui/opkg_manager.cpp +++ b/src/gui/opkg_manager.cpp @@ -58,7 +58,7 @@ #include #include -#if 0 +#if 1 #define OPKG_CL "opkg" #else #define OPKG_CL "opkg-cl" @@ -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 /* script to call instead of "opkg upgrade" * opkg fails to gracefully self-upgrade, and additionally has some ordering issues diff --git a/src/gui/osd_setup.cpp b/src/gui/osd_setup.cpp index c1ed05dfc..b14dbbac7 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; @@ -629,12 +631,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); @@ -675,9 +679,12 @@ int COsdSetup::showOsdSetup() #endif //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); + } osd_menu->addItem(GenericMenuSeparatorLine); @@ -1089,6 +1096,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) @@ -1523,6 +1538,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] = @@ -1572,6 +1588,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 4ac06cf4c..ad96e009b 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 f43ac6e54..469fd1837 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 a7f19f1ef..e1e330b00 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 fec5f85b7..5627be7fa 100644 --- a/src/gui/plugins.cpp +++ b/src/gui/plugins.cpp @@ -4,6 +4,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' Homepage: http://dbox.cyberphoria.org/ + Copyright (C) 2011-2014 Stefan Seyfried + License: GPL This program is free software; you can redistribute it and/or @@ -118,7 +120,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 @@ -127,7 +129,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); @@ -364,7 +365,7 @@ void CPlugins::startLuaPlugin(int number) lua->runScript(script); delete lua; #endif -#if HAVE_SPARK_HARDWARE +#if 0 frameBuffer->ClearFB(); #endif videoDecoder->Pig(-1, -1, -1, -1); @@ -377,25 +378,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); @@ -437,7 +438,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); @@ -451,7 +452,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 de477c0be..51683cd09 100644 --- a/src/gui/plugins.h +++ b/src/gui/plugins.h @@ -34,14 +34,14 @@ class CFrameBuffer; class CPlugins { public: - // neutrino-internal plugin-type conversion typedef enum p_type { - P_TYPE_DISABLED = 0x1, - P_TYPE_GAME = 0x2, - P_TYPE_TOOL = 0x4, - P_TYPE_SCRIPT = 0x8, - P_TYPE_LUA = 0x10 + P_TYPE_DISABLED = 0x1, + P_TYPE_GAME = 0x2, + P_TYPE_TOOL = 0x4, + P_TYPE_SCRIPT = 0x8, + 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 1bd1334f4..a103ddefa 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 358cbd8bf..e679b4ba0 100644 --- a/src/gui/scan.cpp +++ b/src/gui/scan.cpp @@ -2,9 +2,7 @@ Neutrino-GUI - DBoxII-Project Copyright (C) 2001 Steffen Hehn 'McClean' - Homepage: http://dbox.cyberphoria.org/ - - Copyright (C) 2011-2012 Stefan Seyfried + Copyright (C) 2011-2013,2015,2017 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 @@ -107,7 +104,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; @@ -125,7 +123,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); @@ -142,6 +140,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); } @@ -171,6 +170,13 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) bool test = actionKey == "test"; bool manual = (actionKey == "manual") || test; bool fast = (actionKey == "fast"); +#if !ENABLE_FASTSCAN + if (fast) { + /* popup message? But this *should* be impossible to happen anyway */ + fprintf(stderr, "CScanTs::exec: fastscan disabled at build-time!\n"); + return menu_return::RETURN_REPAINT; + } +#endif if (CFrontend::isSat(delsys)) pname = scansettings.satName; @@ -187,10 +193,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; @@ -290,14 +299,17 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) tuned = -1; paint(test); + /* go */ if(test) { testFunc(); } else if(manual) success = g_Zapit->scan_TP(TP); else if(fast) { +#if ENABLE_FASTSCAN CServiceScan::getInstance()->QuietFastScan(false); success = CZapit::getInstance()->StartFastScan(scansettings.fast_type, scansettings.fast_op); +#endif } else success = g_Zapit->startScan(scan_flags); @@ -372,7 +384,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); @@ -403,7 +418,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; diff --git a/src/gui/scan.h b/src/gui/scan.h index bf2457c31..40d13dbd7 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 5d350c9fe..1cef717e7 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 @@ -160,7 +161,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 @@ -171,37 +176,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 } }; @@ -215,17 +234,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 } }; @@ -248,14 +275,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 } }; @@ -1280,12 +1313,14 @@ int CScanSetup::showScanMenuSatFind() void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t & satconfig) { temp_sat->addIntroItems(); + CMenuOptionNumberChooser *diseqc = NULL; - CMenuOptionNumberChooser *comm = NULL; + CMenuOptionNumberChooser *comm = NULL; CMenuOptionNumberChooser *uncomm = NULL; CMenuOptionNumberChooser *unilnb = NULL; - CMenuOptionNumberChooser *motor = NULL; - CMenuOptionChooser *usals = NULL; + CMenuOptionNumberChooser *motor = NULL; + CMenuOptionChooser *usals = NULL; + CMenuForwarder *mf; bool unicable = (dmode == DISEQC_UNICABLE ? true : dmode == DISEQC_UNICABLE2); if (!unicable) { @@ -1297,7 +1332,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) @@ -1319,7 +1354,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..f281de2f3 100644 --- a/src/gui/scan_setup.h +++ b/src/gui/scan_setup.h @@ -42,8 +42,6 @@ #define scansettings CNeutrinoApp::getInstance()->getScanSettings() -#define ENABLE_FASTSCAN //don't define this to remove fast scan menu - class CScanSetup : public CMenuTarget, public CChangeObserver { protected: diff --git a/src/gui/settings_manager.cpp b/src/gui/settings_manager.cpp index ddd0d2c3d..156ec6489 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 adc2a6637..f90076a48 100644 --- a/src/gui/start_wizard.cpp +++ b/src/gui/start_wizard.cpp @@ -90,11 +90,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), CMsgBox::mbrYes, CMsgBox::mbYes | CMsgBox::mbrCancel) == CMsgBox::mbrYes) +#endif { int advanced = 1; #ifdef ENABLE_FASTSCAN diff --git a/src/gui/streaminfo2.cpp b/src/gui/streaminfo2.cpp index 31a7ef272..cadd41358 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 @@ -140,42 +144,19 @@ int CStreamInfo2::doSignalStrengthLoop () neutrino_msg_t msg; neutrino_msg_t postmsg = 0; 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 sw = g_Font[font_info]->getRenderWidth("99999"); maxb = minb = lastb = tmp_rate = 0; + std::string br_str = std::string(g_Locale->getText(LOCALE_STREAMINFO_BITRATE)) + ":"; + std::string avg_str = "(" + std::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; - - uint64_t timeoutEnd = CRCInput::calcTimeoutEnd_MS (100); - g_RCInput->getMsgAbsoluteTimeout (&msg, &data, &timeoutEnd); - - if ((msg == NeutrinoMessages::EVT_TIMER) && (data == fader.GetFadeTimer())) - { - if (fader.FadeDone()) - { - break; - } - continue; - } - if (fadeout && msg == CRCInput::RC_timeout) - { - if (fader.StartFadeOut()) - { - msg = 0; - continue; - } - else - { - break; - } - } - if (!mp) { signal.sig = frontend->getSignalStrength() & 0xFFFF; signal.snr = frontend->getSignalNoiseRatio() & 0xFFFF; @@ -187,17 +168,7 @@ int CStreamInfo2::doSignalStrengthLoop () if (cnt < 12) cnt++; - int dheight = g_Font[font_info]->getHeight (); - int dx1 = x + 10; - if(!mp && delay_counter > delay + 1){ - CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); - if(channel) - pmt_version = channel->getPmtVersion(); - if(pmt_version != current_pmt_version){ - delay_counter = 0; - } - } if (ret && (lastb != bit_s)) { lastb = bit_s; @@ -207,26 +178,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) @@ -253,6 +223,31 @@ 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); + + if ((msg == NeutrinoMessages::EVT_TIMER) && (data == fader.GetFadeTimer())) + { + if (fader.FadeDone()) + { + break; + } + continue; + } + if (fadeout && msg == CRCInput::RC_timeout) + { + if (fader.StartFadeOut()) + { + msg = 0; + continue; + } + else + { + break; + } + } + // switch paint mode if (msg == CRCInput::RC_red || msg == CRCInput::RC_blue || msg == CRCInput::RC_green || msg == CRCInput::RC_yellow) { hide (); @@ -499,7 +494,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. @@ -659,7 +654,7 @@ void CStreamInfo2::paint_techinfo(int xpos, int ypos) if (!g_RemoteControl->current_PIDs.APIDs.empty()) desc = g_RemoteControl->current_PIDs.APIDs[g_RemoteControl->current_PIDs.PIDs.selected_apid].desc; - if (type == AUDIO_FMT_MPEG) + if (type == AUDIO_FMT_MPEG || type == AUDIO_FMT_MP3) { const char *mpegmodes[] = { @@ -927,7 +922,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){ @@ -1036,8 +1030,7 @@ int CStreamInfo2::update_rate () int ret = 0; int timeout = 100; - int b_len; - + int b_len = 0; if(!dmx && !mp) return 0; @@ -1045,7 +1038,15 @@ int CStreamInfo2::update_rate () usleep(timeout * 1000); b_len = mp->GetReadCount(); } else { - b_len = dmx->Read(dmxbuf, TS_BUF_SIZE, timeout); + int64_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 %" PRId64 "\n", b_len, time_monotonic_ms() - start); } //printf("ts: read %d\n", b_len); @@ -1075,8 +1076,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 () @@ -1092,9 +1093,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 d777e095c..dfb199488 100644 --- a/src/gui/test_menu.cpp +++ b/src/gui/test_menu.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,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*/] = @@ -193,6 +196,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) return res; } +#if HAVE_COOL_HARDWARE else if (actionKey == "card0") { char str[255]; @@ -239,6 +243,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) return res; } +#endif else if (actionKey == "hdd") { char buffer[255]; @@ -1161,8 +1166,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/themes.cpp b/src/gui/themes.cpp index 70b202c6e..7ad470d1b 100644 --- a/src/gui/themes.cpp +++ b/src/gui/themes.cpp @@ -347,7 +347,7 @@ void CThemes::getTheme(CConfigFile &configfile) t.menu_Head_Text_green = configfile.getInt32( "menu_Head_Text_green", 0x46 ); t.menu_Head_Text_blue = configfile.getInt32( "menu_Head_Text_blue", 0x00 ); - t.menu_Head_gradient = configfile.getInt32( "menu_Head_gradient", CC_COLGRAD_LIGHT_2_DARK); + t.menu_Head_gradient = configfile.getInt32("menu_Head_gradient", CC_COLGRAD_OFF); /* no bling */ t.menu_Head_gradient_direction = configfile.getInt32( "menu_Head_gradient_direction", CFrameBuffer::gradientVertical); t.menu_Separator_gradient_enable = configfile.getInt32( "menu_Separator_gradient_enable", 0); @@ -420,7 +420,7 @@ void CThemes::getTheme(CConfigFile &configfile) t.colored_events_blue = configfile.getInt32( "colored_events_blue", 0 ); t.colored_events_channellist = configfile.getInt32( "colored_events_channellist", 0 ); - t.colored_events_infobar = configfile.getInt32( "colored_events_infobar", 2 ); + t.colored_events_infobar = configfile.getInt32("colored_events_infobar", 0); /* no bling bling */ t.clock_Digit_alpha = configfile.getInt32( "clock_Digit_alpha", t.menu_Content_Text_alpha ); t.clock_Digit_red = configfile.getInt32( "clock_Digit_red", t.menu_Content_Text_red ); t.clock_Digit_green = configfile.getInt32( "clock_Digit_green", t.menu_Content_Text_green ); diff --git a/src/gui/timerlist.cpp b/src/gui/timerlist.cpp index 89b5d735b..cb4350049 100644 --- a/src/gui/timerlist.cpp +++ b/src/gui/timerlist.cpp @@ -660,7 +660,8 @@ struct button_label TimerListButtons[] = { NEUTRINO_ICON_BUTTON_INFO_SMALL, LOCALE_TIMERLIST_INFO }, { NEUTRINO_ICON_BUTTON_PLAY , LOCALE_TIMERLIST_SEND_TIMER } }; -size_t TimerListButtonsCount = sizeof(TimerListButtons)/sizeof(TimerListButtons[0]); +// int to match the type in paintButtons +int TimerListButtonsCount = sizeof(TimerListButtons)/sizeof(TimerListButtons[0]); #define RemoteBoxFooterButtonCount 3 static const struct button_label RemoteBoxFooterButtons[RemoteBoxFooterButtonCount] = { diff --git a/src/gui/update.cpp b/src/gui/update.cpp index 40e1a2312..980f70ab2 100644 --- a/src/gui/update.cpp +++ b/src/gui/update.cpp @@ -552,6 +552,7 @@ int CFlashUpdate::exec(CMenuTarget* parent, const std::string &actionKey) #endif if(fileType <= '2') { //flash it... +#if ENABLE_EXTUPDATE #ifndef BOXMODEL_CS_HD2 if (g_settings.apply_settings) { if (ShowMsg(LOCALE_MESSAGEBOX_INFO, LOCALE_FLASHUPDATE_APPLY_SETTINGS, CMsgBox::mbrYes, CMsgBox::mbYes | CMsgBox::mbNo, NEUTRINO_ICON_UPDATE) == CMsgBox::mbrYes) @@ -561,6 +562,7 @@ int CFlashUpdate::exec(CMenuTarget* parent, const std::string &actionKey) } } #endif +#endif #ifdef DRYRUN if(1) { @@ -765,6 +767,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_CS_HD2 int eSize = CMTDInfo::getInstance()->getMTDEraseSize(CMTDInfo::getInstance()->findMTDsystem()); if (preadmtd == 0) { @@ -781,6 +785,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_CS_HD2 @@ -920,9 +925,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_CS_HD2 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; @@ -992,11 +999,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.h b/src/gui/update.h index 1a8107c61..dc8d3584b 100644 --- a/src/gui/update.h +++ b/src/gui/update.h @@ -38,7 +38,6 @@ #include -#include #ifdef BOXMODEL_CS_HD2 #include #endif 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 10c222dd3..a4ba49bd5 100644 --- a/src/gui/update_settings.cpp +++ b/src/gui/update_settings.cpp @@ -60,6 +60,7 @@ CUpdateSettings::~CUpdateSettings() #endif } +#if ENABLE_EXTUPDATE #define SOFTUPDATE_NAME_MODE1_OPTION_COUNT 3 const CMenuOptionChooser::keyval SOFTUPDATE_NAME_MODE1_OPTIONS[SOFTUPDATE_NAME_MODE1_OPTION_COUNT] = { @@ -74,6 +75,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) { @@ -121,6 +123,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); @@ -132,6 +135,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); @@ -144,11 +148,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_CS_HD2 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 fa6adfc6f..8646ac926 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 diff --git a/src/gui/user_menue_setup.cpp b/src/gui/user_menue_setup.cpp index 900ad3c75..01e87ae32 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 f4c600a32..782f054eb 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 4280f1cb4..0c7ffdb22 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 @@ -48,6 +50,7 @@ #include #include +#include #include @@ -56,7 +59,9 @@ #include #include +#ifdef BOXMODEL_CS_HD2 #include +#endif extern cVideo *videoDecoder; #ifdef ENABLE_PIP @@ -81,11 +86,12 @@ CVideoSettings::CVideoSettings(int wizard_mode) prev_video_mode = g_settings.video_Mode; setupVideoSystem(false); + Init43ModeOptions(); } CVideoSettings::~CVideoSettings() { - + videomenu_43mode_options.clear(); } int CVideoSettings::exec(CMenuTarget* parent, const std::string &/*actionKey*/) @@ -106,15 +112,22 @@ int CVideoSettings::exec(CMenuTarget* parent, const std::string &/*actionKey*/) const CMenuOptionChooser::keyval VIDEOMENU_43MODE_OPTIONS[] = { { DISPLAY_AR_MODE_PANSCAN, LOCALE_VIDEOMENU_PANSCAN }, -#ifndef BOXMODEL_CS_HD2 { DISPLAY_AR_MODE_PANSCAN2, LOCALE_VIDEOMENU_PANSCAN2 }, -#endif { DISPLAY_AR_MODE_LETTERBOX, LOCALE_VIDEOMENU_LETTERBOX }, { DISPLAY_AR_MODE_NONE, LOCALE_VIDEOMENU_FULLSCREEN } //{ 2, LOCALE_VIDEOMENU_AUTO } // whatever is this auto mode, it seems its totally broken }; #define VIDEOMENU_43MODE_OPTION_COUNT (sizeof(VIDEOMENU_43MODE_OPTIONS)/sizeof(CMenuOptionChooser::keyval)) +#ifndef BOXMODEL_CS_HD2 +#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] = @@ -190,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] = { @@ -200,6 +235,8 @@ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_O { VIDEO_STD_1080I50, NONEXISTANT_LOCALE, "1080i 50Hz" }, #ifdef BOXMODEL_CS_HD2 { 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" }, @@ -208,12 +245,50 @@ 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_CS_HD2 + /* 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 #define VIDEOMENU_VIDEOFORMAT_OPTION_COUNT 3//2 const CMenuOptionChooser::keyval VIDEOMENU_VIDEOFORMAT_OPTIONS[VIDEOMENU_VIDEOFORMAT_OPTION_COUNT] = @@ -238,6 +313,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; @@ -262,52 +347,69 @@ int CVideoSettings::showVideoSetup() vs_chinch_ch->setHint("", LOCALE_MENU_HINT_VIDEO_CINCH_MODE); #endif } +#ifndef BOXMODEL_CS_HD2 + 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); + CMenuOptionChooser * vs_43mode_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_43MODE, &g_settings.video_43mode, videomenu_43mode_options, true, this); vs_43mode_ch->setHint("", LOCALE_MENU_HINT_VIDEO_43MODE); //display format - CMenuOptionChooser * vs_dispformat_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_VIDEOFORMAT, &g_settings.video_Format, VIDEOMENU_VIDEOFORMAT_OPTIONS, VIDEOMENU_VIDEOFORMAT_OPTION_COUNT, true, this); + CMenuOptionChooser * vs_dispformat_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_VIDEOFORMAT, &g_settings.video_Format, VIDEOMENU_VIDEOFORMAT_OPTIONS, g_info.hw_caps->can_ar_14_9 ? VIDEOMENU_VIDEOFORMAT_OPTION_COUNT : VIDEOMENU_VIDEOFORMAT_OPTION_COUNT -1, true, this); /* works only if 14:9 is last! */ 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_CS_HD2 CMenuForwarder * vs_automodes_fw = NULL; CMenuWidget automodes(LOCALE_MAINSETTINGS_VIDEO, NEUTRINO_ICON_SETTINGS); #endif CAutoModeNotifier anotify; + CMenuForwarder *vs_videomodes_fw = NULL; //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_CS_HD2 - 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) @@ -316,15 +418,18 @@ 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 - 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_CS_HD2 - videosetup->addItem(vs_automodes_fw); //video auto modes submenue + videosetup->addItem(vs_automodes_fw); //video auto modes submenue #endif #ifdef BOXMODEL_CS_HD2 @@ -503,20 +608,20 @@ void CVideoSettings::next43Mode(void) { printf("[neutrino VideoSettings] %s setting 43Mode...\n", __FUNCTION__); neutrino_locale_t text; - int curmode = 0; + unsigned int curmode = 0; - for (int i = 0; i < (int) VIDEOMENU_43MODE_OPTION_COUNT; i++) { - if (VIDEOMENU_43MODE_OPTIONS[i].key == g_settings.video_43mode) { + for (unsigned int i = 0; i < videomenu_43mode_options.size(); i++) { + if (videomenu_43mode_options[i].key == g_settings.video_43mode) { curmode = i; break; } } curmode++; - if (curmode >= (int) VIDEOMENU_43MODE_OPTION_COUNT) + if (curmode >= videomenu_43mode_options.size()) curmode = 0; - text = VIDEOMENU_43MODE_OPTIONS[curmode].value; - g_settings.video_43mode = VIDEOMENU_43MODE_OPTIONS[curmode].key; + text = videomenu_43mode_options[curmode].value; + g_settings.video_43mode = videomenu_43mode_options[curmode].key; videoDecoder->setAspectRatio(-1, g_settings.video_43mode); #ifdef ENABLE_PIP pipDecoder->setAspectRatio(-1, g_settings.video_43mode); @@ -539,7 +644,8 @@ void CVideoSettings::SwitchFormat() curmode++; if (curmode >= VIDEOMENU_VIDEOFORMAT_OPTION_COUNT) curmode = 0; - + if (VIDEOMENU_VIDEOFORMAT_OPTIONS[curmode].key == DISPLAY_AR_14_9 && g_info.hw_caps->can_ar_14_9 == 0) + curmode = 0; text = VIDEOMENU_VIDEOFORMAT_OPTIONS[curmode].value; g_settings.video_Format = VIDEOMENU_VIDEOFORMAT_OPTIONS[curmode].key; @@ -584,6 +690,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++; @@ -609,3 +717,17 @@ void CVideoSettings::nextMode(void) CVFD::getInstance()->showServicename(g_RemoteControl->getCurrentChannelName(), g_RemoteControl->getCurrentChannelNumber()); //ShowHint(LOCALE_VIDEOMENU_VIDEOMODE, text, 450, 2); } + +void CVideoSettings::Init43ModeOptions() +{ + videomenu_43mode_options.clear(); + for (unsigned int i = 0; i < VIDEOMENU_43MODE_OPTION_COUNT; i++) + { + if (VIDEOMENU_43MODE_OPTIONS[i].key == DISPLAY_AR_MODE_PANSCAN2 && + g_info.hw_caps->can_ps_14_9 == 0) + continue; + CMenuOptionChooser::keyval_ext o; + o = VIDEOMENU_43MODE_OPTIONS[i]; + videomenu_43mode_options.push_back(o); + } +} diff --git a/src/gui/videosettings.h b/src/gui/videosettings.h index 9c0e7e628..3556f0d34 100644 --- a/src/gui/videosettings.h +++ b/src/gui/videosettings.h @@ -47,6 +47,8 @@ class CVideoSettings : public CMenuWidget, CChangeObserver int width, selected; int showVideoSetup(); + std::vector videomenu_43mode_options; + void Init43ModeOptions(); public: CVideoSettings(int wizard_mode = SNeutrinoSettings::WIZARD_OFF); diff --git a/src/gui/widget/buttons.cpp b/src/gui/widget/buttons.cpp index 6ee70f32a..f9f4680cb 100644 --- a/src/gui/widget/buttons.cpp +++ b/src/gui/widget/buttons.cpp @@ -29,7 +29,7 @@ #include #include -//#include +#include #include @@ -132,7 +132,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) @@ -348,7 +348,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/menue.cpp b/src/gui/widget/menue.cpp index 12f2bd6e1..fc2487df9 100644 --- a/src/gui/widget/menue.cpp +++ b/src/gui/widget/menue.cpp @@ -811,7 +811,6 @@ int CMenuWidget::exec(CMenuTarget* parent, const std::string &) paint(); break; } - frameBuffer->blit(); continue; } for (unsigned int i= 0; i< items.size(); i++) { @@ -2378,6 +2377,7 @@ bool CZapProtection::check() hint = NONEXISTANT_LOCALE; int res; std::string cPIN; + char systemstr[128]; do { cPIN = ""; @@ -2386,10 +2386,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/progresswindow.cpp b/src/gui/widget/progresswindow.cpp index 27b4418c8..50626c232 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-2017 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 e52e71d6e..b4b8aac40 100644 --- a/src/lcddisplay/fontrenderer.cpp +++ b/src/lcddisplay/fontrenderer.cpp @@ -321,6 +321,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 09df7153f..fc23a65dd 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -3,9 +3,8 @@ Copyright (C) 2001 Steffen Hehn 'McClean' and some other guys - Homepage: http://dbox.cyberphoria.org/ - Copyright (C) 2006-2016 Stefan Seyfried + Copyright (C) 2006-2017 Stefan Seyfried Copyright (C) 2011 CoolStream International Ltd @@ -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 @@ -227,6 +226,11 @@ CNeutrinoApp::CNeutrinoApp() : configfile('\t') { standby_pressed_at.tv_sec = 0; +#if HAVE_TRIPLEDRAGON || USE_STB_HAL + /* this needs to happen before the framebuffer is set up */ + init_td_api(); + // shutdown_td_api(); +#endif osd_resolution_tmp = -1; frameBufferInitialized = false; @@ -291,7 +295,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 }; @@ -309,6 +313,22 @@ 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 40 //5 +#define DEFAULT_Y_START_HD 25 //5 +#define DEFAULT_X_END_HD 1235 //1275 +#define DEFAULT_Y_END_HD 690 //715 std::string ttx_font_file = ""; @@ -347,7 +367,14 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.softupdate_autocheck = configfile.getBool("softupdate_autocheck" , false); // 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 @@ -370,10 +397,10 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.audio_volume_percent_ac3 = configfile.getInt32("audio_volume_percent_ac3", 100); g_settings.audio_volume_percent_pcm = configfile.getInt32("audio_volume_percent_pcm", 100); - g_settings.channel_mode = configfile.getInt32("channel_mode", LIST_MODE_PROV); - g_settings.channel_mode_radio = configfile.getInt32("channel_mode_radio", LIST_MODE_PROV); - g_settings.channel_mode_initial = configfile.getInt32("channel_mode_initial", -1); - g_settings.channel_mode_initial_radio = configfile.getInt32("channel_mode_initial_radio", -1); + g_settings.channel_mode = configfile.getInt32("channel_mode", LIST_MODE_FAV); + g_settings.channel_mode_radio = configfile.getInt32("channel_mode_radio", LIST_MODE_FAV); + g_settings.channel_mode_initial = configfile.getInt32("channel_mode_initial", LIST_MODE_FAV); + g_settings.channel_mode_initial_radio = configfile.getInt32("channel_mode_initial_radio", LIST_MODE_FAV); if (g_settings.channel_mode_initial > -1) g_settings.channel_mode = g_settings.channel_mode_initial; if (g_settings.channel_mode_initial_radio > -1) @@ -397,8 +424,10 @@ 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 +#endif for(int i = 0; i < VIDEOMENU_VIDEOMODE_OPTION_COUNT; i++) { sprintf(cfg_key, "enabled_auto_mode_%d", i); @@ -420,7 +449,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.standby_cpufreq = 50; #endif - g_settings.make_hd_list = configfile.getInt32("make_hd_list", 1); + g_settings.make_hd_list = configfile.getInt32("make_hd_list", 0); g_settings.make_webtv_list = configfile.getInt32("make_webtv_list", 1); g_settings.make_new_list = configfile.getInt32("make_new_list", 1); g_settings.make_removed_list = configfile.getInt32("make_removed_list", 1); @@ -487,16 +516,16 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.infobar_sat_display = configfile.getBool("infobar_sat_display" , true ); g_settings.infobar_show_channeldesc = configfile.getBool("infobar_show_channeldesc" , false ); - g_settings.infobar_subchan_disp_pos = configfile.getInt32("infobar_subchan_disp_pos" , 0 ); + g_settings.infobar_subchan_disp_pos = configfile.getInt32("infobar_subchan_disp_pos", 4); // subchan display in infobar g_settings.infobar_buttons_usertitle = configfile.getBool("infobar_buttons_usertitle", false ); g_settings.infobar_show = configfile.getInt32("infobar_show", configfile.getInt32("infobar_cn", 1)); g_settings.infobar_show_channellogo = configfile.getInt32("infobar_show_channellogo" , 3 ); g_settings.infobar_progressbar = configfile.getInt32("infobar_progressbar" , 1 ); // below channel name - g_settings.infobar_casystem_display = configfile.getInt32("infobar_casystem_display", 1 );//discreet ca mode default + g_settings.infobar_casystem_display = configfile.getInt32("infobar_casystem_display", 2); //mini ca mode default g_settings.infobar_casystem_dotmatrix = configfile.getInt32("infobar_casystem_dotmatrix", 0 ); g_settings.infobar_casystem_frame = configfile.getInt32("infobar_casystem_frame", 1 ); g_settings.scrambled_message = configfile.getBool("scrambled_message", true ); - g_settings.volume_pos = configfile.getInt32("volume_pos", CVolumeBar::VOLUMEBAR_POS_TOP_RIGHT ); + g_settings.volume_pos = configfile.getInt32("volume_pos", CVolumeBar::VOLUMEBAR_POS_BOTTOM_CENTER); g_settings.volume_digits = configfile.getBool("volume_digits", true); g_settings.volume_size = configfile.getInt32("volume_size", 26 ); g_settings.menu_pos = configfile.getInt32("menu_pos", CMenuWidget::MENU_POS_CENTER); @@ -522,7 +551,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.pref_subs[i] = configfile.getString(cfg_key, "none"); } g_settings.subs_charset = configfile.getString("subs_charset", "CP1252"); - g_settings.zap_cycle = configfile.getInt32( "zap_cycle", 0 ); + g_settings.zap_cycle = configfile.getInt32("zap_cycle", 1); /* stay in bouquet by default */ //screen saver g_settings.screensaver_delay = configfile.getInt32("screensaver_delay", 1); @@ -705,12 +734,12 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.mode_clock = configfile.getInt32( "mode_clock", 0); g_settings.zapto_pre_time = configfile.getInt32( "zapto_pre_time", 0); g_settings.spectrum = configfile.getBool("spectrum" , false); - g_settings.channellist_additional = configfile.getInt32("channellist_additional", 2); //default minitv + g_settings.channellist_additional = configfile.getInt32("channellist_additional", 1); //default no minitv g_settings.eventlist_additional = configfile.getInt32("eventlist_additional", 0); g_settings.eventlist_epgplus = configfile.getInt32("eventlist_epgplus", 1); g_settings.channellist_epgtext_align_right = configfile.getBool("channellist_epgtext_align_right" , false); - g_settings.channellist_foot = configfile.getInt32("channellist_foot" , 1);//default next Event - g_settings.channellist_new_zap_mode = configfile.getInt32("channellist_new_zap_mode", 1); + g_settings.channellist_foot = configfile.getInt32("channellist_foot", 0); //default transponder data + g_settings.channellist_new_zap_mode = configfile.getInt32("channellist_new_zap_mode", 0); g_settings.channellist_sort_mode = configfile.getInt32("channellist_sort_mode", 0);//sort mode: alpha, freq, sat g_settings.channellist_numeric_adjust = configfile.getInt32("channellist_numeric_adjust", 0); g_settings.channellist_show_channellogo = configfile.getInt32("channellist_show_channellogo", 1); @@ -745,7 +774,7 @@ int CNeutrinoApp::loadSetup(const char * fname) if (g_settings.screen_EndY >= g_settings.screen_height) g_settings.screen_EndY = g_settings.screen_height - 1; - g_settings.bigFonts = configfile.getInt32("bigFonts", 0); + g_settings.bigFonts = configfile.getInt32("bigFonts", 1); g_settings.window_size = configfile.getInt32("window_size", 100); g_settings.window_width = configfile.getInt32("window_width", g_settings.window_size); g_settings.window_height = configfile.getInt32("window_height", g_settings.window_size); @@ -757,8 +786,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); @@ -1016,12 +1050,12 @@ void CNeutrinoApp::upgradeSetup(const char * fname) { //convert and remove obsolete progressbar_* keys - g_settings.theme.progressbar_design = configfile.getInt32("progressbar_design", CProgressBar::PB_COLOR); + g_settings.theme.progressbar_design = configfile.getInt32("progressbar_design", CProgressBar::PB_MONO); bool pb_color = configfile.getBool("progressbar_color", true ); if (!pb_color) g_settings.theme.progressbar_design = CProgressBar::PB_MONO; g_settings.theme.progressbar_design_channellist = configfile.getInt32("channellist_progressbar_design", g_settings.theme.progressbar_design); - g_settings.theme.progressbar_gradient = configfile.getBool("progressbar_gradient", true ); + g_settings.theme.progressbar_gradient = configfile.getBool("progressbar_gradient", false); g_settings.theme.progressbar_timescale_red = configfile.getInt32("progressbar_timescale_red", 0); g_settings.theme.progressbar_timescale_green = configfile.getInt32("progressbar_timescale_green", 100); g_settings.theme.progressbar_timescale_yellow = configfile.getInt32("progressbar_timescale_yellow", 70); @@ -1801,7 +1835,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(); @@ -2083,6 +2117,14 @@ void CNeutrinoApp::InitZapitClient() void CNeutrinoApp::InitSectiondClient() { +#if 0 + /* TODO: check if still needed */ + /* wait for sectionsd to be able to process our registration */ + int64_t t = time_monotonic_ms(); + while (! sectionsd_isReady()) + sleep(0); + dprintf(DEBUG_NORMAL, "had to wait %" PRId64 " ms for sectionsd to start up\n", time_monotonic_ms() - t); +#endif g_Sectionsd = new CSectionsdClient; struct timespec t; if (clock_gettime(CLOCK_MONOTONIC, &t)) { @@ -2098,7 +2140,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 @@ -2120,13 +2162,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) @@ -2250,10 +2297,9 @@ TIMER_START(); } //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)){ @@ -2265,6 +2311,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(); @@ -2328,6 +2378,11 @@ TIMER_START(); InitSectiondClient(); + /* wait until timerd is ready... */ + int64_t timerd_wait = time_monotonic_ms(); + while (timerd_signal >= 0) + usleep(100); + dprintf(DEBUG_NORMAL, "had to wait %" PRId64 " ms for timerd start...\n", time_monotonic_ms() - timerd_wait); InitTimerdClient(); // volume @@ -2363,14 +2418,14 @@ TIMER_START(); hdd->exec(NULL, ""); delete hdd; + hintBox->hide(); // InitZapper also displays a hintbox + delete hintBox; + cCA::GetInstance()->Ready(true); //InitZapper(); SHTDCNT::getInstance()->init(); - hintBox->hide(); - delete hintBox; - cSysLoad::getInstance(); cHddStat::getInstance(); @@ -2605,6 +2660,7 @@ void CNeutrinoApp::RealRun() numericZap( msg ); InfoClock->enableInfoClock(true); } +#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); @@ -2612,6 +2668,7 @@ void CNeutrinoApp::RealRun() sc->Start(); } } +#endif else if( msg == (neutrino_msg_t) g_settings.key_lastchannel ) { // Quick Zap numericZap( msg ); @@ -2758,6 +2815,8 @@ void CNeutrinoApp::RealRun() CTimerList Timerlist; Timerlist.exec(NULL, ""); } + else if (msg == CRCInput::RC_aux) + scartMode(true); else { if (msg == CRCInput::RC_home) CVFD::getInstance()->setMode(CVFD::MODE_TVRADIO); @@ -2768,7 +2827,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 ); @@ -2973,7 +3032,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 { @@ -3048,7 +3107,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); - res = res | channelList->handleMsg(msg, data); + 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); @@ -3220,6 +3281,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); @@ -3227,6 +3289,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) { @@ -3649,7 +3712,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 %lX data %lX\n", msg, data); + INFO("###################################### DELETED msg %lx data %lx\n", msg, data); delete [] (unsigned char*) data; return messages_return::handled; } @@ -3661,6 +3724,7 @@ extern bool timer_is_rec;//timermanager.cpp void CNeutrinoApp::ExitRun(int can_shutdown) { + /* can_shutdown is actually our exit code */ printf("[neutrino] %s can_shutdown: %d\n", __func__, can_shutdown); bool do_shutdown = true; @@ -3704,16 +3768,20 @@ void CNeutrinoApp::ExitRun(int can_shutdown) g_settings.shutdown_timer_record_type = timer_is_rec; saveSetup(NEUTRINO_SETTINGS_FILE); +#if 0 if (can_shutdown) { +#endif puts("[neutrino.cpp] executing " NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT "."); if (my_system(NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT) != 0) perror(NEUTRINO_ENTER_DEEPSTANDBY_SCRIPT " failed"); 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); struct tm *tmtime = localtime(&mtime); @@ -3794,6 +3862,67 @@ void CNeutrinoApp::ExitRun(int can_shutdown) //_exit(0); exit(0); } +#endif + int leds = 0; + int bright = 0; +#if HAVE_COOL_HARDWARE + if (can_shutdown) { + 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; + //fan speed + if (g_info.hw_caps->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", can_shutdown); + Cleanup(); +#ifdef __sh__ + /* the sh4 gcc seems to dislike someting about openthreads... */ + _exit(can_shutdown); +#else + exit(can_shutdown); +#endif } void CNeutrinoApp::saveEpg(bool cvfd_mode) @@ -3895,13 +4024,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 ) { @@ -3927,6 +4065,7 @@ void CNeutrinoApp::standbyMode( bool bOnOff, bool fromDeepStandby ) lockStandbyCall = true; if( bOnOff ) { + CVFD::getInstance()->ShowText("standby... "); if( mode == mode_scart ) { //g_Controld->setScartMode( 0 ); } @@ -4004,9 +4143,13 @@ 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); if(init_cec_setting){ @@ -4057,6 +4200,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); @@ -4265,11 +4414,12 @@ int CNeutrinoApp::exec(CMenuTarget* parent, const std::string & actionKey) delete hint; 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); @@ -4418,9 +4568,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; } @@ -4515,7 +4670,7 @@ void CNeutrinoApp::loadKeys(const char * fname) /* options */ g_settings.menu_left_exit = tconfig.getInt32( "menu_left_exit", 0 ); - 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); @@ -4619,7 +4774,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(); @@ -4637,7 +4792,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); @@ -4785,8 +4940,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; @@ -4829,12 +4987,13 @@ void CNeutrinoApp::Cleanup() printf("cleanup 5\n");fflush(stdout); delete CEitManager::getInstance(); printf("cleanup 6\n");fflush(stdout); - delete CVFD::getInstance(); + //delete CVFD::getInstance(); comp_malloc_stats(NULL); #endif } +#if ENABLE_FASTSCAN void CNeutrinoApp::CheckFastScan(bool standby, bool reload) { if (scansettings.fst_update) { @@ -4866,6 +5025,11 @@ void CNeutrinoApp::CheckFastScan(bool standby, bool reload) } } } +#else +void CNeutrinoApp::CheckFastScan(bool, bool) +{ +} +#endif bool CNeutrinoApp::adjustToChannelID(const t_channel_id channel_id) { diff --git a/src/neutrino_menue.cpp b/src/neutrino_menue.cpp index 52fef1585..f75fcd83c 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 @@ -93,9 +87,9 @@ extern CCAMMenuHandler * g_CamHandler; const mn_widget_struct_t menu_widgets[MENU_MAX] = { - {LOCALE_MAINMENU_HEAD, NEUTRINO_ICON_MAINMENU, MENU_WIDTH}, /* 0 = MENU_MAIN */ - {LOCALE_MAINSETTINGS_HEAD, NEUTRINO_ICON_SETTINGS, MENU_WIDTH}, /* 1 = MENU_SETTINGS */ - {LOCALE_SERVICEMENU_HEAD, NEUTRINO_ICON_SETTINGS, MENU_WIDTH} /* 2 = MENU_SERVICE */ + {LOCALE_MAINMENU_HEAD, NEUTRINO_ICON_MAINMENU, MENU_WIDTH}, /* 0 = MENU_MAIN*/ + {LOCALE_MAINSETTINGS_HEAD, NEUTRINO_ICON_SETTINGS, MENU_WIDTH}, /* 1 = MENU_SETTINGS*/ + {LOCALE_SERVICEMENU_HEAD, NEUTRINO_ICON_SETTINGS, MENU_WIDTH} /* 2 = MENU_SERVICE*/ }; //init all menues @@ -167,13 +161,14 @@ void CNeutrinoApp::InitMenuMain() media->setHint(NEUTRINO_ICON_HINT_MEDIA, LOCALE_MENU_HINT_MEDIA); personalize.addItem(MENU_MAIN, media, &g_settings.personalize[SNeutrinoSettings::P_MAIN_MEDIA]); - CMenuForwarder *mf; + CMenuForwarder * mf; //games bool show_games = g_Plugins->hasPlugin(CPlugins::P_TYPE_GAME); mf = new CMenuForwarder(LOCALE_MAINMENU_GAMES, show_games, NULL, new CPluginList(LOCALE_MAINMENU_GAMES,CPlugins::P_TYPE_GAME)); 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_Plugins->hasPlugin(CPlugins::P_TYPE_TOOL); mf = new CMenuForwarder(LOCALE_MAINMENU_TOOLS, show_tools, NULL, new CPluginList(LOCALE_MAINMENU_TOOLS,CPlugins::P_TYPE_TOOL)); @@ -191,6 +186,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_Plugins->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 //separator personalize.addSeparator(MENU_MAIN); @@ -276,6 +277,7 @@ void CNeutrinoApp::InitMenuSettings() // settings manager mf = new CMenuForwarder(LOCALE_MAINSETTINGS_MANAGE, true, NULL, new CSettingsManager(), NULL, CRCInput::RC_green); personalize.addItem(MENU_SETTINGS, mf, &g_settings.personalize[SNeutrinoSettings::P_MSET_SETTINGS_MANAGER], false, CPersonalizeGui::PERSONALIZE_SHOW_AS_ACCESS_OPTION); + mf->setHint(NEUTRINO_ICON_HINT_MANAGE_SETTINGS, LOCALE_MENU_HINT_MANAGE_SETTINGS); // personalize @@ -344,6 +346,8 @@ void CNeutrinoApp::InitMenuSettings() personalize.addItem(MENU_SETTINGS, mf, &g_settings.personalize[SNeutrinoSettings::P_MSET_DRIVES]); } + // energy + // cisettings mf = new CMenuForwarder(LOCALE_CI_SETTINGS, true, NULL, g_CamHandler); mf->setHint(NEUTRINO_ICON_HINT_CI, LOCALE_MENU_HINT_CI); @@ -395,13 +399,19 @@ void CNeutrinoApp::InitMenuService() personalize.addItem(MENU_SERVICE, mf, &g_settings.personalize[SNeutrinoSettings::P_MSER_RELOAD_CHANNELS]); //bouquet edit - mf = new CMenuForwarder(LOCALE_BOUQUETEDITOR_NAME , 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]); + // TODO: this needs a neutrino restart after changing parentallock_prompt to activate :-( + 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); + /* 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 CDataResetNotifier *resetNotifier = new CDataResetNotifier(); mf = new CMenuForwarder(LOCALE_RESET_CHANNELS , true, NULL, resetNotifier, "channels"); + mf->setHint(NEUTRINO_ICON_HINT_DELETE_CHANNELS, LOCALE_MENU_HINT_DELETE_CHANNELS); personalize.addItem(MENU_SERVICE, mf, &g_settings.personalize[SNeutrinoSettings::P_MSER_RESET_CHANNELS]); @@ -438,6 +448,7 @@ void CNeutrinoApp::InitMenuService() //firmware update mf = new CMenuForwarder(LOCALE_SERVICEMENU_UPDATE, true, NULL, new CSoftwareUpdate()); + mf->setHint(NEUTRINO_ICON_HINT_SW_UPDATE, LOCALE_MENU_HINT_SW_UPDATE); personalize.addItem(MENU_SERVICE, mf, &g_settings.personalize[SNeutrinoSettings::P_MSER_SOFTUPDATE], false, CPersonalizeGui::PERSONALIZE_SHOW_AS_ITEM_OPTION, NULL, DCOND_MODE_TS); } diff --git a/src/neutrino_menue.h b/src/neutrino_menue.h index ba7abdb2f..b482aa0f4 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/tuxboxapi/controlapi.cpp b/src/nhttpd/tuxboxapi/controlapi.cpp index 90dbad0b4..aae45af24 100644 --- a/src/nhttpd/tuxboxapi/controlapi.cpp +++ b/src/nhttpd/tuxboxapi/controlapi.cpp @@ -185,7 +185,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"}, @@ -911,6 +913,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) { perror("opening " EVENTDEV " failed"); @@ -930,6 +933,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(); } //----------------------------------------------------------------------------- @@ -1993,7 +1999,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); @@ -2005,7 +2011,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)) { @@ -2067,6 +2073,7 @@ void CControlAPI::ReloadChannelsCGI(CyhookHandler *hh) hh->SendOk(); } +#ifdef SCREENSHOT void CControlAPI::ScreenshotCGI(CyhookHandler *hh) { bool enableOSD = true; @@ -2096,6 +2103,7 @@ void CControlAPI::ScreenshotCGI(CyhookHandler *hh) delete screenshot; } } +#endif //----------------------------------------------------------------------------- void CControlAPI::ZaptoCGI(CyhookHandler *hh) diff --git a/src/nhttpd/tuxboxapi/neutrinoapi.cpp b/src/nhttpd/tuxboxapi/neutrinoapi.cpp index 6aef17954..a4f3d8aea 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 5ad95bac3..1acc8a655 100644 --- a/src/nhttpd/tuxboxapi/neutrinoyparser.cpp +++ b/src/nhttpd/tuxboxapi/neutrinoyparser.cpp @@ -676,7 +676,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_mods/Makefile.am b/src/nhttpd/yhttpd_mods/Makefile.am index 240d14804..dee165cb5 100644 --- a/src/nhttpd/yhttpd_mods/Makefile.am +++ b/src/nhttpd/yhttpd_mods/Makefile.am @@ -11,7 +11,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/rcsim.c b/src/rcsim.c index ccfdb6c59..478c8c4c7 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 3304ec953..63fb188f2 100644 --- a/src/system/Makefile.am +++ b/src/system/Makefile.am @@ -43,3 +43,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 5c1eb4234..c09412182 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 + CFlashTool::CFlashTool() { statusViewer = NULL; diff --git a/src/system/helpers.cpp b/src/system/helpers.cpp index 246af293a..57a6cd477 100644 --- a/src/system/helpers.cpp +++ b/src/system/helpers.cpp @@ -31,11 +31,13 @@ #include #include #include /* forkpty*/ +#include #include #include #include #include #include /* or */ +#include /* gettimeofday */ #include #include #include @@ -307,7 +309,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; } @@ -614,7 +616,6 @@ std::string& htmlEntityDecode(std::string& text) CFileHelpers::CFileHelpers() { FileBufMaxSize = 0xFFFF; - doCopyFlag = true; ConsoleQuiet = false; clearDebugInfo(); } @@ -800,8 +801,6 @@ bool CFileHelpers::cp(const char *Src, const char *Dst, const char *Flags/*=""*/ bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t forceMode/*=0*/) { - doCopyFlag = true; - /* set mode for Dst ---------------- @@ -837,69 +836,28 @@ bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t forceMode/* uint32_t block; off64_t fsizeSrc64 = lseek64(fd1, 0, SEEK_END); lseek64(fd1, 0, SEEK_SET); - if (fsizeSrc64 > 0x7FFFFFF0) { // > 2GB - uint32_t FileBufSize = FileBufMaxSize; - FileBuf = initFileBuf(FileBuf, FileBufSize); - 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); - FileBuf = deleteFileBuf(FileBuf); - return false; - } - } + off64_t fsize64 = fsizeSrc64; + uint32_t FileBufSize = (fsizeSrc64 < (off_t)FileBufMaxSize) ? (uint32_t)fsizeSrc64 : FileBufMaxSize; + FileBuf = initFileBuf(FileBuf, FileBufSize); + 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); - uint32_t FileBufSize = (fsizeSrc < (off_t)FileBufMaxSize) ? fsizeSrc : FileBufMaxSize; - FileBuf = initFileBuf(FileBuf, FileBufSize); - 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); - FileBuf = deleteFileBuf(FileBuf); - return false; - } - } - } - close(fd1); - close(fd2); - - if (!doCopyFlag) { - sync(); - unlink(Dst); + lseek64(fd2, 0, SEEK_SET); + off64_t fsizeDst64 = lseek64(fd2, 0, SEEK_END); + if (fsizeSrc64 != fsizeDst64) { + close(fd1); + close(fd2); FileBuf = deleteFileBuf(FileBuf); return false; } + close(fd1); + close(fd2); FileBuf = deleteFileBuf(FileBuf); return true; @@ -967,8 +925,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()); /* mode is set by copyFile */ } } diff --git a/src/system/helpers.h b/src/system/helpers.h index 910f9ea3c..adc87fd05 100644 --- a/src/system/helpers.h +++ b/src/system/helpers.h @@ -96,7 +96,6 @@ class CFileHelpers CFileHelpers(); ~CFileHelpers(); static CFileHelpers* getInstance(); - bool doCopyFlag; void clearDebugInfo(); void readDebugInfo(helpersDebugInfo* di); 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 2212b569f..9c09bc2ad 100644 --- a/src/system/setting_helpers.cpp +++ b/src/system/setting_helpers.cpp @@ -492,9 +492,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 +572,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 +595,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 +624,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_CS_HD2 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.cpp b/src/system/settings.cpp index 4ee846df1..8546a2f8c 100644 --- a/src/system/settings.cpp +++ b/src/system/settings.cpp @@ -40,9 +40,9 @@ const struct personalize_settings_t personalize_settings[SNeutrinoSettings::P_SE {"personalize_redbutton" , CPersonalizeGui::PERSONALIZE_ACTIVE_MODE_ENABLED}, // epg/info //main menu - {"personalize_tv_mode" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, - {"personalize_tv_radio_mode" , CPersonalizeGui::PERSONALIZE_MODE_NOTVISIBLE}, //toggle - {"personalize_radio_mode" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, + {"personalize_tv_mode" , CPersonalizeGui::PERSONALIZE_MODE_NOTVISIBLE}, + {"personalize_tv_radio_mode" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, //toggle + {"personalize_radio_mode" , CPersonalizeGui::PERSONALIZE_MODE_NOTVISIBLE}, {"personalize_timer" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, {"personalize_media" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, diff --git a/src/system/settings.h b/src/system/settings.h index b6095f21c..4b0bd8f14 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 @@ -47,7 +49,7 @@ #ifdef BOXMODEL_CS_HD2 #define VIDEOMENU_VIDEOMODE_OPTION_COUNT 16 #else -#define VIDEOMENU_VIDEOMODE_OPTION_COUNT 12 +#define VIDEOMENU_VIDEOMODE_OPTION_COUNT 13 #endif struct SNeutrinoTheme @@ -726,7 +728,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 @@ -895,7 +897,7 @@ typedef struct time_settings_t const time_settings_struct_t timing_setting[SNeutrinoSettings::TIMING_SETTING_COUNT] = { - { 0, LOCALE_TIMING_MENU, LOCALE_MENU_HINT_OSD_TIMING},//TODO: add hint locales + { 240, LOCALE_TIMING_MENU, LOCALE_MENU_HINT_OSD_TIMING},//TODO: add hint locales { 60, LOCALE_TIMING_CHANLIST, LOCALE_MENU_HINT_OSD_TIMING}, { 240, LOCALE_TIMING_EPG, LOCALE_MENU_HINT_OSD_TIMING}, { 6, LOCALE_TIMING_INFOBAR, LOCALE_MENU_HINT_OSD_TIMING}, diff --git a/src/system/stacktrace.cpp b/src/system/stacktrace.cpp index d692287f1..1c6bcd449 100644 --- a/src/system/stacktrace.cpp +++ b/src/system/stacktrace.cpp @@ -176,5 +176,14 @@ void install_crash_handler() void *trace[16]; backtrace(trace, 16); } +#else +void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) +{ + (void) out; + (void) max_frames; +} +void install_crash_handler() +{ +} #endif diff --git a/src/timerd/timerd.cpp b/src/timerd/timerd.cpp index e1b00fbf9..3585a3b94 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..8441cf1bd --- /dev/null +++ b/src/uncooloff.c @@ -0,0 +1,70 @@ +/* + * 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 + +#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/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 47a90177c..602385c97 100644 --- a/src/zapit/include/zapit/client/zapitclient.h +++ b/src/zapit/include/zapit/client/zapitclient.h @@ -495,11 +495,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 2e92da4b5..987148734 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 */ @@ -182,6 +181,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); @@ -206,7 +208,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; } @@ -271,7 +273,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; } 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/scan.h b/src/zapit/include/zapit/scan.h index bfdfabf55..7457b2889 100644 --- a/src/zapit/include/zapit/scan.h +++ b/src/zapit/include/zapit/scan.h @@ -107,6 +107,7 @@ class CServiceScan : public OpenThreads::Thread uint32_t tune_tp_index; unsigned char fst_version; +#if ENABLE_FASTSCAN bool quiet_fastscan; void InitFastscanLnb(int id); bool FastscanTune(int id); @@ -118,7 +119,7 @@ class CServiceScan : public OpenThreads::Thread void process_satellite_delivery_system_descriptor(const unsigned char * const buffer, FrontendParameters * feparams, t_satellite_position * satellitePosition); bool ScanFast(); void ReportFastScan(FrontendParameters &feparams, t_satellite_position satellitePosition); - +#endif void run(); CFrontend * frontend; @@ -149,12 +150,14 @@ class CServiceScan : public OpenThreads::Thread bool isFtaOnly() { return flags & SCAN_FTA; } int GetFlags() { return flags; } bool SatHaveChannels() { return satHaveChannels; } +#if ENABLE_FASTSCAN /* fast-scan */ bool TestDiseqcConfig(int num); bool ReadFstVersion(int num); unsigned char GetFstVersion() { return fst_version; } void QuietFastScan(bool enable) { quiet_fastscan = enable; } bool ScanFast(int num, bool reload = true); +#endif }; #endif /* __scan_h__ */ diff --git a/src/zapit/include/zapit/settings.h b/src/zapit/include/zapit/settings.h index 48b1e5e28..d22b11ddd 100644 --- a/src/zapit/include/zapit/settings.h +++ b/src/zapit/include/zapit/settings.h @@ -50,10 +50,12 @@ #define TERRESTRIAL_XML CONFIGDIR "/terrestrial.xml" #define WEBTV_XML CONFIGDIR "/webtv_usr.xml" +#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 989f3cc7c..2d34ea1a3 100644 --- a/src/zapit/include/zapit/zapit.h +++ b/src/zapit/include/zapit/zapit.h @@ -69,9 +69,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; @@ -203,7 +200,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/zapitclient.cpp b/src/zapit/lib/zapitclient.cpp index f733112ef..fc9c6b9da 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); @@ -657,6 +681,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; @@ -878,6 +903,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; @@ -892,6 +918,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; @@ -906,6 +933,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; @@ -979,6 +1007,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; @@ -994,6 +1023,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; @@ -1009,6 +1039,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; @@ -1024,6 +1055,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; @@ -1048,6 +1080,7 @@ void CZapitClient::renumChannellist() void CZapitClient::saveBouquets(const bool saveall) { CZapitMessages::commandBoolean msg; + VALGRIND_PARANOIA; msg.truefalse = saveall; OpenThreads::ScopedLock lock(mutex); @@ -1062,36 +1095,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(); @@ -1106,18 +1145,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(); @@ -1146,6 +1191,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)); @@ -1166,6 +1212,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)); @@ -1206,6 +1253,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)); @@ -1215,6 +1263,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)); @@ -1225,6 +1274,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)); @@ -1234,6 +1284,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; @@ -1249,6 +1300,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/Makefile.am b/src/zapit/src/Makefile.am index 1d185ae00..2e6427d32 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -21,7 +21,6 @@ libzapit_a_SOURCES = \ bouquets.cpp \ capmt.cpp \ channel.cpp \ - fastscan.cpp \ femanager.cpp \ frontend.cpp \ getservices.cpp \ @@ -34,6 +33,11 @@ libzapit_a_SOURCES = \ transponder.cpp \ zapit.cpp +if ENABLE_FASTSCAN +libzapit_a_SOURCES += \ + fastscan.cpp +endif + bin_PROGRAMS = pzapit pzapit_SOURCES = \ diff --git a/src/zapit/src/bouquets.cpp b/src/zapit/src/bouquets.cpp index ff018ded9..81c85792f 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 ce8dc7de1..1f21a5dbc 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; @@ -228,15 +228,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(); @@ -257,6 +275,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 24007310e..017b98ecf 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 7987eb5a0..5fd546b58 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-2016 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,16 @@ bool CFEManager::Init() dmap.push_back(CFeDmx(i)); INFO("found %d frontends, %d demuxes", (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, -1); + fekey = MAKE_FE_KEY(0, 0); + femap.insert(std::pair (fekey, fe)); + fe->Open(); + livefe = fe; + have_sat = true; + } if (femap.empty()) return false; @@ -239,8 +247,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); @@ -340,6 +349,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); @@ -456,11 +466,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) { @@ -475,7 +489,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); } } @@ -494,8 +508,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; } @@ -645,7 +666,6 @@ CFrontend * CFEManager::allocateFE(CZapitChannel * channel, bool forrecord) { OpenThreads::ScopedLock m_lock(mutex); - fedebug = 1; if (forrecord) fedebug = 1; CFrontend * frontend = getFrontend(channel); @@ -662,7 +682,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 */ @@ -680,7 +703,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 e4a0e1195..51775f525 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-2016 Stefan Seyfried * Copyright (C) 2011 CoolStream International Ltd * * This program is free software; you can redistribute it and/or modify @@ -39,6 +40,8 @@ #include #include +#include + extern transponder_list_t transponders; extern int zapit_debug; @@ -167,6 +170,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) @@ -174,11 +179,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; @@ -195,12 +200,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; @@ -208,7 +221,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(); } @@ -220,7 +233,15 @@ 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); + + if (adapter == -1) { + deliverySystemMask |= DVB_S; + deliverySystemMask |= DVB_S2; + info.type = FE_QPSK; + strcpy(info.name, "dummyfe"); + return false; + } mutex.lock(); if (fd < 0) { @@ -309,9 +330,7 @@ void CFrontend::getFEInfo(void) switch (info.type) { case FE_QPSK: deliverySystemMask |= DVB_S; -#ifndef BOXMODEL_CS_HD1 - if (info.caps & FE_CAN_2G_MODULATION) -#endif + if (info.caps & FE_CAN_2G_MODULATION || get_hwcaps()->force_tuner_2G) deliverySystemMask |= DVB_S2; break; case FE_OFDM: @@ -332,6 +351,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. @@ -347,7 +368,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(); @@ -390,14 +411,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() @@ -542,8 +563,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 } @@ -623,6 +646,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; } @@ -672,7 +697,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) { @@ -681,24 +706,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 = (uint32_t)(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) @@ -722,7 +750,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); } @@ -797,25 +825,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: @@ -823,99 +851,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; } /* fall through */ 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; } } @@ -934,9 +966,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; @@ -952,15 +986,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; @@ -1040,9 +1076,11 @@ 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; @@ -1095,11 +1133,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; @@ -1131,7 +1171,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; @@ -1165,7 +1205,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; } @@ -1191,6 +1231,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; @@ -1211,13 +1255,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; @@ -1254,12 +1298,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); } } @@ -1272,11 +1316,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; } @@ -1356,7 +1400,7 @@ void CFrontend::setDiseqcType(const diseqc_t newDiseqcType, bool force) if (newDiseqcType == DISEQC_UNICABLE || newDiseqcType == DISEQC_UNICABLE2) { 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))) { @@ -1468,7 +1512,6 @@ void CFrontend::setInput(t_satellite_position satellitePosition, uint32_t freque if (config.diseqcType == DISEQC_UNICABLE || config.diseqcType == DISEQC_UNICABLE2) return; - if (config.diseqcType != DISEQC_ADVANCED) { setDiseqc(sit->second.diseqc, polarization, frequency); return; @@ -1486,36 +1529,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; } uint32_t CFrontend::sendEN50607TuningCommand(const uint32_t frequency, const int high_band, const int horizontal, const int bank) @@ -1596,7 +1653,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) { @@ -1701,7 +1758,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; @@ -1822,6 +1879,7 @@ void CFrontend::sendDiseqcStandby(uint32_t ms) fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_13); return; } + /* en50494 switches don't seem to be hurt by this */ // Send power off to 'all' equipment sendDiseqcZeroByteCommand(0xe0, 0x00, 0x02, ms); } @@ -1881,7 +1939,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 a9d331803..3071d7145 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); @@ -979,7 +985,7 @@ void CServiceManager::CopyFile(const char * from, const char * to) } in.close(); } - sync(); + // sync(); } void CServiceManager::WriteSatHeader(FILE * fd, sat_config_t &config) diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index 233d6bf5c..bba6e472f 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -120,9 +120,11 @@ void CServiceScan::run() fst_version = 0; ScanTransponder(); break; +#if 0 case SCAN_FAST: ScanFast(); break; +#endif default: break; } @@ -155,8 +157,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) @@ -533,7 +549,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", @@ -668,8 +684,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/scanpmt.cpp b/src/zapit/src/scanpmt.cpp index be71ac995..b9a818630 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); @@ -302,7 +302,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) @@ -398,7 +398,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 f6641dbb8..2f4166bcc 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,9 +65,9 @@ #include #include #endif -#if HAVE_TRIPLEDRAGON -#include -#include +#if USE_STB_HAL +#include +#include #endif #include @@ -78,6 +79,12 @@ #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 @@ -572,11 +579,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)); @@ -597,6 +618,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; @@ -617,7 +647,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: @@ -720,6 +750,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); @@ -732,15 +764,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; } @@ -923,7 +970,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) @@ -1032,7 +1079,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; } @@ -1058,6 +1105,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)); } @@ -1132,6 +1180,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); @@ -1203,6 +1252,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; @@ -1210,6 +1260,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; @@ -1217,6 +1268,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(); @@ -1247,6 +1299,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; @@ -1283,6 +1336,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 : @@ -1414,6 +1468,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; @@ -1428,6 +1483,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(); @@ -1513,6 +1569,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; @@ -1521,6 +1578,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)); @@ -1555,6 +1613,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); @@ -1676,14 +1735,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: @@ -1693,6 +1762,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; @@ -1704,12 +1779,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)) @@ -1720,6 +1802,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) unlockPlayBack(); SendCmdReady(connfd); break; + } #if 0 case CZapitMessages::CMD_SET_DISPLAY_FORMAT: { CZapitMessages::commandInt msg; @@ -1754,6 +1837,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)); @@ -1782,6 +1866,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(); @@ -1893,6 +1978,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; @@ -1903,6 +1989,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; @@ -1913,9 +2000,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 @@ -1964,6 +2051,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"); @@ -1978,6 +2066,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; @@ -2006,6 +2095,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) { @@ -2017,6 +2107,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); @@ -2039,6 +2130,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: @@ -2170,6 +2262,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 (video_pid) { + videoDecoder->Start(0, thisChannel->getPcrPid(), thisChannel->getVideoPid()); + videoDemux->Start(); + } +#endif + /* select audio output and start audio */ if (audio_pid) { SetAudioStreamType(thisChannel->getAudioChannel()->audioChannelType); @@ -2177,11 +2278,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); @@ -2191,7 +2294,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) @@ -2210,13 +2313,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 @@ -2383,8 +2497,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()*/); @@ -2481,6 +2601,7 @@ bool CZapit::Stop() { if(!started) return false; + pmt_stop_update_filter(&pmt_update_fd); started = false; int ret = join(); return (ret == 0); @@ -2493,6 +2614,10 @@ static bool zapit_parse_command(CBasicMessage::Header &rmsg, int connfd) void CZapit::run() { +//if HAVE_SPARK_HARDWARE +#if 0 + bool v_stopped = false; +#endif set_threadname("zap:main"); printf("[zapit] starting... tid %ld\n", syscall(__NR_gettid)); @@ -2538,6 +2663,33 @@ void CZapit::run() SendEvent(CZapitClient::EVT_PMT_CHANGED, &channel_id, sizeof(channel_id)); } } +//if HAVE_SPARK_HARDWARE +#if 0 + /* 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);