diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README | 111 | ||||
-rw-r--r-- | common.c | 4 | ||||
-rw-r--r-- | display.c | 26 | ||||
-rw-r--r-- | display.h | 7 | ||||
-rw-r--r-- | patches/femon-1.1.5_fixnullandsegfault_path.diff | 38 | ||||
-rw-r--r-- | patches/femon-1.7.7_fixsegfault_patch.diff | 11 | ||||
-rw-r--r-- | service.c | 358 | ||||
-rw-r--r-- | service.h | 87 | ||||
-rw-r--r-- | skinconfig.c | 73 | ||||
-rw-r--r-- | skinconfig.h | 1 | ||||
-rw-r--r-- | state.c | 97 | ||||
-rw-r--r-- | state.h | 24 |
13 files changed, 654 insertions, 188 deletions
@@ -65,10 +65,13 @@ ifdef HAVE_FREETYPE2 DEFINES += -DHAVE_FREETYPE2 endif +### If femon-plugin <= 1.7.7 is used and has already been patched (see README) +# DEFINES += -DGRAPHLCD_SERVICE_FEMON_VALID + ### The object files (add further files here): #OBJS = alias.o common.o display.o i18n.o menu.o plugin.o setup.o skinconfig.o state.o strfct.o -OBJS = alias.o common.o display.o menu.o plugin.o setup.o skinconfig.o state.o strfct.o +OBJS = alias.o common.o display.o menu.o plugin.o setup.o skinconfig.o state.o strfct.o service.o ### The main target: TARGETS = libvdr-$(PLUGIN).so @@ -4,7 +4,8 @@ Written by Carsten Siebholz (c.siebholz AT t-online.de> From 0.0.8 on maintained by Andreas 'powARman' Regel (andreas.regel AT powarman.de) from 0.1.5 on maintained by Wolfgang Astleitner (mrwastl AT users.sourceforge.net) & Andreas 'randy' Weinberger (vdr AT smue.org) -Project's homepage: http://graphlcd.berlios.de/ +Project's homepage: http://projects.vdr-developer.org/projects/show/graphlcd + before 0.1.5: http://graphlcd.berlios.de/ before 0.0.8: http://c.siebholz.bei.t-online.de/ GIT repo: http://projects.vdr-developer.org/projects/show/graphlcd @@ -41,7 +42,9 @@ Installation and Configuration: | | | | | +-- fonts (contains *.fnt files) | | | - . . +-- logos (contains *.glcd files) + | | +-- logos (contains *.glcd files) + | | | + . . +-- skins (contains skin files and definitions) . . 5. If you are using VDR 1.3 or higher, you will have to recreate the @@ -56,6 +59,8 @@ Installation and Configuration: Possible options are: -c CONFIG, --config=CONFIG file name and path of the configuration file -d DISPLAY, --display=DISPLAY name of the display + -s SKIN, --skin=SKIN name of the skin + -c: Sets the file path and name of the driver library's config file. If this parameter is not given the default '/etc/graphlcd.conf' @@ -63,10 +68,13 @@ Installation and Configuration: -d: Sets the name of the section in the config file that specifies the display used for the plugin's output. If this parameter is not given, the first section will be used. + -s: Sets the name of the skin to be used. + If this parameter is not given, skin 'default' will be used. Examples: vdr -P 'graphlcd -c /video/graphlcd.conf -d ks0108' vdr -P 'graphlcd -c /etc/graphlcd.conf' + vdr -P 'graphlcd -c /video/graphlcd.conf -d usb13700 -s bigskin' Channel Logos @@ -187,47 +195,60 @@ Scroll time interval: (Possible values: 100 <= x <= 2000) -Changing Fonts: ---------------- -It's very easy to change the fonts that are used by graphlcd. -The plugin uses 4 fonts: -- a large font, that is used for - the title of the current program and for - the title of the recording (during replay). -- a normal font, that is used for - the date/time bar, - the channel bar, - the starttime, endtime and the subtitle of the current program, - the times in the replay screen, - the title and the items in the menus, - the popup-messages and for - the text items like the content of a recording. -- a small font, that is only used for the text of the 4 colored buttons. -- a symbol font, that contains the symbols. - -Because smaller displays should use smaller fonts, the displays will be -classified in 3 categories. Each category should have all 4 fonts. -The name of the font files depend on the category and on the font: - small displays ( vertical size < 64 ): - f_s_l.fnt : large font - f_s_n.fnt : normal font - f_s_s.fnt : small font - f_s_sym.fnt: symbols - medium displays ( vertical size 64..127 ): - f_m_l.fnt : large font - f_m_n.fnt : normal font - f_m_s.fnt : small font - f_m_sym.fnt: symbols - large displays ( vertical size >= 128 ): - f_l_l.fnt : large font - f_l_n.fnt : normal font - f_l_s.fnt : small font - f_l_sym.fnt: symbols - -To change the fonts you only have to change the related symbolic link to -another font file. -If you use another already existing font or if you want to create a new -one by yourself does not matter. If you want to create a new one or if -you want to modify an existing font, look into /tools/crtfont in the -GraphLCD base package and read the README. +Patches +------- +femon: +versions <= 1.7.7 require a patch to be functionable with graphlcd. +if graphlcd-plugin detects a femon version <= 1.7.7 and this version has not yet been patched, +femon will ignored by graphlcd (problem: if graphlcd calls an unpatched femon, vdr will crash +when shutting or restarting). the bug has already been reported to the maintainer of femon and +will be fixed in 1.7.8. + +note: $SOURCEDIR/VDR == source directory of vdr. replace accordingly. + +for femon <= 1.2.x apply the following patch: +cd $SOURCEDIR/VDR/PLUGINS/src/femon +patch -p0 < $SOURCEDIR/VDR/PLUGINS/src/graphlcd/patches/femon-1.1.5_fixnullandsegfault_path.diff + +for femon > 1.2.x and <= 1.7.7 apply the following patch: +cd $SOURCEDIR/VDR/PLUGINS/src/femon +patch -p0 < $SOURCEDIR/VDR/PLUGINS/src/graphlcd/patches/femon-1.7.7_fixsegfault_patch.diff + +or, if you don't want to apply a patch or the patch fails with your version of femon, +replace the entire function + +bool cPluginFemon::Service(const char *Id, void *Data) +{ +.... +} + +with the following one (should be valid for all femon versions >= 1.1.x): + +bool cPluginFemon::Service(const char *Id, void *Data) +{ + if (strcmp(Id,"FemonService-v1.0") == 0) { + if (Data) { + FemonService_v1_0 *data = (FemonService_v1_0*)Data; + if (! cDevice::ActualDevice() ) + return false; + + int ndx = cDevice::ActualDevice()->CardIndex(); + data->fe_name = getFrontendName(ndx); + data->fe_status = getFrontendStatus(ndx); + data->fe_snr = getSNR(ndx); + data->fe_signal = getSignal(ndx); + data->fe_ber = getBER(ndx); + data->fe_unc = getUNC(ndx); + data->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0; + data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0; + data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 0.0; + } + return true; + } + + return false; +} + + +after applying this patch uncomment DEFINES += -DGRAPHLCD_SERVICE_FEMON_VALID in the Makefile. @@ -70,8 +70,8 @@ GLCD::cType DurationType(int Index, const std::string &Format) enum { normal, format } state = normal; int n = 0; #if VDRVERSNUM >= 10701 - int f = (Index % DEFAULTFRAMESPERSECOND) + 1; - int s = (Index / DEFAULTFRAMESPERSECOND); + int f = (Index % (int)DEFAULTFRAMESPERSECOND) + 1; + int s = (Index / (int)DEFAULTFRAMESPERSECOND); #else int f = (Index % FRAMESPERSEC) + 1; int s = (Index / FRAMESPERSEC); @@ -49,6 +49,8 @@ cGraphLCDDisplay::cGraphLCDDisplay() nCurrentBrightness = -1; LastTimeBrightness = 0; bBrightnessActive = true; + + mService = NULL; /* cannot be initialised here (mGraphLCDState not yet available) */ } cGraphLCDDisplay::~cGraphLCDDisplay() @@ -59,6 +61,8 @@ cGraphLCDDisplay::~cGraphLCDDisplay() delete mSkinConfig; delete mScreen; delete mGraphLCDState; + + delete mService; } bool cGraphLCDDisplay::Initialise(GLCD::cDriver * Lcd, const std::string & CfgPath, const std::string & SkinsPath, const std::string & SkinName) @@ -73,6 +77,9 @@ bool cGraphLCDDisplay::Initialise(GLCD::cDriver * Lcd, const std::string & CfgPa if (!mGraphLCDState) return false; + // must be initialised before cGraphLCDSkinConfig (else: seg fault) + mService = new cGraphLCDService(mGraphLCDState); + skinsPath = SkinsPath; if (skinsPath == "") skinsPath = CfgPath + "/skins"; @@ -191,19 +198,28 @@ void cGraphLCDDisplay::Action(void) mUpdate = true; } + + bool bActive = bBrightnessActive + || (mState != StateNormal) + || (GraphLCDSetup.ShowVolume && mShowVolume) + || (GraphLCDSetup.ShowMessages && mGraphLCDState->ShowMessage()) + || (GraphLCDSetup.BrightnessDelay == 900); + // update display if BrightnessDelay is exceeded - if ((nCurrentBrightness == GraphLCDSetup.BrightnessActive) && - ((cTimeMs::Now() - LastTimeBrightness) > (uint64_t) (GraphLCDSetup.BrightnessDelay*1000))) + if (bActive && (nCurrentBrightness == GraphLCDSetup.BrightnessActive) && + ((int)((cTimeMs::Now() - LastTimeBrightness)) > (GraphLCDSetup.BrightnessDelay*1000))) { mUpdate = true; } - // external service changed (check each second) - if ( (currTimeMs/1000 != mLastTimeMs/1000) && mGraphLCDState->CheckServiceEventUpdate()) + + // external service changed (check each 1/10th second) + if ( (currTimeMs/100 != mLastTimeMs/100) && mService->NeedsUpdate(currTimeMs)) { mUpdate = true; } + if (mUpdate) { mUpdateAt = 0; @@ -353,7 +369,7 @@ void cGraphLCDDisplay::SetBrightness() else { if (GraphLCDSetup.BrightnessDelay < 1 - || ((cTimeMs::Now() - LastTimeBrightness) > (uint64_t) (GraphLCDSetup.BrightnessDelay*1000))) + || ((int)(cTimeMs::Now() - LastTimeBrightness) > (GraphLCDSetup.BrightnessDelay*1000))) { mLcd->SetBrightness(GraphLCDSetup.BrightnessIdle); nCurrentBrightness = GraphLCDSetup.BrightnessIdle; @@ -28,6 +28,8 @@ #include "state.h" #include "skinconfig.h" +#include "service.h" + #include <vdr/thread.h> @@ -56,6 +58,7 @@ public: void ForceUpdateBrightness(); + const cGraphLCDService * GetServiceObject() const { return mService; } protected: virtual void Action(); @@ -79,11 +82,13 @@ private: void UpdateIn(uint64_t msec); - /** set brightness depending on user activity */ + /* set brightness depending on user activity */ void SetBrightness(); uint64_t LastTimeBrightness; int nCurrentBrightness; bool bBrightnessActive; + /* external services */ + cGraphLCDService * mService; }; #endif diff --git a/patches/femon-1.1.5_fixnullandsegfault_path.diff b/patches/femon-1.1.5_fixnullandsegfault_path.diff new file mode 100644 index 0000000..a8dcc82 --- /dev/null +++ b/patches/femon-1.1.5_fixnullandsegfault_path.diff @@ -0,0 +1,38 @@ +--- femon.c_orig 2008-01-20 03:20:00.000000000 +0100 ++++ femon.c 2010-06-05 01:30:33.000000000 +0200 +@@ -134,18 +134,23 @@ + + bool cPluginFemon::Service(const char *Id, void *Data) + { +- if ((strcmp(Id,"FemonService-v1.0") == 0) && Data) { +- FemonService_v1_0 *data = (FemonService_v1_0*)Data; +- int ndx = cDevice::ActualDevice()->CardIndex(); +- data->fe_name = getFrontendName(ndx); +- data->fe_status = getFrontendStatus(ndx); +- data->fe_snr = getSNR(ndx); +- data->fe_signal = getSignal(ndx); +- data->fe_ber = getBER(ndx); +- data->fe_unc = getUNC(ndx); +- data->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0; +- data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0; +- data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 0.0; ++ if (strcmp(Id,"FemonService-v1.0") == 0) { ++ if (Data) { ++ FemonService_v1_0 *data = (FemonService_v1_0*)Data; ++ if (! cDevice::ActualDevice() ) ++ return false; ++ ++ int ndx = cDevice::ActualDevice()->CardIndex(); ++ data->fe_name = getFrontendName(ndx); ++ data->fe_status = getFrontendStatus(ndx); ++ data->fe_snr = getSNR(ndx); ++ data->fe_signal = getSignal(ndx); ++ data->fe_ber = getBER(ndx); ++ data->fe_unc = getUNC(ndx); ++ data->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0; ++ data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0; ++ data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 0.0; ++ } + return true; + } + diff --git a/patches/femon-1.7.7_fixsegfault_patch.diff b/patches/femon-1.7.7_fixsegfault_patch.diff new file mode 100644 index 0000000..86cf976 --- /dev/null +++ b/patches/femon-1.7.7_fixsegfault_patch.diff @@ -0,0 +1,11 @@ +--- femon.c_orig 2010-06-05 01:34:59.000000000 +0200 ++++ femon.c 2010-06-05 01:35:23.000000000 +0200 +@@ -133,6 +133,8 @@ + if (strcmp(Id,"FemonService-v1.0") == 0) { + if (Data) { + FemonService_v1_0 *data = (FemonService_v1_0*)Data; ++ if (! cDevice::ActualDevice() ) ++ return false; + int ndx = cDevice::ActualDevice()->CardIndex(); + data->fe_name = getFrontendName(ndx); + data->fe_status = getFrontendStatus(ndx); diff --git a/service.c b/service.c new file mode 100644 index 0000000..bc6da24 --- /dev/null +++ b/service.c @@ -0,0 +1,358 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * service.h - class for events from external services + * + * (c) 2010 Wolfgang Astleitner <mrwastl AT users sourceforge net> + **/ + +#include "strfct.h" + +#include "service.h" + +#include <vdr/plugin.h> + + +cGraphLCDService::cGraphLCDService(cGraphLCDState * state) +{ + mState = state; + + /* initialise flags for services */ + radioActive = false; radioChanged = false; radioUse = false; + lcrActive = false; lcrChanged = false; lcrUse = false; + femonActive = false; femonChanged = false; femonUse = false; + + radioLastChange = lcrLastChange = femonLastChange = 0; + + femonVersionChecked = femonVersionValid = false; + + // default min. change delays + radioUpdateDelay = 100; // 100 ms + lcrUpdateDelay = 60000; // 60 sec + femonUpdateDelay = 2000; // 2 sec +} + +cGraphLCDService::~cGraphLCDService() +{ +} + + +bool cGraphLCDService::ServiceIsAvailable(const std::string & Name) { + if (Name == "RadioTextService-v1.0" || Name == "radio") { + radioUse = true; + return (mState->GetChannelInfo().isRadio) ? radioActive : false; + } else if (Name == "LcrService-v1.0" || Name == "lcr") { + lcrUse = true; + return lcrActive; + } else if (Name == "FemonService-v1.0" || Name == "femon") { + femonUse = true; + return femonActive; + } + return false; +} + + +void cGraphLCDService::SetServiceUpdateDelay(const std::string & Name, int delay) { + if (delay < 100) + return; + + if (Name == "RadioTextService-v1.0" || Name == "radio") { + radioUpdateDelay = delay; + } else if (Name == "LcrService-v1.0" || Name == "lcr") { + lcrUpdateDelay = delay; + } else if (Name == "FemonService-v1.0" || Name == "femon") { + femonUpdateDelay = delay; + } +} + + +GLCD::cType cGraphLCDService::GetItem(const std::string & ServiceName, const std::string & Item = "") +{ + size_t found = 0; + std::string ItemName = Item; + std::string ItemFormat = ""; + std::string ItemExtra = ""; + + if (ItemName != "") { + found = Item.find(","); + if (found != std::string::npos) { + ItemName = Item.substr(0, found); + ItemFormat = Item.substr(found+1); + if ( (found = ItemFormat.find(",")) != std::string::npos) { + ItemExtra = ItemFormat.substr(found+1); + ItemFormat = ItemFormat.substr(0, found); + } + } else { + ItemName = Item; + } + } + + //NeedsUpdate(); + if (ServiceName == "RadioTextService-v1.0" || ServiceName == "radio") { + radioUse = true; + if (radioActive) { + if (ItemName == "" || ItemName == "default") { + if (currRTSData.rds_info == 2 && strstr(currRTSData.rds_title, "---") == NULL) { + char rtpinfo[2][65], rtstr[140]; + strcpy(rtpinfo[0], currRTSData.rds_title); + strcpy(rtpinfo[1], currRTSData.rds_artist); + sprintf(rtstr, "%02d:%02d %s | %s", currRTSData.title_start->tm_hour, currRTSData.title_start->tm_min, trim(((std::string)(rtpinfo[0]))).c_str(), trim(((std::string)(rtpinfo[1]))).c_str()); + return rtstr; + } else if (currRTSData.rds_info > 0) { + return trim(currRTSData.rds_text); + } + } else if (ItemName == "title") { + return trim(currRTSData.rds_title); + } else if (ItemName == "artist") { + return trim(currRTSData.rds_artist); + } else if (ItemName == "text") { + return trim(currRTSData.rds_text); + } else if (ItemName == "rds_info" || ItemName == "info") { + return (int)(currRTSData.rds_info); + } else if (ItemName == "rds_pty" || ItemName == "pty") { + return (int)(currRTSData.rds_pty); + } + } + + } else if (ServiceName == "LcrService-v1.0" || ServiceName == "lcr") { + lcrUse = true; + if (lcrActive) { + if ( strstr( currLcrData.destination, "---" ) == NULL ) { + char lcrStringParts[3][25], lcrString[100]; + strcpy( lcrStringParts[0], (const char *)currLcrData.destination ); + strcpy( lcrStringParts[1], (const char *)currLcrData.price ); + strcpy( lcrStringParts[2], (const char *)currLcrData.pulse ); + sprintf(lcrString, "%s | %s", trim((std::string)(lcrStringParts[1])).c_str(), trim((std::string)(lcrStringParts[2])).c_str()); + if (ItemName == "" || ItemName == "default") { + return trim(lcrString); + } else if (ItemName == "destination") { + return trim(lcrStringParts[0]); + } else if (ItemName == "price") { + return trim(lcrStringParts[1]); + } else if (ItemName == "pulse") { + return trim(lcrStringParts[2]); + } + } + } + } else if (ServiceName == "FemonService-v1.0" || ServiceName == "femon") { + femonUse = true; + if (femonActive) { + if (ItemName == "" || ItemName == "default" || ItemName == "status") { + return (const char*)currFemonData.fe_status; + } else if (ItemName == "name") { + return (const char*)currFemonData.fe_name; + } else if (ItemName == "snr") { + return (int)currFemonData.fe_snr; + } else if (ItemName == "signal") { + return (int)currFemonData.fe_signal; + } else if (ItemName == "percent_snr") { + return (int)((currFemonData.fe_snr * 100) / 65535); + } else if (ItemName == "percent_signal") { + return (int)((currFemonData.fe_signal * 100) / 65535); + } else if (ItemName == "ber") { + return (int)currFemonData.fe_ber; + } else if (ItemName == "unc") { + return (int)currFemonData.fe_unc; + } else if (ItemName == "video_bitrate" || ItemName == "vbr") { + if (ItemFormat == "" && (ItemExtra == "" || ItemExtra == "0")) { + return (int)currFemonData.video_bitrate; + } else { + double divisor = (ItemExtra == "") ? 1.0 : atof(ItemExtra.c_str()); + double value = currFemonData.video_bitrate; + if (ItemFormat == "") { + return (int)(value / divisor); + } else { + char buf[20]; + snprintf(buf, 19, ItemFormat.c_str(), (value / divisor)); + return buf; + } + } + } else if (ItemName == "audio_bitrate" || ItemName == "abr") { + if (ItemFormat == "" && (ItemExtra == "" || ItemExtra == "0")) { + return (int)currFemonData.audio_bitrate; + } else { + double divisor = (ItemExtra == "") ? 1 : atof(ItemExtra.c_str()); + double value = currFemonData.audio_bitrate; + if (ItemFormat == "") { + return (int)(value / divisor); + } else { + char buf[20]; + snprintf(buf, 19, ItemFormat.c_str(), (value / divisor)); + return buf; + } + } + } else if (ItemName == "dolby_bitrate" || ItemName == "dbr") { + if (ItemFormat == "" && (ItemExtra == "" || ItemExtra == "0")) { + return (int)currFemonData.dolby_bitrate; + } else { + double divisor = (ItemExtra == "") ? 1 : atof(ItemExtra.c_str()); + double value = currFemonData.dolby_bitrate; + if (ItemFormat == "") { + return (int)(value / divisor); + } else { + char buf[20]; + snprintf(buf, 19, ItemFormat.c_str(), (value / divisor)); + return buf; + } + } + } + } + } + + return ""; +} + + + +/* async. check event updates for services from other plugins */ +/* only sets flags but does NOT update display output */ +bool cGraphLCDService::NeedsUpdate(uint64_t CurrentTime) +{ + //mutex.Lock(); + + /*radioActive = false;*/ radioChanged = false; + /*lcrActive = false;*/ lcrChanged = false; + /*femonActive = false;*/ femonChanged = false; + + cPlugin *p = NULL; + + // Radiotext + // only ask if radio-services are defined in the skin and min. request delay exceeded + if (radioUse && ((CurrentTime-radioLastChange) >= (uint64_t)radioUpdateDelay)) { + radioLastChange = CurrentTime; + p = cPluginManager::CallFirstService("RadioTextService-v1.0", NULL); + if (p) { + radioActive = true; + if (cPluginManager::CallFirstService("RadioTextService-v1.0", &checkRTSData)) { + if ( + (currRTSData.rds_info != checkRTSData.rds_info) || + (currRTSData.rds_pty != checkRTSData.rds_pty) || + (strcmp(currRTSData.rds_text, checkRTSData.rds_text) != 0) || + (strcmp(currRTSData.rds_title, checkRTSData.rds_title) != 0) || + (strcmp(currRTSData.rds_artist, checkRTSData.rds_artist) != 0) + ) + { + currRTSData.rds_info = checkRTSData.rds_info; + currRTSData.rds_pty = checkRTSData.rds_pty; + currRTSData.rds_text = checkRTSData.rds_text; + currRTSData.rds_title = checkRTSData.rds_title; + currRTSData.rds_artist = checkRTSData.rds_artist; + currRTSData.title_start= checkRTSData.title_start; + + radioChanged = true; + } + } + } + } + + // Lcr + // only ask if lcr-services are defined in the skin and min. request delay exceeded + if (lcrUse && ((CurrentTime-lcrLastChange) >= (uint64_t)lcrUpdateDelay)) { + lcrLastChange = CurrentTime; + p = cPluginManager::CallFirstService("LcrService-v1.0", NULL); + if (p) { + lcrActive = true; + if (cPluginManager::CallFirstService("LcrService-v1.0", &checkLcrData)) { + if ( + (strcmp(currLcrData.destination, checkLcrData.destination) != 0) || + (strcmp(currLcrData.price, checkLcrData.price) != 0) || + (strcmp(currLcrData.pulse, checkLcrData.pulse) != 0) + ) + { + currLcrData.destination = checkLcrData.destination; + currLcrData.price = checkLcrData.price; + currLcrData.pulse = checkLcrData.pulse; + + lcrChanged = true; + } + } + } + } + + + // femon + // only ask if femon-services are defined in the skin and min. request delay exceeded + if (femonUse && ((CurrentTime-femonLastChange) >= (uint64_t)femonUpdateDelay)) { + femonLastChange = CurrentTime; + p = cPluginManager::CallFirstService("FemonService-v1.0", NULL); + if (p) { +#ifdef GRAPHLCD_SERVICE_FEMON_VALID + femonVersionChecked = femonVersionValid = true; +#else + // nota bene: femon version <= 1.2.x will not make it until here because of a 2nd bug in femon in these versions + if (!femonVersionChecked) { // only execute this check once + std::string version = p->Version(); + size_t mstart = 0; + size_t mend = std::string::npos; + int numval = 0; + + if ((mend = version.find(".", mstart)) != std::string::npos) { + numval = atoi(version.substr(mstart, mend-mstart).c_str()); + if (numval > 1) { + femonVersionValid = true; + } else if (numval == 1) { // version 1.x.x + mstart = mend + 1; + if ((mend = version.find(".", mstart)) != std::string::npos) { + numval = atoi(version.substr(mstart, mend-mstart).c_str()); + if (numval <= 6) { // version <= 1.6.x + isyslog("graphlcd plugin: femon <= 1.7.7 requires a patch prior to be usable with graphlcd.\n"); + isyslog("graphlcd plugin: see README for further instructions.\n"); + } else if (numval == 7) { + mstart = mend + 1; + numval = atoi(version.substr(mstart).c_str()); // ignore trailing characters + if (numval <= 7) { + isyslog("graphlcd plugin: femon <= 1.7.7 requires a patch prior to be usable with graphlcd.\n"); + isyslog("graphlcd plugin: see README for further instructions.\n"); + } else { // version >= 1.7.8: ok + femonVersionValid = true; + } + } else { // version >= 1.8.x: ok + femonVersionValid = true; + } + } else { + isyslog("graphlcd plugin: unable to decode version information of femon.\n"); + } + } else { + isyslog("graphlcd plugin: unable to decode version information of femon.\n"); + } + } + femonVersionChecked = true; + } +#endif /* GRAPHLCD_SERVICE_FEMON_VALID */ + + if (femonVersionValid) { + femonActive = true; + if (cPluginManager::CallFirstService("FemonService-v1.0", &checkFemonData)) { + if ( +#if 0 + (strcmp(currFemonData.fe_name, checkFemonData.fe_name) != 0) || + (strcmp(currFemonData.fe_status, checkFemonData.fe_status) != 0) || +#endif + (currFemonData.fe_signal != checkFemonData.fe_signal) || + (currFemonData.fe_ber != checkFemonData.fe_ber) || + (currFemonData.fe_unc != checkFemonData.fe_unc) || + (currFemonData.video_bitrate != checkFemonData.video_bitrate) || + (currFemonData.audio_bitrate != checkFemonData.audio_bitrate) || + (currFemonData.dolby_bitrate != checkFemonData.dolby_bitrate) + ) + { + currFemonData.fe_name = checkFemonData.fe_name; + currFemonData.fe_status = checkFemonData.fe_status; + currFemonData.fe_snr = checkFemonData.fe_snr; + currFemonData.fe_signal = checkFemonData.fe_signal; + currFemonData.fe_ber = checkFemonData.fe_ber; + currFemonData.fe_unc = checkFemonData.fe_unc; + currFemonData.video_bitrate = checkFemonData.video_bitrate; + currFemonData.audio_bitrate = checkFemonData.audio_bitrate; + currFemonData.dolby_bitrate = checkFemonData.dolby_bitrate; + + femonChanged = true; + } + } + } + } + } + + //mutex.Unlock(); + return (radioChanged || lcrChanged || femonChanged); +} diff --git a/service.h b/service.h new file mode 100644 index 0000000..1248af5 --- /dev/null +++ b/service.h @@ -0,0 +1,87 @@ +/** + * GraphLCD plugin for the Video Disk Recorder + * + * service.h - class for events from external services + * + * (c) 2010 Wolfgang Astleitner <mrwastl AT users sourceforge net> + **/ + +#ifndef _GRAPHLCD_SERVICE_H_ +#define _GRAPHLCD_SERVICE_H_ + +#include <glcdskin/type.h> + +#include <string> +#include <vdr/plugin.h> + +#include <vector> // req. for state.h +#include "state.h" + +// Radiotext +struct RadioTextService_v1_0 { + int rds_info; + int rds_pty; + char *rds_text; + char *rds_title; + char *rds_artist; + struct tm *title_start; +}; + +// LcrData +struct LcrService_v1_0 { + cString destination; + cString price; + cString pulse; +}; + +// Femon +struct FemonService_v1_0 { + cString fe_name; + cString fe_status; + uint16_t fe_snr; + uint16_t fe_signal; + uint32_t fe_ber; + uint32_t fe_unc; + double video_bitrate; + double audio_bitrate; + double dolby_bitrate; +}; + + + +class cGraphLCDService +{ +private: + //cMutex mutex; + cGraphLCDState * mState; + + RadioTextService_v1_0 checkRTSData, currRTSData; + LcrService_v1_0 checkLcrData, currLcrData; + FemonService_v1_0 checkFemonData, currFemonData; + /* __Changed = data has been changed */ + /* __Active = plugin/service is available and active */ + /* __Use = service is requested in skin (don't call services that wouldn't be used anyway) */ + bool radioChanged, radioActive, radioUse; + bool lcrChanged, lcrActive, lcrUse; + bool femonChanged, femonActive, femonUse; + // timestamp of last service update request + uint64_t radioLastChange, lcrLastChange, femonLastChange; + // min. delay between two service update requests + int radioUpdateDelay, lcrUpdateDelay, femonUpdateDelay; + + // check if femon version <= 1.7.7 + bool femonVersionChecked, femonVersionValid; + +//protected: + +public: + cGraphLCDService(cGraphLCDState * state); + virtual ~cGraphLCDService(); + + bool ServiceIsAvailable(const std::string & Name); + void SetServiceUpdateDelay(const std::string & Name, int delay); + bool NeedsUpdate(uint64_t CurrentTime); + GLCD::cType GetItem(const std::string & ServiceName, const std::string & Item); +}; + +#endif diff --git a/skinconfig.c b/skinconfig.c index f99adb9..8537eaf 100644 --- a/skinconfig.c +++ b/skinconfig.c @@ -17,11 +17,12 @@ #include "display.h" #include "state.h" #include "skinconfig.h" +#include "service.h" typedef enum _eTokenId { - // current channel - tokPrivateChannelStart, + // current channel + tokPrivateChannelStart, tokChannelNumber, tokChannelName, tokChannelShortName, @@ -42,10 +43,10 @@ typedef enum _eTokenId tokChannelAlias, tokPrivateChannelEnd, - tokPrivateRecordingStart, - tokIsRecording, - tokRecordings, - tokPrivateRecordingEnd, + tokPrivateRecordingStart, + tokIsRecording, + tokRecordings, + tokPrivateRecordingEnd, // present event tokPrivatePresentStart, @@ -115,7 +116,7 @@ typedef enum _eTokenId tokButtonGreen, tokButtonYellow, tokButtonBlue, - tokPrivateOsdEnd, + tokPrivateOsdEnd, tokDateTime, tokConfigPath, @@ -135,9 +136,14 @@ typedef enum _eTokenId tokBrightnessActive, tokBrightnessIdle, tokBrightnessDelay, - tokPrivateSettingEnd, + // external services + tokPrivateServiceStart, + tokServiceIsAvailable, + tokServiceItem, + tokPrivateServiceEnd, + tokCountToken } eTokenId; @@ -164,10 +170,10 @@ static const std::string Tokens[tokCountToken] = "ChannelAlias", "privateChannelEnd", - "privateRecordingStart", - "IsRecording", - "Recordings", - "privateRecordingEnd", + "privateRecordingStart", + "IsRecording", + "Recordings", + "privateRecordingEnd", "privatePresentStart", "PresentValid", @@ -254,8 +260,13 @@ static const std::string Tokens[tokCountToken] = "BrightnessActive", "BrightnessIdle", "BrightnessDelay", + "privateSettingEnd", - "privateSettingEnd" + // external services + "privateServiceStart", + "ServiceIsAvailable", + "ServiceItem", + "privateServiceEnd" }; cGraphLCDSkinConfig::cGraphLCDSkinConfig(const cGraphLCDDisplay * Display, const std::string & CfgPath, const std::string & SkinsPath, const std::string & SkinName, cGraphLCDState * State) @@ -641,6 +652,36 @@ GLCD::cType cGraphLCDSkinConfig::GetToken(const GLCD::tSkinToken & Token) break; } } + else if (Token.Id > tokPrivateServiceStart && Token.Id < tokPrivateServiceEnd) + { + cGraphLCDService * s = (cGraphLCDService*)mDisplay->GetServiceObject(); + switch (Token.Id) + { + case tokServiceIsAvailable: { + if (Token.Attrib.Text == "") + return false; + + return s->ServiceIsAvailable(Token.Attrib.Text); + } + break; + case tokServiceItem: { + size_t found = Token.Attrib.Text.find(","); + std::string ServiceName = ""; + std::string ItemName = ""; + + if (found != std::string::npos) { + ServiceName = Token.Attrib.Text.substr(0, found); + ItemName = Token.Attrib.Text.substr(found+1); + } else { + ServiceName = Token.Attrib.Text; + } + return s->GetItem(ServiceName, ItemName); + } + break; + default: + break; + } + } else { switch (Token.Id) @@ -724,6 +765,12 @@ int cGraphLCDSkinConfig::GetTabPosition(int Index, int MaxWidth, const GLCD::cFo return 0; } +uint64_t cGraphLCDSkinConfig::Now(void) +{ + return cTimeMs::Now(); +} + + void cGraphLCDSkinConfig::SetMenuClear() { mTabs.clear(); diff --git a/skinconfig.h b/skinconfig.h index 26ccb7c..97bde72 100644 --- a/skinconfig.h +++ b/skinconfig.h @@ -37,6 +37,7 @@ public: virtual GLCD::cType GetToken(const GLCD::tSkinToken & Token); virtual int GetTokenId(const std::string & Name); virtual int GetTabPosition(int Index, int MaxWidth, const GLCD::cFont & Font); + virtual uint64_t Now(void); const std::string & SkinName(void) const { return mSkinName; } }; @@ -17,7 +17,6 @@ #include <vdr/eitscan.h> #include <vdr/i18n.h> -#include <vdr/plugin.h> cGraphLCDState::cGraphLCDState(cGraphLCDDisplay * Display) @@ -74,12 +73,6 @@ cGraphLCDState::cGraphLCDState(cGraphLCDDisplay * Display) mVolume.value = -1; mVolume.lastChange = 0; - /* change flags for RDS and LCR services */ - rtsChanged = false; - rtsActive = false; - lcrChanged = false; - lcrActive = false; - SetChannel(cDevice::CurrentChannel()); } @@ -650,8 +643,6 @@ void cGraphLCDState::UpdateChannelInfo(void) void cGraphLCDState::UpdateEventInfo(void) { - bool ptitle = false; - mutex.Lock(); const cEvent * present = NULL, * following = NULL; cSchedulesLock schedulesLock; @@ -696,7 +687,6 @@ void cGraphLCDState::UpdateEventInfo(void) mPresent.title = ""; if (present->Title()) { mPresent.title = present->Title(); - ptitle = true; } mPresent.shortText = ""; if (present->ShortText()) @@ -725,31 +715,6 @@ void cGraphLCDState::UpdateEventInfo(void) } } - /* get events from add. services (if activated) */ - if (rtsActive) { - if (currRTSData.rds_info == 2 && strstr(currRTSData.rds_title, "---") == NULL) { - char rtpinfo[2][65], rtstr[140]; - strcpy(rtpinfo[0], currRTSData.rds_title); - strcpy(rtpinfo[1], currRTSData.rds_artist); - sprintf(rtstr, "%02d:%02d %s | %s", currRTSData.title_start->tm_hour, currRTSData.title_start->tm_min, trim(((std::string)(rtpinfo[0]))).c_str(), trim(((std::string)(rtpinfo[1]))).c_str()); - ptitle ? mPresent.shortText = rtstr : mPresent.title = rtstr; - } else if (currRTSData.rds_info > 0) { - char rtstr[65]; - strcpy(rtstr, currRTSData.rds_text); - ptitle ? mPresent.shortText = trim(rtstr) : mPresent.title = trim(rtstr); - } - } else if (lcrActive && lcrChanged) { - if ( strstr( currLcrData.destination, "---" ) == NULL ) { - char lcrStringParts[3][25], lcrString[100]; - strcpy( lcrStringParts[0], (const char *)currLcrData.destination ); - strcpy( lcrStringParts[1], (const char *)currLcrData.price ); - strcpy( lcrStringParts[2], (const char *)currLcrData.pulse ); - sprintf(lcrString, "%s | %s", trim((std::string)(lcrStringParts[1])).c_str(), trim((std::string)(lcrStringParts[2])).c_str()); - mPresent.title = trim(lcrStringParts[0]); - mPresent.shortText = trim(lcrString); - } - } - mutex.Unlock(); } @@ -908,65 +873,3 @@ bool cGraphLCDState::ShowMessage() } -/* async. check event updates for services from other plugins */ -/* only sets flags but does NOT update display output */ -bool cGraphLCDState::CheckServiceEventUpdate(void) -{ - mutex.Lock(); - - rtsChanged = false; - lcrChanged = false; - rtsActive = false; - lcrActive = false; - - // get&display Radiotext - cPlugin *p; - p = cPluginManager::CallFirstService("RadioTextService-v1.0", NULL); - if (p) { - rtsActive = true; - if (cPluginManager::CallFirstService("RadioTextService-v1.0", &checkRTSData)) { - if ( - (currRTSData.rds_info != checkRTSData.rds_info) || - (currRTSData.rds_pty != checkRTSData.rds_pty) || - (strcmp(currRTSData.rds_text, checkRTSData.rds_text) != 0) || - (strcmp(currRTSData.rds_title, checkRTSData.rds_title) != 0) || - (strcmp(currRTSData.rds_artist, checkRTSData.rds_artist) != 0) - ) - { - currRTSData.rds_info = checkRTSData.rds_info; - currRTSData.rds_pty = checkRTSData.rds_pty; - currRTSData.rds_text = checkRTSData.rds_text; - currRTSData.rds_title = checkRTSData.rds_title; - currRTSData.rds_artist = checkRTSData.rds_artist; - currRTSData.title_start= checkRTSData.title_start; - - rtsChanged = true; - } - } - } - - - // get&display LcrData - p = cPluginManager::CallFirstService("LcrService-v1.0", NULL); - if (p) { - lcrActive = true; - if (cPluginManager::CallFirstService("LcrService-v1.0", &checkLcrData)) { - if ( - (strcmp(currLcrData.destination, checkLcrData.destination) != 0) || - (strcmp(currLcrData.price, checkLcrData.price) != 0) || - (strcmp(currLcrData.pulse, checkLcrData.pulse) != 0) - ) - { - currLcrData.destination = checkLcrData.destination; - currLcrData.price = checkLcrData.price; - currLcrData.pulse = checkLcrData.pulse; - - lcrChanged = true; - } - } - } - mutex.Unlock(); - return (rtsChanged || lcrChanged); -} - - @@ -93,23 +93,6 @@ struct tVolumeState uint64_t lastChange; }; -// Radiotext -struct RadioTextService_v1_0 { - int rds_info; - int rds_pty; - char *rds_text; - char *rds_title; - char *rds_artist; - struct tm *title_start; -}; - -// LcrData -struct LcrService_v1_0 { - cString destination; - cString price; - cString pulse; -}; - class cGraphLCDDisplay; class cGraphLCDState : public cStatus @@ -129,11 +112,6 @@ private: tOsdState mOsd; tVolumeState mVolume; - RadioTextService_v1_0 checkRTSData, currRTSData; - LcrService_v1_0 checkLcrData, currLcrData; - bool rtsChanged, rtsActive; - bool lcrChanged, lcrActive; - void SetChannel(int ChannelNumber); void UpdateChannelInfo(void); void UpdateEventInfo(void); @@ -168,8 +146,6 @@ public: tOsdState GetOsdState(); tVolumeState GetVolumeState(); bool ShowMessage(); - - bool CheckServiceEventUpdate(); }; #endif |