/* Neutrino graphlcd daemon thread (C) 2012-2014 by martii 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "glcd.h" #include "analogclock.h" #include "digitalclock.h" #include "simpleclock.h" #include "weather.h" #include "zlib.h" #include "png.h" #include "jpeglib.h" #define ICONSEXT ".png" static const char * kDefaultConfigFile = "/etc/graphlcd.conf"; static cGLCD *cglcd = NULL; extern CRemoteControl *g_RemoteControl; extern CPictureViewer * g_PicViewer; cGLCD::cGLCD() { lcd = NULL; Logo = ""; Channel = "Neutrino"; Epg = std::string(g_info.hw_caps->boxvendor) + " " + std::string(g_info.hw_caps->boxname); sem_init(&sem, 0, 1); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init(&mutex, &attr); channelLocked = false; timeLocked = false; durationLocked = false; startLocked = false; endLocked = false; recLocked = false; muteLocked = false; tsLocked = false; ecmLocked = false; timerLocked = false; ddLocked = false; txtLocked = false; subLocked = false; camLocked = false; doRescan = false; doStandby = false; doStandbyTime = false; doStandbyWeather = false; doShowVolume = false; doShowLcdIcon = false; doSuspend = false; doExit = false; doMirrorOSD = false; fontsize_channel = 0; fontsize_epg = 0; fontsize_time = 0; fontsize_duration = 0; fontsize_start = 0; fontsize_end = 0; fontsize_smalltext = 0; fonts_initialized = false; ismediaplayer = false; doScrollChannel = false; doScrollEpg = false; percent_channel = 0; percent_time = 0; percent_duration = 0; percent_start = 0; percent_end = 0; percent_smalltext = 0; percent_epg = 0; percent_bar = 0; percent_logo = 0; percent_logo_width = 0; power_state = 1; Scale = 0; bitmap = NULL; blitFlag = true; timeout_cnt = 0; locked_countdown = false; time_thread_started = false; config_mode = false; cglcd = this; if (!g_settings.glcd_enable) doSuspend = true; if (pthread_create (&thrGLCD, 0, cGLCD::Run, this) != 0 ) fprintf(stderr, "ERROR: pthread_create(cGLCD::Init)\n"); if (pthread_create (&thrTimeThread, 0, cGLCD::TimeThread, this) != 0 ) fprintf(stderr, "ERROR: pthread_create(cGLCD::TimeThread)\n"); InitAnalogClock(); InitDigitalClock(); InitSimpleClock(); Update(); } void cGLCD::Lock(void) { if (cglcd) { pthread_mutex_lock(&cglcd->mutex); } } void cGLCD::Unlock(void) { if (cglcd) { pthread_mutex_unlock(&cglcd->mutex); } } cGLCD::~cGLCD() { Suspend(); cglcd = NULL; if (lcd) { lcd->DeInit(); delete lcd; } sem_destroy(&sem); pthread_mutex_destroy(&mutex); } cGLCD *cGLCD::getInstance() { if (!cglcd) cglcd = new cGLCD; return cglcd; } uint32_t cGLCD::ColorConvert3to1(uint32_t red, uint32_t green, uint32_t blue) { unsigned int color_red_tmp = (static_cast(red) * 2.55) + 1; unsigned int color_green_tmp = (static_cast(green) * 2.55) + 1; unsigned int color_blue_tmp = (static_cast(blue) * 2.55) + 1; uint32_t color = 0xff; color <<= 8; color |= color_red_tmp; color <<= 8; color |= color_green_tmp; color <<= 8; color |= color_blue_tmp; return color; } void cGLCD::Exec() { SNeutrinoGlcdTheme &t = g_settings.glcd_theme; if (!lcd) return; bitmap->Clear(ColorConvert3to1(t.glcd_background_color_red, t.glcd_background_color_green, t.glcd_background_color_blue)); if (Channel.compare("Neutrino") == 0) { if (imageShow(DATADIR "/neutrino/icons/start.jpg", 0, 0, 0, 0, false, true, true, false, false)) { GLCD::cFont font_tmp; int fw = font_epg.Width(Epg); fw = (fw == 0) ? 1: fw; font_tmp.LoadFT2(t.glcd_font, "UTF-8", fontsize_epg * bitmap->Width() / fw); fw = font_tmp.Width(Epg); int fh = font_tmp.Height(Epg); drawText(std::max(2,(bitmap->Width() - fw)/2), std::max(2,(bitmap->Height() - fh)/2), bitmap->Width(), fw, Epg, &font_tmp, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, 0, ALIGN_NONE); lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(true); } else { cglcd->bitmap->Clear(ColorConvert3to1(t.glcd_background_color_red, t.glcd_background_color_green, t.glcd_background_color_blue)); cglcd->lcd->Refresh(true); } return; } if (doStandbyTime || doStandbyWeather) { if (t.glcd_standby_clock == CLOCK_ANALOG) { ShowAnalogClock(tm->tm_hour, tm->tm_min, tm->tm_sec, bitmap->Width()/2, bitmap->Height()/2); } else if (t.glcd_standby_clock == CLOCK_DIGITAL) { ShowDigitalClock(tm->tm_hour, tm->tm_min); } else if (t.glcd_standby_clock > CLOCK_OFF) { ShowSimpleClock(strftime("%H:%M", tm), t.glcd_standby_clock); } if (t.glcd_standby_weather == 1 && t.glcd_standby_clock != CLOCK_ANALOG) { ShowWeather(true); } lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(false); return; } if (t.glcd_background_image != "") imageShow(t.glcd_background_image, 0, 0, 0, 0, false, true, true, false, false); if (t.glcd_weather) ShowWeather(false); switch (CAudioPlayer::getInstance()->getState()) { case CBaseDec::REV: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_REW ICONSEXT; break; case CBaseDec::FF: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_FF ICONSEXT; break; case CBaseDec::PAUSE: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_PAUSE ICONSEXT; break; case CBaseDec::PLAY: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_PLAY ICONSEXT; break; default: ismediaplayer = false; ; } switch (CMoviePlayerGui::getInstance().getState()) { case CMoviePlayerGui::REW: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_REW ICONSEXT; break; case CMoviePlayerGui::FF: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_FF ICONSEXT; break; case CMoviePlayerGui::PAUSE: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_PAUSE ICONSEXT; break; case CMoviePlayerGui::PLAY: ismediaplayer = true; Logo = ICONSDIR "/" NEUTRINO_ICON_PLAY ICONSEXT; break; default: ismediaplayer = false; ; } switch (CRecordManager::getInstance()->GetRecordMode()) { case CRecordManager::RECMODE_REC_TSHIFT: recLocked = true; tsLocked = true; break; case CRecordManager::RECMODE_REC: recLocked = true; break; case CRecordManager::RECMODE_TSHIFT: tsLocked = true; break; default: recLocked = false; tsLocked = false; break; } int icon_start_width = 0, icon_start_height = 0; g_PicViewer->getSize(Logo.c_str(), &icon_start_width, &icon_start_height); if (t.glcd_logo && percent_logo && showImage(channel_id, Channel, t.glcd_logo_x_position+(bitmap->Width()-(percent_logo_width * bitmap->Width()/100))/2, t.glcd_logo_y_position, percent_logo_width * bitmap->Width()/100, percent_logo * bitmap->Height()/100, true, false)) { doScrollChannel = false; scrollChannelSkip = 0; } else if (percent_logo && icon_start_width && icon_start_height && doShowLcdIcon && showImage(Logo, icon_start_width, icon_start_height, t.glcd_logo_x_position, t.glcd_logo_y_position, bitmap->Width(), percent_logo * bitmap->Height()/100, true, false)) { doScrollChannel = false; scrollChannelSkip = 0; } else if (percent_channel) { if (ChannelWidth) { if (scrollChannelForward) { if (ChannelWidth - scrollChannelSkip < bitmap->Width()) scrollChannelForward = false; } else if (scrollChannelSkip <= 0) { scrollChannelSkip = 0; doScrollChannel = false; } drawText(t.glcd_channel_x_position + scrollChannelOffset, t.glcd_channel_y_position, bitmap->Width(), ChannelWidth, Channel, &font_channel, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, scrollChannelSkip, t.glcd_channel_align); if (scrollChannelOffset > 0) scrollChannelOffset -= g_settings.glcd_scroll_speed; if (scrollChannelOffset < 0) scrollChannelOffset = 0; if (scrollChannelOffset == 0) { if (scrollChannelForward) scrollChannelSkip += g_settings.glcd_scroll_speed; else scrollChannelSkip -= g_settings.glcd_scroll_speed; } } } if (percent_epg) { if (EpgWidth) { if (scrollEpgForward) { if (EpgWidth - scrollEpgSkip < bitmap->Width()) scrollEpgForward = false; } else if (scrollEpgSkip <= 0) { scrollEpgSkip = 0; doScrollEpg = false; } drawText(t.glcd_epg_x_position + scrollEpgOffset, t.glcd_epg_y_position, bitmap->Width(), EpgWidth, Epg, &font_epg, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, scrollEpgSkip, t.glcd_epg_align); if (scrollEpgOffset > 0) scrollEpgOffset -= g_settings.glcd_scroll_speed; if (scrollEpgOffset < 0) scrollEpgOffset = 0; if (scrollEpgOffset == 0) { if (scrollEpgForward) scrollEpgSkip += g_settings.glcd_scroll_speed; else scrollEpgSkip -= g_settings.glcd_scroll_speed; } } } if (percent_bar && t.glcd_progressbar) { showProgressBarBorder( t.glcd_progressbar_x_position, t.glcd_progressbar_y_position, t.glcd_progressbar_width, t.glcd_progressbar_y_position + t.glcd_progressbar_percent, Scale, GLCD::cColor::Gray, ColorConvert3to1(t.glcd_progressbar_color_red, t.glcd_progressbar_color_green, t.glcd_progressbar_color_blue) ); } if (percent_time && t.glcd_time) { Lock(); Time = strftime("%H:%M", tm); TimeWidth = font_time.Width(Time); Unlock(); drawText(t.glcd_time_x_position, t.glcd_time_y_position, bitmap->Width() - 1, TimeWidth, Time, &font_time, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, 0, t.glcd_time_align); } if (percent_duration && t.glcd_duration) { Lock(); Duration = stagingDuration; DurationWidth = font_duration.Width(Duration); Unlock(); drawText(t.glcd_duration_x_position, t.glcd_duration_y_position, bitmap->Width() - 1, DurationWidth, Duration, &font_duration, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, 0, t.glcd_duration_align); } if (percent_start && t.glcd_start) { Lock(); Start = stagingStart; StartWidth = font_start.Width(Start); Unlock(); drawText(t.glcd_start_x_position, t.glcd_start_y_position, bitmap->Width() - 1, StartWidth, Start, &font_start, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, 0, t.glcd_start_align); } if (percent_end && t.glcd_end) { Lock(); End = stagingEnd; EndWidth = font_end.Width(End); Unlock(); drawText(t.glcd_end_x_position, t.glcd_end_y_position, bitmap->Width() - 1, EndWidth, End, &font_end, ColorConvert3to1(t.glcd_foreground_color_red, t.glcd_foreground_color_green, t.glcd_foreground_color_blue), GLCD::cColor::Transparent, true, 0, t.glcd_end_align); } if (percent_smalltext && !doStandby) { Lock(); SmalltextWidth = font_smalltext.Width(Smalltext); Unlock(); if (access("/tmp/ecm.info", F_OK) == 0) { struct stat buf; stat("/tmp/ecm.info", &buf); if (buf.st_size > 0) ecmLocked = true; else ecmLocked = false; } std::string smalltext; if (t.glcd_icon_rec_x_position) { smalltext = "REC"; if (recLocked) { drawText(t.glcd_icon_rec_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Red, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_rec_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_mute_x_position) { smalltext = "MUTE"; if (muteLocked) { drawText(t.glcd_icon_mute_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Red, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_mute_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_ts_x_position) { smalltext = "TS"; if (tsLocked) { drawText(t.glcd_icon_ts_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Yellow, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_ts_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_ecm_x_position) { smalltext = "ECM"; if (ecmLocked) { drawText(t.glcd_icon_ecm_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Green, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_ecm_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_timer_x_position) { smalltext = "TIMER"; if (timerLocked) { drawText(t.glcd_icon_timer_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Yellow, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_timer_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_dd_x_position) { smalltext = "DD"; if (ddLocked) { drawText(t.glcd_icon_dd_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Green, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_dd_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } if (t.glcd_icon_txt_x_position) { if (ismediaplayer) { smalltext = "SUB"; if (subLocked) { drawText(t.glcd_icon_txt_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Green, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_txt_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } else { smalltext = "TXT"; if (txtLocked) { drawText(t.glcd_icon_txt_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Green, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_txt_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } } if (t.glcd_icon_cam_x_position) { smalltext = "CAM"; if (camLocked) { drawText(t.glcd_icon_cam_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Green, GLCD::cColor::Transparent, true, 0, 0); } else { drawText(t.glcd_icon_cam_x_position, t.glcd_icons_y_position, bitmap->Width() - 1, SmalltextWidth, smalltext, &font_smalltext, GLCD::cColor::Gray, GLCD::cColor::Transparent, true, 0, 0); } } } lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(false); } void cGLCD::updateFonts() { SNeutrinoGlcdTheme &t = g_settings.glcd_theme; percent_logo = std::min(t.glcd_logo_percent, 100); percent_logo_width = std::min(t.glcd_logo_width_percent, 100); percent_channel = std::min(t.glcd_channel_percent, 100); percent_epg = std::min(t.glcd_epg_percent, 100); percent_bar = std::min(t.glcd_progressbar_percent, 100); percent_time = std::min(t.glcd_time_percent, 100); percent_duration = std::min(t.glcd_duration_percent, 100); percent_start = std::min(t.glcd_start_percent, 100); percent_end = std::min(t.glcd_end_percent, 100); percent_smalltext = std::min(t.glcd_icons_percent, 100); // calculate height int fontsize_channel_new = percent_channel * cglcd->lcd->Height() / 100; int fontsize_epg_new = percent_epg * cglcd->lcd->Height() / 100; int fontsize_time_new = percent_time * cglcd->lcd->Height() / 100; int fontsize_duration_new = percent_duration * cglcd->lcd->Height() / 100; int fontsize_start_new = percent_start * cglcd->lcd->Height() / 100; int fontsize_end_new = percent_end * cglcd->lcd->Height() / 100; int fontsize_smalltext_new = percent_smalltext * cglcd->lcd->Height() / 100; if (!fonts_initialized || (fontsize_channel_new != fontsize_channel)) { fontsize_channel = fontsize_channel_new; if (!font_channel.LoadFT2(t.glcd_font, "UTF-8", fontsize_channel)) { t.glcd_font = g_settings.font_file; font_channel.LoadFT2(t.glcd_font, "UTF-8", fontsize_channel); } } if (!fonts_initialized || (fontsize_epg_new != fontsize_epg)) { fontsize_epg = fontsize_epg_new; if (!font_epg.LoadFT2(t.glcd_font, "UTF-8", fontsize_epg)) { t.glcd_font = g_settings.font_file; font_epg.LoadFT2(t.glcd_font, "UTF-8", fontsize_epg); } } if (!fonts_initialized || (fontsize_time_new != fontsize_time)) { fontsize_time = fontsize_time_new; if (!font_time.LoadFT2(t.glcd_font, "UTF-8", fontsize_time)) { t.glcd_font = g_settings.font_file; font_time.LoadFT2(t.glcd_font, "UTF-8", fontsize_time); } } if (!fonts_initialized || (fontsize_duration_new != fontsize_duration)) { fontsize_duration = fontsize_duration_new; if (!font_duration.LoadFT2(t.glcd_font, "UTF-8", fontsize_duration)) { t.glcd_font = g_settings.font_file; font_duration.LoadFT2(t.glcd_font, "UTF-8", fontsize_duration); } } if (!fonts_initialized || (fontsize_start_new != fontsize_start)) { fontsize_start = fontsize_start_new; if (!font_start.LoadFT2(t.glcd_font, "UTF-8", fontsize_start)) { t.glcd_font = g_settings.font_file; font_start.LoadFT2(t.glcd_font, "UTF-8", fontsize_start); } } if (!fonts_initialized || (fontsize_end_new != fontsize_end)) { fontsize_end = fontsize_end_new; if (!font_end.LoadFT2(t.glcd_font, "UTF-8", fontsize_end)) { t.glcd_font = g_settings.font_file; font_end.LoadFT2(t.glcd_font, "UTF-8", fontsize_end); } } if (!fonts_initialized || (fontsize_smalltext_new != fontsize_smalltext)) { fontsize_smalltext = fontsize_smalltext_new; if (!font_smalltext.LoadFT2(t.glcd_font, "UTF-8", fontsize_smalltext)) { t.glcd_font = g_settings.font_file; font_smalltext.LoadFT2(t.glcd_font, "UTF-8", fontsize_smalltext); } } WeatherUpdateFonts(); fonts_initialized = true; } bool cGLCD::getBoundingBox(uint32_t *buffer, int width, int height, int &bb_x, int &bb_y, int &bb_w, int &bb_h) { if (!width || !height) { bb_x = bb_y = bb_w = bb_h = 0; return false; } int y_min = height; uint32_t *b = buffer; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++, b++) if (*b) { y_min = y; goto out1; } out1: int y_max = y_min; b = buffer + height * width - 1; for (int y = height - 1; y_min < y; y--) for (int x = 0; x < width; x++, b--) if (*b) { y_max = y; goto out2; } out2: int x_min = width; for (int x = 0; x < width; x++) { b = buffer + x + y_min * width; for (int y = y_min; y < y_max; y++, b += width) if (*b) { x_min = x; goto out3; } } out3: int x_max = x_min; for (int x = width - 1; x_min < x; x--) { b = buffer + x + y_min * width; for (int y = y_min; y < y_max; y++, b += width) if (*b) { x_max = x; goto out4; } } out4: bb_x = x_min; bb_y = y_min; bb_w = 1 + x_max - x_min; bb_h = 1 + y_max - y_min; if (bb_x < 0) bb_x = 0; if (bb_y < 0) bb_y = 0; return true; } void* cGLCD::Run(void *arg) { cGLCD *me = (cGLCD *)arg; me->Run(); pthread_exit(NULL); } void cGLCD::CountDown() { if (timeout_cnt > 0) { timeout_cnt--; if (timeout_cnt == 0) { UpdateBrightness(); cglcd->locked_countdown = false; } } } void cGLCD::WakeUp() { int tmp = atoi(g_settings.glcd_brightness_dim_time.c_str()); if (tmp > 0) { timeout_cnt = (unsigned int)tmp; UpdateBrightness(); cglcd->locked_countdown = true; } } void* cGLCD::TimeThread(void *p) { set_threadname("cGLCD:Time"); ((cGLCD *)p)->time_thread_started = true; while (((cGLCD *)p)->time_thread_started) { sleep(1); if (!cglcd->doExit && ( cglcd->locked_countdown == true || cglcd->channelLocked == true || cglcd->timeLocked == true || cglcd->durationLocked == true || cglcd->startLocked == true || cglcd->endLocked == true || cglcd->recLocked == true || cglcd->muteLocked == true || cglcd->tsLocked == true || cglcd->ecmLocked == true || cglcd->timerLocked == true || cglcd->ddLocked == true || cglcd->txtLocked == true || cglcd->camLocked == true || cglcd->doShowVolume == true || cglcd->doMirrorOSD == true )) { cGLCD::getInstance()->CountDown(); } } return NULL; } void cGLCD::Run(void) { SNeutrinoGlcdTheme &t = g_settings.glcd_theme; set_threadname("cGLCD::Run"); if (GLCD::Config.Load(kDefaultConfigFile) == false) { fprintf(stderr, "Error loading config file!\n"); return; } if ((GLCD::Config.driverConfigs.size() < 1)) { fprintf(stderr, "No driver config found!\n"); return; } struct timespec ts; CSectionsdClient::CurrentNextInfo info_CurrentNext; t_channel_id epg_id = -1; channel_id = -1; info_CurrentNext.current_zeit.startzeit = 0; info_CurrentNext.current_zeit.dauer = 0; info_CurrentNext.flags = 0; fonts_initialized = false; bool broken = false; do { if (broken) { #ifdef GLCD_DEBUG fprintf(stderr, "No graphlcd display found ... sleeping for 30 seconds\n"); #endif clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 30; sem_timedwait(&sem, &ts); broken = false; if (doExit) break; if (!g_settings.glcd_enable) continue; } else while ((doSuspend || doStandby || !g_settings.glcd_enable) && !doExit) sem_wait(&sem); if (doExit) break; int warmUp = 10; if ((g_settings.glcd_selected_config < 0) || (g_settings.glcd_selected_config > GetConfigSize() - 1)) g_settings.glcd_selected_config = 0; lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[g_settings.glcd_selected_config].id, &GLCD::Config.driverConfigs[g_settings.glcd_selected_config]); if (!lcd) { #ifdef GLCD_DEBUG fprintf(stderr, "CreateDriver failed.\n"); #endif broken = true; continue; } #ifdef GLCD_DEBUG fprintf(stderr, "CreateDriver succeeded.\n"); #endif if (lcd->Init()) { delete lcd; lcd = NULL; #ifdef GLCD_DEBUG fprintf(stderr, "LCD init failed.\n"); #endif broken = true; continue; } #ifdef GLCD_DEBUG fprintf(stderr, "LCD init succeeded.\n"); #endif lcd->SetBrightness(0); if (!bitmap) bitmap = new GLCD::cBitmap(lcd->Width(), lcd->Height(), ColorConvert3to1(t.glcd_background_color_red, t.glcd_background_color_green, t.glcd_background_color_blue)); UpdateBrightness(); Update(); doMirrorOSD = false; while ((!doSuspend && !doStandby) && !doExit && g_settings.glcd_enable) { if (doMirrorOSD && !doStandbyTime && !doStandbyWeather) { if (blitFlag) { blitFlag = false; bitmap->Clear(GLCD::cColor::Black); ts.tv_sec = 0; // don't wait static CFrameBuffer* fb = CFrameBuffer::getInstance(); static int fb_height = fb->getScreenHeight(true); static uint32_t *fbp = fb->getFrameBufferPointer(); int lcd_width = bitmap->Width(); int lcd_height = bitmap->Height(); #if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE ||BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE unsigned int fb_stride = fb->getStride()/4; if (!showImage(fbp, fb_stride, fb_height, 0, 0, lcd_width, lcd_height, false, false)) { #else static int fb_width = fb->getScreenWidth(true); if (!showImage(fbp, fb_width, fb_height, 0, 0, lcd_width, lcd_height, false, true)) { #endif usleep(500000); } else { lcd->SetScreen(bitmap->Data(), lcd_width, lcd_height); lcd->Refresh(false); } } else usleep(100000); continue; } if (g_settings.glcd_mirror_video && !doStandbyTime && !doStandbyWeather) { #if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE ||BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE lcd->SetMirrorVideo(true); #else char ws[10]; snprintf(ws, sizeof(ws), "%d", bitmap->Width()); const char *bmpShot = "/tmp/glcd-video.bmp"; std::string grab = find_executable("grab"); if (!grab.empty()) my_system(4, grab.c_str(), "-vr", ws, bmpShot); int bw = 0, bh = 0; g_PicViewer->getSize(bmpShot, &bw, &bh); if (bw > 0 && bh > 0) { int lcd_width = bitmap->Width(); int lcd_height = bitmap->Height(); if (!showImage(bmpShot, (uint32_t) bw, (uint32_t) bh, 0, 0, (uint32_t) lcd_width, (uint32_t) lcd_height, false, true)) usleep(1000000); else { lcd->SetScreen(bitmap->Data(), lcd_width, lcd_height); lcd->Refresh(false); } } else usleep(1000000); continue; #endif } #if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE ||BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE else lcd->SetMirrorVideo(false); #endif clock_gettime(CLOCK_REALTIME, &ts); tm = localtime(&ts.tv_sec); updateFonts(); Exec(); clock_gettime(CLOCK_REALTIME, &ts); tm = localtime(&ts.tv_sec); if (warmUp > 0) { ts.tv_sec += 1; warmUp--; } else { ts.tv_sec += 60 - tm->tm_sec; ts.tv_nsec = 0; } if (!doScrollChannel && !doScrollEpg) sem_timedwait(&sem, &ts); while(!sem_trywait(&sem)); if(doRescan || doSuspend || doStandby || doExit) break; if (doShowVolume) { if (ismediaplayer) { Channel = ""; if (Epg.compare(g_Locale->getText(LOCALE_GLCD_VOLUME))) { Epg = g_Locale->getText(LOCALE_GLCD_VOLUME); EpgWidth = font_epg.Width(Epg); doScrollEpg = EpgWidth > bitmap->Width(); scrollEpgSkip = 0; scrollEpgForward = true; if (doScrollEpg) { scrollEpgOffset = bitmap->Width()/4; EpgWidth += scrollEpgOffset; } else scrollEpgOffset = 0; } ChannelWidth = 0; scrollChannelSkip = 0; scrollChannelForward = true; Scale = g_settings.current_volume; //epg_id = -1; } else { Epg = ""; if (Channel.compare(g_Locale->getText(LOCALE_GLCD_VOLUME))) { Channel = g_Locale->getText(LOCALE_GLCD_VOLUME); ChannelWidth = font_channel.Width(Channel); doScrollChannel = ChannelWidth > bitmap->Width(); scrollChannelSkip = 0; scrollChannelForward = true; if (doScrollChannel) { scrollChannelOffset = bitmap->Width()/4; ChannelWidth += scrollChannelOffset; } else scrollChannelOffset = 0; } EpgWidth = 0; scrollEpgSkip = 0; scrollEpgForward = true; Scale = g_settings.current_volume; channel_id = -1; } } else if (channelLocked) { Lock(); if (Epg.compare(stagingEpg)) { Epg = stagingEpg; EpgWidth = font_epg.Width(Epg); doScrollEpg = EpgWidth > bitmap->Width(); scrollEpgSkip = 0; scrollEpgForward = true; if (doScrollEpg) { scrollEpgOffset = bitmap->Width()/4; EpgWidth += scrollEpgOffset; } else scrollChannelOffset = 0; } if (Channel.compare(stagingChannel)) { Channel = stagingChannel; ChannelWidth = font_channel.Width(Channel); doScrollChannel = ChannelWidth > bitmap->Width(); scrollChannelSkip = 0; scrollChannelForward = true; if (doScrollChannel) { scrollChannelOffset = bitmap->Width()/4; ChannelWidth += scrollChannelOffset; } else scrollChannelOffset = 0; } channel_id = -1; Unlock(); } else { CChannelList *channelList = CNeutrinoApp::getInstance ()->channelList; if (!channelList) continue; t_channel_id new_channel_id = channelList->getActiveChannel_ChannelID(); if (!new_channel_id) continue; if ((new_channel_id != channel_id)) { Channel = channelList->getActiveChannelName (); ChannelWidth = font_channel.Width(Channel); epg_id = channelList->getActiveChannel()->getEpgID(); Epg = ""; EpgWidth = 0; Scale = 0; doScrollEpg = false; doScrollChannel = ChannelWidth > bitmap->Width(); scrollChannelForward = true; scrollChannelSkip = 0; if (doScrollChannel) { scrollChannelOffset = bitmap->Width()/4; ChannelWidth += scrollChannelOffset; } else scrollChannelOffset = 0; warmUp = 10; info_CurrentNext.current_name = ""; info_CurrentNext.current_zeit.dauer = 0; } CEitManager::getInstance()->getCurrentNextServiceKey(epg_id & 0xFFFFFFFFFFFFULL, info_CurrentNext); channel_id = new_channel_id; if (info_CurrentNext.current_name.compare(Epg)) { Epg = info_CurrentNext.current_name; EpgWidth = font_epg.Width(Epg); doScrollEpg = EpgWidth > bitmap->Width(); scrollEpgForward = true; scrollEpgSkip = 0; if (doScrollEpg) { scrollEpgOffset = bitmap->Width()/4; EpgWidth += scrollEpgOffset; } else scrollEpgOffset = 0; } if (info_CurrentNext.flags & CSectionsdClient::epgflags::has_current) { if ((info_CurrentNext.current_zeit.dauer > 0) && (info_CurrentNext.current_zeit.dauer < 86400)) { Scale = (ts.tv_sec - info_CurrentNext.current_zeit.startzeit) * 100 / info_CurrentNext.current_zeit.dauer; char tmp_duration[15] = {0}; int total = info_CurrentNext.current_zeit.dauer / 60; int done = (abs(time(NULL) - info_CurrentNext.current_zeit.startzeit) + 30) / 60; int todo = total - done; if ((time(NULL) < info_CurrentNext.current_zeit.startzeit) && todo >= 0) { done = 0; todo = info_CurrentNext.current_zeit.dauer / 60; } snprintf(tmp_duration, sizeof(tmp_duration), "%d/%d", done, total); Duration = stagingDuration = tmp_duration; } if (Scale > 100) Scale = 100; else if (Scale < 0) Scale = 0; char tmp_start[6] = {0}; time_t tmp_start_time = info_CurrentNext.current_zeit.startzeit; tm = localtime(&tmp_start_time); snprintf(tmp_start, sizeof(tmp_start), "%02d:%02d", tm->tm_hour, tm->tm_min); Start = stagingStart = tmp_start; } if (info_CurrentNext.flags & CSectionsdClient::epgflags::has_next) { char tmp_end[6] = {0}; time_t tmp_end_time = info_CurrentNext.next_zeit.startzeit; tm = localtime(&tmp_end_time); snprintf(tmp_end, sizeof(tmp_end), "%02d:%02d", tm->tm_hour, tm->tm_min); End = stagingEnd = tmp_end; } } } if (!g_settings.glcd_enable || doSuspend || doStandby) { // for restart, don't blacken screen bitmap->Clear(GLCD::cColor::Black); lcd->SetBrightness(0); lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(false); } if (doExit) { if (imageShow(DATADIR "/neutrino/icons/shutdown.jpg", 0, 0, 0, 0, false, true, true, false, false)) { lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(false); sleep(1); lcd->SetBrightness(0); } else { bitmap->Clear(GLCD::cColor::Black); lcd->SetBrightness(0); lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height()); lcd->Refresh(false); } return; } if (doRescan) { doRescan = false; Update(); } lcd->DeInit(); delete lcd; lcd = NULL; } while(!doExit); } void cGLCD::Update() { if (cglcd) { sem_post(&cglcd->sem); if (!cglcd->doExit) cGLCD::getInstance()->WakeUp(); } } void cGLCD::StandbyMode(bool b) { SNeutrinoGlcdTheme &t = g_settings.glcd_theme; if (cglcd) { if (t.glcd_standby_clock || t.glcd_standby_weather) { if (t.glcd_standby_clock) cglcd->doStandbyTime = b; else cglcd->doStandbyTime = false; if (t.glcd_standby_weather) cglcd->doStandbyWeather = b; else cglcd->doStandbyWeather = false; cglcd->doStandby = false; } else cglcd->doStandby = b; if (b) { cglcd->doScrollChannel = false; cglcd->doScrollEpg = false; } else { cglcd->doScrollChannel = true; cglcd->doScrollEpg = true; } cglcd->doMirrorOSD = false; cglcd->UpdateBrightness(); cglcd->Update(); } } void cGLCD::ShowVolume(bool b) { if (cglcd) { cglcd->doShowVolume = b; cglcd->Update(); } } void cGLCD::ShowLcdIcon(bool b) { if (cglcd) { cglcd->Lock(); cglcd->doShowLcdIcon = b; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::MirrorOSD(bool b) { if (cglcd) { cglcd->doMirrorOSD = b; cglcd->Update(); } } void cGLCD::Exit() { if (cglcd) { cglcd->doMirrorOSD = false; cglcd->doSuspend = false; cglcd->time_thread_started = false; cglcd->doExit = true; cglcd->Update(); void *res; pthread_join(cglcd->thrGLCD, &res); pthread_join(cglcd->thrTimeThread, NULL); delete cglcd; cglcd = NULL; } } void cGLCD::Respawn() { Exit(); cGLCD::getInstance(); } void cGLCD::Rescan() { doRescan = true; Update(); } void cGLCD::Suspend() { if (cglcd) { cglcd->doSuspend = true; cglcd->Update(); } } void cGLCD::Resume() { if (cglcd) { cglcd->doSuspend = false; cglcd->channelLocked = false; cglcd->Update(); } } void cGLCD::lockChannel(std::string c, std::string e, int s) { if(cglcd) { cglcd->Lock(); cglcd->channelLocked = true; cglcd->stagingChannel = c; cglcd->stagingEpg = e; cglcd->Scale = s; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockChannel(void) { if(cglcd) { cglcd->channelLocked = false; cglcd->Update(); } } void cGLCD::lockTime(std::string t) { if(cglcd) { cglcd->Lock(); cglcd->timeLocked = true; cglcd->stagingTime = t; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockTime(void) { if(cglcd) { cglcd->timeLocked = false; cglcd->Update(); } } void cGLCD::lockDuration(std::string t) { if(cglcd) { cglcd->Lock(); cglcd->durationLocked = true; cglcd->stagingDuration = t; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockDuration(void) { if(cglcd) { cglcd->durationLocked = false; cglcd->Update(); } } void cGLCD::lockStart(std::string t) { if(cglcd) { cglcd->Lock(); cglcd->startLocked = true; cglcd->stagingStart = t; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockStart(void) { if(cglcd) { cglcd->startLocked = false; cglcd->Update(); } } void cGLCD::lockEnd(std::string t) { if(cglcd) { cglcd->Lock(); cglcd->endLocked = true; cglcd->stagingEnd = t; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockEnd(void) { if(cglcd) { cglcd->endLocked = false; cglcd->Update(); } } void cGLCD::lockIcon(int type) { if(cglcd) { cglcd->Lock(); if (type == REC) cglcd->recLocked = true; else if (type == MUTE) cglcd->muteLocked = true; else if (type == TS) cglcd->tsLocked = true; else if (type == ECM) cglcd->ecmLocked = true; else if (type == TIMER) cglcd->timerLocked = true; else if (type == DD) cglcd->ddLocked = true; else if (type == TXT) cglcd->txtLocked = true; else if (type == SUB) cglcd->subLocked = true; else if (type == CAM) cglcd->camLocked = true; cglcd->Unlock(); cglcd->Update(); } } void cGLCD::unlockIcon(int type) { if(cglcd) { if (type == REC) cglcd->recLocked = false; else if (type == MUTE) cglcd->muteLocked = false; else if (type == TS) cglcd->tsLocked = false; else if (type == ECM) cglcd->ecmLocked = false; else if (type == TIMER) cglcd->timerLocked = false; else if (type == DD) cglcd->ddLocked = false; else if (type == TXT) cglcd->txtLocked = false; else if (type == SUB) cglcd->subLocked = false; else if (type == CAM) cglcd->camLocked = false; cglcd->Update(); } } bool cGLCD::showProgressBarBorder(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t scale, uint32_t color_border, uint32_t color_progress) { cglcd->bitmap->DrawRectangle(x1, y1, x1 + (x2 - x1 - 1), y2, color_border, false); if (scale) { cglcd->bitmap->DrawRectangle(x1 + 1, y1 + 1, x1 + (scale * (x2 - x1 - 1) / 100), y2 - 1, color_progress, true); return true; } else return false; } bool cGLCD::showImage(fb_pixel_t *s, uint32_t sw, uint32_t sh, uint32_t dx, uint32_t dy, uint32_t dw, uint32_t dh, bool transp, bool maximize) { int bb_x, bb_y, bb_w, bb_h; if (cglcd->getBoundingBox(s, sw, sh, bb_x, bb_y, bb_w, bb_h) && bb_w && bb_h) { if (!maximize) { if (bb_h * dw > bb_w * dh) { uint32_t dw_new = dh * bb_w / bb_h; dx += (dw - dw_new) >> 1; dw = dw_new; } else { uint32_t dh_new = dw * bb_h / bb_w; dy += (dh - dh_new) >> 1; dh = dh_new; } } for (u_int y = 0; y < dh; y++) { for (u_int x = 0; x < dw; x++) { uint32_t pix = *(s + (y * bb_h / dh + bb_y) * sw + x * bb_w / dw + bb_x); if (!transp || pix) cglcd->bitmap->DrawPixel(x + dx, y + dy, pix); } } return true; } return false; } bool cGLCD::showImage(const std::string & filename, uint32_t sw, uint32_t sh, uint32_t dx, uint32_t dy, uint32_t dw, uint32_t dh, bool transp, bool maximize) { bool res = false; if (!dw || !dh) return res; fb_pixel_t *s = g_PicViewer->getImage(filename, sw, sh); if (s && sw && sh) res = showImage(s, sw, sh, dx, dy, dw, dh, transp, maximize); if (s) free(s); return res; } bool cGLCD::showImage(uint64_t cid, std::string cname, uint32_t dx, uint32_t dy, uint32_t dw, uint32_t dh, bool transp, bool maximize) { std::string logo; int sw, sh; if (g_PicViewer->GetLogoName(cid, cname, logo, &sw, &sh, CPictureViewer::GRAPHLCD, true)) { return showImage(logo, (uint32_t) sw, (uint32_t) sh, dx, dy, dw, dh, transp, maximize); } return false; } bool cGLCD::imageShow(const std::string & filename, uint32_t dx, uint32_t dy, uint32_t dw, uint32_t dh, bool transp, bool maximize, bool clear, bool center_sw, bool center_sh) { bool ret = false; int sw, sh; g_PicViewer->getSize(filename.c_str(), &sw, &sh); if (sw && sh) { if (clear) cglcd->bitmap->Clear(GLCD::cColor::Black); if (maximize) ret = showImage(filename, (uint32_t) sw, (uint32_t) sh, (uint32_t) dx, (uint32_t) dy, (uint32_t) cglcd->bitmap->Width(), (uint32_t) cglcd->bitmap->Height(), transp, false); else if (center_sw || center_sh) { int move_sw = 0; int move_sh = 0; if (center_sw) move_sw = dx - (sw / 2); else move_sw = dx; if (center_sh) move_sh = dy - (sh / 2); else move_sh = dy; if (dw > 0 && dh > 0) ret = showImage(filename, (uint32_t) sw, (uint32_t) sh, (uint32_t) move_sw, (uint32_t) move_sh, (uint32_t) dw, (uint32_t) dh, transp, false); else ret = showImage(filename, (uint32_t) sw, (uint32_t) sh, (uint32_t) move_sw, (uint32_t) move_sh, (uint32_t) sw, (uint32_t) sh, transp, false); } else if (dw > 0 && dh > 0) ret = showImage(filename, (uint32_t) sw, (uint32_t) sh, (uint32_t) dx, (uint32_t) dy, (uint32_t) dw, (uint32_t) dh, transp, false); else ret = showImage(filename, (uint32_t) sw, (uint32_t) sh, (uint32_t) dx, (uint32_t) dy, (uint32_t) sw, (uint32_t) sh, transp, false); } return ret; } bool cGLCD::drawText(int x, int y, int xmax, int text_width, const std::string & text, const GLCD::cFont * font, uint32_t color1, uint32_t color2, bool proportional, int skipPixels, int align) { int z = 0; int offset = 10; // px if (align == ALIGN_NONE) { z = x; } else if (align == ALIGN_LEFT) { z = offset; } else if (align == ALIGN_CENTER) { z = std::max(offset, (bitmap->Width() - text_width) / 2); } else if (align == ALIGN_RIGHT) { z = std::max(offset, (bitmap->Width() - text_width - offset)); } return bitmap->DrawText(z, y, xmax, text, font, color1, color2, proportional, skipPixels); } bool cGLCD::dumpBuffer(fb_pixel_t *s, int format, const char *filename) { int output_bytes = 4; int jpg_quality = 90; int xres = bitmap->Width(); int yres = bitmap->Height(); unsigned char *output = (unsigned char *)s; FILE *fd = fopen(filename, "wr"); if (!fd) return false; if(cglcd) cglcd->Lock(); if (format == BMP) { // write bmp unsigned char hdr[14 + 40]; int i = 0; #define PUT32(x) hdr[i++] = ((x)&0xFF); hdr[i++] = (((x)>>8)&0xFF); hdr[i++] = (((x)>>16)&0xFF); hdr[i++] = (((x)>>24)&0xFF); #define PUT16(x) hdr[i++] = ((x)&0xFF); hdr[i++] = (((x)>>8)&0xFF); #define PUT8(x) hdr[i++] = ((x)&0xFF); PUT8('B'); PUT8('M'); PUT32((((xres * yres) * 3 + 3) &~ 3) + 14 + 40); PUT16(0); PUT16(0); PUT32(14 + 40); PUT32(40); PUT32(xres); PUT32(yres); PUT16(1); PUT16(output_bytes*8); // bits PUT32(0); PUT32(0); PUT32(0); PUT32(0); PUT32(0); PUT32(0); #undef PUT32 #undef PUT16 #undef PUT8 fwrite(hdr, 1, i, fd); int y; for (y=yres-1; y>=0 ; y-=1) fwrite(output + (y * xres * output_bytes), xres * output_bytes, 1, fd); } else if (format == JPG) { const int row_stride = xres * output_bytes; // write jpg if (output_bytes == 3) // swap bgr<->rgb { int y; //#pragma omp parallel for shared(output) for (y = 0; y < yres; y++) { int xres1 = y * xres * 3; int xres2 = xres1 + 2; int x; for (x = 0; x < xres; x++) { int x2 = x * 3; SWAP(output[x2 + xres1], output[x2 + xres2]); } } } else // swap bgr<->rgb and eliminate alpha channel jpgs are always saved with 24bit without alpha channel { int y; //#pragma omp parallel for shared(output) for (y = 0; y < yres; y++) { unsigned char *scanline = output + (y * row_stride); int x; for (x=0; xUnlock(); fclose(fd); return true; } void cGLCD::UpdateBrightness() { int dim_time = atoi(g_settings.glcd_brightness_dim_time.c_str()); int dim_brightness = g_settings.glcd_brightness_dim; bool timeouted = (dim_time > 0) && (timeout_cnt == 0); if (cglcd && cglcd->lcd) { if (timeouted && !cglcd->doStandbyTime && !cglcd->doStandbyWeather) cglcd->lcd->SetBrightness((unsigned int) (dim_brightness)); else cglcd->lcd->SetBrightness((unsigned int) ((cglcd->doStandbyTime || cglcd->doStandbyWeather) ? g_settings.glcd_brightness_standby : g_settings.glcd_brightness)); } } void cGLCD::SetBrightness(unsigned int b) { if (cglcd) cglcd->SetBrightness(b); } void cGLCD::TogglePower() { if (cglcd) { cglcd->power_state = 1 - cglcd->power_state; if (cglcd->power_state) cglcd->Resume(); else cglcd->Suspend(); } } void cGLCD::Blit() { if (cglcd) cglcd->blitFlag = true; } int cGLCD::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t /* data */) { if (msg == NeutrinoMessages::EVT_CURRENTNEXT_EPG) { Update(); return messages_return::handled; } return messages_return::unhandled; } int cGLCD::GetConfigSize() { return (int) GLCD::Config.driverConfigs.size(); } std::string cGLCD::GetConfigName(int driver) { if ((driver < 0) || (driver > GetConfigSize() - 1)) driver = 0; return GLCD::Config.driverConfigs[driver].name; } void cGLCD::AVInputMode(bool b) { if (cglcd) { bool mo = cglcd->doMirrorOSD; if (b) { cglcd->doScrollChannel = false; cglcd->doScrollEpg = false; cglcd->MirrorOSD(false); cglcd->lockChannel(g_info.hw_caps->boxname, g_Locale->getText(LOCALE_MAINMENU_AVINPUTMODE), 0); } else { cglcd->doScrollChannel = true; cglcd->doScrollEpg = true; cglcd->MirrorOSD(mo); cglcd->unlockChannel(); } } }