diff --git a/src/driver/radiotext.cpp b/src/driver/radiotext.cpp index a771f1adb..563be71e2 100644 --- a/src/driver/radiotext.cpp +++ b/src/driver/radiotext.cpp @@ -58,7 +58,7 @@ #include #include #include - +#include #include #include #include @@ -67,6 +67,7 @@ #include "radiotext.h" #include "radiotools.h" +#include rtp_classes rtp_content; @@ -384,19 +385,28 @@ fprintf(stderr, "MEC=0x%02x DSN=0x%02x PSN=0x%02x MEL=%02d STATUS=0x%02x MFL=%02 char *temp; asprintf(&temp, "%s", RT_Text[RT_Index]); if (++rtp_content.rt_Index >= 2*MAX_RTPC) - rtp_content.rt_Index = 0; + rtp_content.rt_Index = 0; asprintf(&rtp_content.radiotext[rtp_content.rt_Index], "%s", rtrim(temp)); free(temp); if (S_Verbose >= 1) - printf("Radiotext[%d]: %s\n", RT_Index, RT_Text[RT_Index]); - RT_Index +=1; if (RT_Index >= S_RtOsdRows) RT_Index = 0; + printf("Radiotext[%d]: %s\n", RT_Index, RT_Text[RT_Index]); + RT_Index +=1; if (RT_Index >= S_RtOsdRows) RT_Index = 0; } RTP_TToggle = 0x03; // Bit 0/1 = Title/Artist RT_MsgShow = true; S_RtOsd = 1; RT_Info = (RT_Info > 0) ? RT_Info : 1; RadioStatusMsg(); - OnAfterDecodeLine(); + + if (!OnAfterDecodeLine.empty()) { + if (!OnAfterDecodeLine.blocked()){ + dprintf(DEBUG_DEBUG, "\033[36m[CRadioText] %s - %d: signal OnAfterDecodeLine contains %d slot(s)\033[0m\n", __func__, __LINE__, (int)OnAfterDecodeLine.size()); + OnAfterDecodeLine(); + } + else{ + dprintf(DEBUG_DEBUG, "\033[31m[CRadioText] %s - %d: signal OnAfterDecodeLine blocked\033[0m\n", __func__, __LINE__); + } + } } else if (RTP_TToggle > 0 && mtext[5] == 0x46 && S_RtFunc >= 2) { // RTplus tags V2.0, only if RT @@ -670,6 +680,10 @@ CRadioText::~CRadioText(void) radiotext_stop(); cond.broadcast(); OpenThreads::Thread::join(); + if (g_RadiotextWin){ + delete g_RadiotextWin; + g_RadiotextWin = NULL; + } printf("CRadioText::~CRadioText done\n"); } @@ -722,6 +736,10 @@ void CRadioText::radiotext_stop(void) void CRadioText::setPid(uint inPid) { printf("CRadioText::setPid: ###################### old pid 0x%x new pid 0x%x ######################\n", pid, inPid); + if (!g_RadiotextWin){ + g_RadiotextWin = new CRadioTextGUI(); + g_RadiotextWin->allowPaint(false); + } if (pid != inPid) { mutex.lock(); pid = inPid; diff --git a/src/global.h b/src/global.h index efb9c128c..990b7bed5 100644 --- a/src/global.h +++ b/src/global.h @@ -95,6 +95,8 @@ class CVideoSettings; NEUTRINO_CPP CVideoSettings *g_videoSettings; class CRadioText; NEUTRINO_CPP CRadioText *g_Radiotext; +class CRadioTextGUI; +NEUTRINO_CPP CRadioTextGUI *g_RadiotextWin; #ifndef DISABLE_GUI_MOUNT #define ENABLE_GUI_MOUNT diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index c48acd85b..9e281ea91 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -90,6 +90,7 @@ libneutrino_gui_a_SOURCES = \ plugins.cpp \ plugins_hide.cpp \ proxyserver_setup.cpp \ + radiotext_window.cpp \ rc_lock.cpp \ record_setup.cpp \ scan.cpp \ diff --git a/src/gui/infoviewer.cpp b/src/gui/infoviewer.cpp index b6bacbf30..5399aba1f 100644 --- a/src/gui/infoviewer.cpp +++ b/src/gui/infoviewer.cpp @@ -277,7 +277,7 @@ void CInfoViewer::initClock() clock->setClockFormat("%H:%M", "%H %M"); } - CInfoClock::getInstance()->disableInfoClock(); + CInfoClock::getInstance()->block(); clock->clear(); clock->enableColBodyGradient(gradient_top, COL_INFOBAR_PLUS_0); clock->doPaintBg(!gradient_top); @@ -589,10 +589,6 @@ void CInfoViewer::showMovieTitle(const int playState, const t_channel_id &Channe zap_mode = _zap_mode; reset_allScala(); - if (g_settings.radiotext_enable && g_Radiotext) { - g_Radiotext->RT_MsgShow = true; - } - if(!is_visible) fader.StartFadeIn(); @@ -945,7 +941,7 @@ void CInfoViewer::showTitle(CZapitChannel * channel, const bool calledFromNumZap if (CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_radio || CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_webradio) { if ((g_settings.radiotext_enable) && (!recordModeActive) && (!calledFromNumZap)) - showRadiotext(); + enableRadiotext(); else if (showButtonBar) infoViewerBB->showIcon_RadioText(false); } @@ -1241,7 +1237,7 @@ void CInfoViewer::loop(bool show_dot) show_dot = !show_dot; showInfoFile(); if ((g_settings.radiotext_enable) && (CNeutrinoApp::getInstance()->getMode() == NeutrinoModes::mode_radio)) - showRadiotext(); + enableRadiotext(); infoViewerBB->showIcon_16_9(); //infoViewerBB->paint_ca_icons(0); @@ -1448,111 +1444,12 @@ void CInfoViewer::showMotorMoving (int duration) ShowHint (LOCALE_MESSAGEBOX_INFO, text, g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(text) + 2*OFFSET_INNER_MID, duration); } -void CInfoViewer::killRadiotext() +void CInfoViewer::enableRadiotext() //TODO: remove this roundabout way { - if (g_Radiotext->S_RtOsd) - frameBuffer->paintBackgroundBoxRel(rt_x, rt_y, rt_w + OFFSET_SHADOW, rt_h + OFFSET_SHADOW); - rt_x = rt_y = rt_h = rt_w = 0; - CInfoClock::getInstance()->enableInfoClock(true); - //NI InfoIcons - if (!g_settings.mode_icons && g_settings.mode_icons_skin == INFOICONS_INFOVIEWER) - CInfoIcons::getInstance()->paintIcons(true); - else - CInfoIcons::getInstance()->enableInfoIcons(true); -} - -void CInfoViewer::showRadiotext() -{ - /* - Maybe there's a nice CComponents solution with user's gradients. - */ - - if (g_Radiotext == NULL) - return; + OnEnableRadiotext(); if (showButtonBar) infoViewerBB->showIcon_RadioText(g_Radiotext->haveRadiotext()); - - char stext[3][100]; - bool RTisUTF8 = false; - - if (g_Radiotext->S_RtOsd) - { - CInfoClock::getInstance()->enableInfoClock(false); - //NI InfoIcons - if (!g_settings.mode_icons && g_settings.mode_icons_skin == INFOICONS_INFOVIEWER) - CInfoIcons::getInstance()->hideIcons(); - else - CInfoIcons::getInstance()->enableInfoIcons(false); - - int rt_font = SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO; - int item_h = g_Font[rt_font]->getHeight(); - - // dimensions of radiotext window - rt_x = BoxStartX; - rt_y = g_settings.screen_StartY + OFFSET_INNER_MID; - rt_w = BoxEndX - BoxStartX; - rt_h = (g_Radiotext->S_RtOsdRows + 1)*item_h + 4*OFFSET_INNER_SMALL; - - int item_x = rt_x + OFFSET_INNER_MID; - int item_y = rt_y + OFFSET_INNER_SMALL + item_h; - int item_w = rt_w - 2*OFFSET_INNER_MID; - - int item = 0; - int lines = 0; - for (int i = 0; i < g_Radiotext->S_RtOsdRows; i++) - { - if (g_Radiotext->RT_Text[i][0] != '\0') - lines++; - } - if (lines == 0) - frameBuffer->paintBackgroundBoxRel(rt_x, rt_y, rt_w + OFFSET_SHADOW, rt_h + OFFSET_SHADOW); - - if (g_Radiotext->RT_MsgShow) - { - // Title - if (g_Radiotext->S_RtOsdTitle == 1) - { - if (lines || g_Radiotext->RT_PTY != 0) - { - sprintf(stext[0], g_Radiotext->RT_PTY == 0 ? "%s %s%s" : "%s (%s)%s", tr("Radiotext"), g_Radiotext->RT_PTY == 0 ? g_Radiotext->RDS_PTYN : g_Radiotext->ptynr2string(g_Radiotext->RT_PTY), ":"); - int title_w = g_Font[rt_font]->getRenderWidth(stext[0]) + 2*OFFSET_INNER_MID; - - frameBuffer->paintBoxRel(rt_x + OFFSET_SHADOW, rt_y + OFFSET_SHADOW, title_w, 2*OFFSET_INNER_SMALL + item_h, COL_SHADOW_PLUS_0, RADIUS_LARGE, CORNER_TOP); - frameBuffer->paintBoxRel(rt_x, rt_y, title_w, 2*OFFSET_INNER_SMALL + item_h, COL_INFOBAR_PLUS_0, RADIUS_LARGE, CORNER_TOP); - - g_Font[rt_font]->RenderString(item_x, item_y, title_w, stext[0], COL_INFOBAR_TEXT, 0, RTisUTF8); - } - item = 1; - } - // Body - if (lines) - { - frameBuffer->paintBoxRel(rt_x + OFFSET_SHADOW, rt_y + 2*OFFSET_INNER_SMALL + item_h + OFFSET_SHADOW, rt_w, item_h*g_Radiotext->S_RtOsdRows + 2*OFFSET_INNER_SMALL, COL_SHADOW_PLUS_0, RADIUS_LARGE, item == 1 ? CORNER_TOP_RIGHT|CORNER_BOTTOM : CORNER_ALL); - frameBuffer->paintBoxRel(rt_x, rt_y + 2*OFFSET_INNER_SMALL + item_h, rt_w, item_h*g_Radiotext->S_RtOsdRows + 2*OFFSET_INNER_SMALL, COL_INFOBAR_PLUS_0, RADIUS_LARGE, item == 1 ? CORNER_TOP_RIGHT|CORNER_BOTTOM : CORNER_ALL); - - item_y += 2*OFFSET_INNER_SMALL; - - // RT-Text roundloop - int index = (g_Radiotext->RT_Index == 0) ? g_Radiotext->S_RtOsdRows - 1 : g_Radiotext->RT_Index - 1; - if (g_Radiotext->S_RtOsdLoop == 1) // latest bottom - { - for (int i = index + 1; i < g_Radiotext->S_RtOsdRows; i++) - g_Font[rt_font]->RenderString(item_x, item_y + (item++)*item_h, item_w, g_Radiotext->RT_Text[i], COL_INFOBAR_TEXT, 0, RTisUTF8); - for (int i = 0; i <= index; i++) - g_Font[rt_font]->RenderString(item_x, item_y + (item++)*item_h, item_w, g_Radiotext->RT_Text[i], COL_INFOBAR_TEXT, 0, RTisUTF8); - } - else // latest top - { - for (int i = index; i >= 0; i--) - g_Font[rt_font]->RenderString(item_x, item_y + (item++)*item_h, item_w, g_Radiotext->RT_Text[i], COL_INFOBAR_TEXT, 0, RTisUTF8); - for (int i = g_Radiotext->S_RtOsdRows - 1; i > index; i--) - g_Font[rt_font]->RenderString(item_x, item_y + (item++)*item_h, item_w, g_Radiotext->RT_Text[i], COL_INFOBAR_TEXT, 0, RTisUTF8); - } - } - } - } - g_Radiotext->RT_MsgShow = false; } int CInfoViewer::handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data) @@ -2271,8 +2168,11 @@ void CInfoViewer::killTitle() //printf("killTitle(%d, %d, %d, %d)\n", BoxStartX, BoxStartY, BoxEndX + OFFSET_SHADOW, BoxEndY); //frameBuffer->paintBackgroundBox(BoxStartX, BoxStartY, BoxEndX + OFFSET_SHADOW, BoxEndY); } + showButtonBar = false; CInfoClock::getInstance()->enableInfoClock(); + + OnAfterKillTitle(); } #if 0 diff --git a/src/gui/infoviewer.h b/src/gui/infoviewer.h index f4526ec68..47c8141d8 100644 --- a/src/gui/infoviewer.h +++ b/src/gui/infoviewer.h @@ -44,7 +44,7 @@ class CFrameBuffer; class COSDFader; class CInfoViewerBB; -class CInfoViewer +class CInfoViewer : public sigc::trackable { private: @@ -133,8 +133,7 @@ class CInfoViewer void showMotorMoving(int duration); void showLcdPercentOver(); int showChannelLogo(const t_channel_id logo_channel_id, const int channel_number_width); - void showRadiotext(); - void killRadiotext(); + void enableRadiotext(); //small infobox, shows a small textbox with a short message text, //text must be located in a file named /tmp/infobar.txt @@ -224,5 +223,7 @@ class CInfoViewer inline t_channel_id get_current_channel_id(void) { return current_channel_id; } void ResetModules(); bool hasTimeout(); + sigc::signal OnAfterKillTitle; + sigc::signal OnEnableRadiotext; }; #endif diff --git a/src/gui/osd_helpers.cpp b/src/gui/osd_helpers.cpp index 715df998a..cd2c37521 100644 --- a/src/gui/osd_helpers.cpp +++ b/src/gui/osd_helpers.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -41,6 +42,7 @@ COsdHelpers* COsdHelpers::getInstance() #ifdef ENABLE_CHANGE_OSD_RESOLUTION void COsdHelpers::changeOsdResolution(uint32_t mode, bool automode/*=false*/, bool forceOsdReset/*=false*/) { + OnBeforeChangeResolution(); size_t idx = 0; bool resetOsd = false; uint32_t modeNew; @@ -97,7 +99,7 @@ void COsdHelpers::changeOsdResolution(uint32_t mode, bool automode/*=false*/, bo //printf("\n>>>>>[%s:%d] New res: %dx%dx%d\n \n", __func__, __LINE__, resW, resH, bpp); g_settings.osd_resolution = modeNew; if (InfoClock) - InfoClock->disableInfoClock(); + InfoClock->StopInfoClock(true); frameBuffer->Clear(); if (resetOsd) { CNeutrinoApp::getInstance()->setScreenSettings(); @@ -122,6 +124,11 @@ void COsdHelpers::changeOsdResolution(uint32_t mode, bool automode/*=false*/, bo g_InfoViewer->showTitle(CNeutrinoApp::getInstance()->channelList->getActiveChannel(), true, 0, true); CNeutrinoApp::getInstance()->StartSubtitles(); } + if (g_RadiotextWin) { + delete g_RadiotextWin; + g_RadiotextWin = new CRadioTextGUI(); + g_RadiotextWin->allowPaint(false); + } } OnAfterChangeResolution(); } diff --git a/src/gui/osd_setup.cpp b/src/gui/osd_setup.cpp index af5e4f5b3..b547fc158 100644 --- a/src/gui/osd_setup.cpp +++ b/src/gui/osd_setup.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -176,7 +177,9 @@ const SNeutrinoSettings::FONT_TYPES other_font_sizes[] = SNeutrinoSettings::FONT_TYPE_WINDOW_GENERAL, SNeutrinoSettings::FONT_TYPE_SUBTITLES, SNeutrinoSettings::FONT_TYPE_FILEBROWSER_ITEM, - SNeutrinoSettings::FONT_TYPE_BUTTON_TEXT + SNeutrinoSettings::FONT_TYPE_BUTTON_TEXT, + SNeutrinoSettings::FONT_TYPE_WINDOW_RADIOTEXT_TITLE, + SNeutrinoSettings::FONT_TYPE_WINDOW_RADIOTEXT_DESC }; size_t other_font_items = sizeof(other_font_sizes)/sizeof(other_font_sizes[0]); @@ -234,7 +237,9 @@ font_sizes_struct neutrino_font[SNeutrinoSettings::FONT_TYPE_COUNT] = {LOCALE_FONTSIZE_SUBTITLES , 25, CNeutrinoFonts::FONT_STYLE_BOLD , 0}, {LOCALE_FONTSIZE_MESSAGE_TEXT , 20, CNeutrinoFonts::FONT_STYLE_BOLD , 0}, {LOCALE_FONTSIZE_BUTTON_TEXT , 14, CNeutrinoFonts::FONT_STYLE_REGULAR, 0}, - {LOCALE_FONTSIZE_GENERAL_WINDOW_TEXT, 20, CNeutrinoFonts::FONT_STYLE_REGULAR, 1} + {LOCALE_FONTSIZE_GENERAL_WINDOW_TEXT, 20, CNeutrinoFonts::FONT_STYLE_REGULAR, 1}, + {LOCALE_FONTSIZE_WINDOW_RADIOTEXT_DESC0, 22, CNeutrinoFonts::FONT_STYLE_REGULAR, 1}, + {LOCALE_FONTSIZE_WINDOW_RADIOTEXT_DESC1 , 17, CNeutrinoFonts::FONT_STYLE_REGULAR, 1} }; int COsdSetup::exec(CMenuTarget* parent, const std::string &actionKey) @@ -1659,10 +1664,20 @@ bool COsdSetup::changeNotify(const neutrino_locale_t OptionName, void * data) void COsdSetup::resetRadioText() { + if (getenv("SIMULATE_FE")){ + dprintf(DEBUG_NORMAL, "\033[33m[COsdSetup][%s - %d] SIMULATE_FE is set, no radiotext function availavble \033[0m\n", __func__, __LINE__); + return; + } + if (g_settings.radiotext_enable) { if (g_Radiotext == NULL) g_Radiotext = new CRadioText; + if (g_Radiotext && ((CNeutrinoApp::getInstance()->getMode()) == NeutrinoModes::mode_radio)){ + if (g_RadiotextWin){ + delete g_RadiotextWin; + g_RadiotextWin = NULL; + } unsigned int pid = 0; if(!g_RemoteControl->current_PIDs.APIDs.empty()) pid = g_RemoteControl->current_PIDs.APIDs[g_RemoteControl->current_PIDs.PIDs.selected_apid].pid; diff --git a/src/gui/radiotext_window.cpp b/src/gui/radiotext_window.cpp new file mode 100644 index 000000000..fffd3c075 --- /dev/null +++ b/src/gui/radiotext_window.cpp @@ -0,0 +1,378 @@ +/* + Based up Neutrino-GUI - Tuxbox-Project + Copyright (C) 2001 by Steffen Hehn 'McClean' + + Class for radio text handling + Copyright (C) 2019, Thilo Graf 'dbt' + + 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 "radiotext_window.h" +#include "infoclock.h" +#include "screensaver.h" +#include "infoviewer.h" + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TITLE_LINES 1 +#define MAX_DESC_LINES 2 + +using namespace std; + +CRadioTextGUI::CRadioTextGUI() : CComponentsWindow(0, 0, CFrameBuffer::getInstance()->getScreenWidth() - 2*OFFSET_INNER_MID, 0, "") +{ + Init(); +} + + +CRadioTextGUI::~CRadioTextGUI() +{ + dprintf(DEBUG_DEBUG, "\033[32m[CRadioTextGUI] %s - %d delete radiotext window instance\033[0m\n", __func__, __LINE__); +} + + +void CRadioTextGUI::Init() +{ + cc_item_type.name = "radiotext_window"; + + if (!g_Radiotext) + return; + + dprintf(DEBUG_DEBUG, "\033[32m[CRadioTextGUI] %s - %d init radiotext window handler\033[0m\n", __func__, __LINE__); + + initSlots(); + + font1 = g_Font[SNeutrinoSettings::FONT_TYPE_WINDOW_RADIOTEXT_TITLE]; + font2 = g_Font[SNeutrinoSettings::FONT_TYPE_WINDOW_RADIOTEXT_DESC]; + height = (MAX_DESC_LINES * font1->getHeight()) + (ccw_head->getHeight() + 2*OFFSET_INNER_MID); + shadow = CC_SHADOW_ON; + ccw_show_footer = false; + shadow_force = true; + channel_id_pair.first = CZapit::getInstance()->GetCurrentChannelID(); + channel_id_pair.second = 0; + +#if 0 // gradient mode for header with infobar properties + ccw_head->setColorBody(g_settings.theme.infobar_gradient_top ? COL_MENUHEAD_PLUS_0 : COL_INFOBAR_PLUS_0); + ccw_head->enableColBodyGradient(g_settings.theme.infobar_gradient_top, COL_INFOBAR_PLUS_0, g_settings.theme.infobar_gradient_top_direction); +#endif + ccw_body->setColorBody(g_settings.theme.infobar_gradient_body ? COL_MENUHEAD_PLUS_0 : COL_INFOBAR_PLUS_0); + ccw_body->enableColBodyGradient(g_settings.theme.infobar_gradient_body, COL_INFOBAR_PLUS_0, g_settings.theme.infobar_gradient_body_direction); + +} + + +void CRadioTextGUI::initSlots() +{ + // paint rt window if any decoded lines are available + sl_after_decode_line = sigc::bind(sigc::mem_fun(*this, &CRadioTextGUI::paint), false); + g_Radiotext->OnAfterDecodeLine.connect(sl_after_decode_line); + + // unblock paint of rt window if screensaver is started + sl_on_start_screensaver = sigc::bind(sigc::mem_fun(*this, &CRadioTextGUI::allowPaint), true); + CScreenSaver::getInstance()->OnAfterStart.connect(sl_on_start_screensaver); + + // block paint of screensaver if screensaver was sopped + sl_on_stop_screensaver = sigc::bind(sigc::mem_fun(*this, &CRadioTextGUI::allowPaint), false); + CScreenSaver::getInstance()->OnAfterStop.connect(sl_on_stop_screensaver); + + // reset position of rt window if screensaver was stopped, because rt window position would be changed inside screensaver + sl_on_stop_screensaver = sigc::mem_fun(*this, &CRadioTextGUI::resetPos); + CScreenSaver::getInstance()->OnAfterStop.connect(sl_on_stop_screensaver); + + // cleanup saved background while stopping screensaver + sl_on_stop_screensaver = sigc::mem_fun(*this, (&CRadioTextGUI::_clearSavedScreen)); + CScreenSaver::getInstance()->OnAfterStop.connect(sl_on_stop_screensaver); + + // remove rt window from screen if infoviewer was closed + sl_on_after_kill_infobar = sigc::bind(sigc::mem_fun(*this, &CRadioTextGUI::kill), COL_BACKGROUND_PLUS_0, -1, ~CC_FBDATA_TYPES); + g_InfoViewer->OnAfterKillTitle.connect(sl_on_after_kill_infobar); + + // allow paint of rt window if infoviewer gives commands + sl_on_show_radiotext = sigc::bind(sigc::mem_fun(*this, &CRadioTextGUI::allowPaint), true); + g_InfoViewer->OnEnableRadiotext.connect(sl_on_show_radiotext); +} + + +bool CRadioTextGUI::GetData() +{ + if (g_Radiotext == NULL) + return false; + +// if (showButtonBar) +// infoViewerBB->showIcon_RadioText(g_Radiotext->haveRadiotext()); ///callback??? +// + std::mutex mutex; + std::lock_guard lg(mutex); + char stext[3][100]; + + // cleanup lines on changed channel and clean up cached lines + channel_id_pair.first = CZapit::getInstance()->GetCurrentChannelID(); + if (channel_id_pair.first != channel_id_pair.second){ + clearLines(); + channel_id_pair.second = CZapit::getInstance()->GetCurrentChannelID(); + } + + if (g_Radiotext->S_RtOsd) + { + int lines = 0; + for (int i = 0; i < g_Radiotext->S_RtOsdRows; i++) + { + if (g_Radiotext->RT_Text[i][0] != '\0') + lines++; + } + +// if (lines) +// { +// clean up title before generate new lines +// clearLines() +// } + + if (g_Radiotext->RT_MsgShow) // TODO: remove unused desc lines from vector, maybe more than one lines are not really sensefully + { + // title line(s) + if (g_Radiotext->S_RtOsdTitle == 1) + { + if (lines || g_Radiotext->RT_PTY != 0) + { + snprintf(stext[0], sizeof(stext[0]),g_Radiotext->RT_PTY == 0 ? "%s %s%s" : "%s (%s)%s", tr("Radiotext"), g_Radiotext->RT_PTY == 0 ? g_Radiotext->RDS_PTYN : g_Radiotext->ptynr2string(g_Radiotext->RT_PTY), ":"); + if (!isDubLine(v_lines_title, stext[0])) + addLine(v_lines_title, stext[0]); + } + } + // collecting... + if (lines) + { + // RT-Text roundloop + int index = (g_Radiotext->RT_Index == 0) ? g_Radiotext->S_RtOsdRows - 1 : g_Radiotext->RT_Index - 1; + + if (g_Radiotext->S_RtOsdLoop == 1) // ...description lines, latest bottom + { + for (int i = index + 1; i < g_Radiotext->S_RtOsdRows; i++) + { + if (!string(g_Radiotext->RT_Text[i]).empty()) + if (!isDubLine(v_lines_desc, g_Radiotext->RT_Text[i])) + addLine(v_lines_desc, g_Radiotext->RT_Text[i]); + } + + for (int i = 0; i <= index; i++) + { + if (!string(g_Radiotext->RT_Text[i]).empty()) + if (!isDubLine(v_lines_desc, g_Radiotext->RT_Text[i])) + addLine(v_lines_desc, g_Radiotext->RT_Text[i]); + } + } + else // ...title line(s), latest top + { + for (int i = index; i >= 0; i--) + { + if (!string(g_Radiotext->RT_Text[i]).empty()) + if (!isDubLine(v_lines_desc, g_Radiotext->RT_Text[i])) + addLine(v_lines_desc, g_Radiotext->RT_Text[i]); + } + + for (int i = g_Radiotext->S_RtOsdRows - 1; i > index; i--) + { + if (!string(g_Radiotext->RT_Text[i]).empty()) + if (!isDubLine(v_lines_desc, g_Radiotext->RT_Text[i])) + addLine(v_lines_desc, g_Radiotext->RT_Text[i]); + } + } + } + } + } + + // clean up last description line that not to use + if (v_lines_desc.size() > MAX_DESC_LINES) + v_lines_desc.erase(v_lines_desc.begin()); + + g_Radiotext->RT_MsgShow = false; + + if (hasDescription() && hasTitle()) + return true; + + return false; +} + + +bool CRadioTextGUI::isDubLine(vector& vec, const string& to_compare_str) +{ + for (size_t i = 0; i < vec.size(); i++) + if (vec.at(i) == to_compare_str) + return true; + + return false; +} + +void CRadioTextGUI::addLine(std::vector& vec, std::string str) +{ + vec.push_back(iso_8859_1_to_utf8(str)); +} + + +void CRadioTextGUI::clearLines() +{ + if (hasTitle()) + v_lines_title.clear(); + if (hasDescription()) + v_lines_desc.clear(); + ccw_body->clear(); +} + +bool CRadioTextGUI::hasDescription() +{ + return !v_lines_desc.empty(); +} + + +bool CRadioTextGUI::hasTitle() +{ + return !v_lines_title.empty(); +} + +void CRadioTextGUI::InitInfoItems() +{ + //get and checkup required informations + if ((!GetData() && !hasLines()) || !cc_allow_paint) + return; + + //define size and position + int x_info = OFFSET_INNER_MID; + int y_info = OFFSET_INNER_MID; + int h_info = font1->getHeight(); //default height + int w_info = width-2*x_info; + + //init text items + if (ccw_body->empty()) + { + // add required text objects + for (int i = 0; i < MAX_DESC_LINES; i++) + { + static CComponentsTextTransp* item = NULL; + item = new CComponentsTextTransp(NULL, OFFSET_INNER_MID, y_info, w_info, h_info, ""); + item->setItemName("desc" + to_string(i)); + addWindowItem(item); + y_info += h_info; + } + } + + // fill text items with text + if (!v_lines_desc.empty()) + { + reverse(v_lines_desc.begin(),v_lines_desc.end()); // we need synchron order + for (size_t i = 0; i < v_lines_desc.size(); i++) + { + if (i < MAX_DESC_LINES) // use only required entries + { + if (ccw_body->getCCItem(i)) + { + if (ccw_body->getCCItem(i)->getItemType() == CC_ITEMTYPE_TEXT) + { + try + { + string s_tmp = v_lines_desc.at(i); + if (i > 0) + { + if (s_tmp == v_lines_desc.at(i-1)) + s_tmp = ""; + } + dprintf(DEBUG_INFO, "\033[36m[CRadioTextGUI] %s - %d: set line: %d text: %s\033[0m\n", __func__, __LINE__, (int)i, s_tmp.c_str()); + static CComponentsTextTransp* item = NULL; + item = static_cast (ccw_body->getCCItem(i)); + item->setText( s_tmp, + CTextBox::AUTO_HIGH | CTextBox::TOP | CTextBox::AUTO_LINEBREAK_NO_BREAKCHARS, + item->getItemName() == "desc0" ? font1 : font2); + } + catch (const std::exception &e) + { + dprintf(DEBUG_NORMAL, "\033[31m[CRadioTextGUI]\[%s - %d], exeption error %s\033[0m\n", __func__, __LINE__, e.what()); + return; + } + } + } + } + } + reverse(v_lines_desc.begin(),v_lines_desc.end()); // restore origin order + } +} + +void CRadioTextGUI::paint(const bool &do_save_bg) +{ + hide(); + clearSavedScreen(); + + if (!g_Radiotext) + return; + + if (!g_Radiotext->haveRadiotext()) + return; +#if 0 + g_Radiotext->S_RtOsd = g_Radiotext->haveRadiotext() ? 1 : 0; + + if (g_settings.radiotext_enable) + g_Radiotext->RT_MsgShow = true; +#endif + if (ccw_body->isPainted()){ + ccw_body->hideCCItems(); + } + + InitInfoItems(); +#if 0 + for (size_t i = 0; i < v_lines_title.size(); i++) + dprintf(DEBUG_NORMAL, "\033[32m[CRadioTextGUI] %s - %d: Title: %s\033[0m\n", __func__, __LINE__, v_lines_title[i].c_str()); + + size_t n = v_lines_desc.size()-1; + for (int i = n; i > -1; i--) + dprintf(DEBUG_NORMAL, "\033[32m[CRadioTextGUI] %s - %d: Description line: %s\033[0m\n", __func__, __LINE__, v_lines_desc[i].c_str()); +#endif + + if (!v_lines_title.empty()) + setWindowCaption(v_lines_title.back()); + + + if (cc_allow_paint) + CInfoClock::getInstance()->block(); + + CComponentsWindow::paint(do_save_bg); +} + +void CRadioTextGUI::kill(const fb_pixel_t& bg_color, const int& corner_radius, const int& fblayer_type) +{ + int cr = getCornerRadius() != corner_radius ? corner_radius : getCornerRadius(); + CComponentsWindow::kill(bg_color, cr, fblayer_type); + allowPaint(false); + ccw_body->clear(); +} + +void CRadioTextGUI::resetPos() +{ + setPos(0, 0); + initWindowSize(); + initWindowPos(); +} diff --git a/src/gui/radiotext_window.h b/src/gui/radiotext_window.h new file mode 100644 index 000000000..097b84b49 --- /dev/null +++ b/src/gui/radiotext_window.h @@ -0,0 +1,68 @@ +/* + Based up Neutrino-GUI - Tuxbox-Project + Copyright (C) 2001 by Steffen Hehn 'McClean' + + Class for radio text handling + Copyright (C) 2019, Thilo Graf 'dbt' + + 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 __C_GUI_RADIO_TEXT_H__ +#define __C_GUI_RADIO_TEXT_H__ + +#include +#include +#include + +class CRadioTextGUI : public CComponentsWindow +{ + private: + std::vector v_lines_title; + std::vector v_lines_desc; + Font *font1, *font2; + typedef std::pair channel_id_pairs; //pair = current id, old id + channel_id_pairs channel_id_pair; + + bool hasDescription(); + bool hasTitle(); + bool isDubLine(std::vector& vec, const std::string& to_compare_str); + void addLine(std::vector& vec, std::string str); + bool GetData(); + void initSlots(); + void resetPos(); + void Init(); + void InitInfoItems(); + void _clearSavedScreen() {clearSavedScreen();} + + + public: + CRadioTextGUI(); + virtual~CRadioTextGUI(); + + void kill(const fb_pixel_t& bg_color = COL_BACKGROUND_PLUS_0, const int& corner_radius = -1, const int& fblayer_type = ~CC_FBDATA_TYPES); + void clearLines(); + bool hasLines(){ return (hasTitle() || hasDescription());} + void paint(const bool &do_save_bg); + + sigc::slotsl_after_decode_line, + sl_on_start_screensaver, + sl_on_stop_screensaver, + sl_on_after_kill_infobar, + sl_on_show_radiotext; +}; +#endif diff --git a/src/gui/screensaver.cpp b/src/gui/screensaver.cpp index d8a0a1385..e960f95d1 100644 --- a/src/gui/screensaver.cpp +++ b/src/gui/screensaver.cpp @@ -38,11 +38,14 @@ #include // sort #include "audiomute.h" #include "screensaver.h" +#include +#include "radiotext_window.h" #include #include #include #include #include +#include #include extern cVideo * videoDecoder; @@ -50,32 +53,41 @@ extern cVideo * videoDecoder; //NI InfoIcons #include +static CComponentsFrmClock *scr_clock = NULL; + + using namespace std; CScreenSaver::CScreenSaver() { - thrScreenSaver = 0; + thrScreenSaver = NULL; m_frameBuffer = CFrameBuffer::getInstance(); m_viewer = new CPictureViewer(); index = 0; status_mute = CAudioMute::getInstance()->getStatus(); status_icons = CInfoIcons::getInstance()->getStatus(); //NI - scr_clock = NULL; + clr.i_color = COL_DARK_GRAY; pip_channel_id = 0; idletime = time(NULL); force_refresh = false; + thr_exit = false; + + sl_scr_stop = sigc::mem_fun(*this, &CScreenSaver::thrExit); + CNeutrinoApp::getInstance()->OnBeforeRestart.connect(sl_scr_stop); + CNeutrinoApp::getInstance()->OnShutDown.connect(sl_scr_stop); } CScreenSaver::~CScreenSaver() { - if(thrScreenSaver) - pthread_cancel(thrScreenSaver); - thrScreenSaver = 0; + thrExit(); delete m_viewer; - if (scr_clock) + + if (scr_clock){ delete scr_clock; + scr_clock = NULL; + } } @@ -88,20 +100,38 @@ CScreenSaver* CScreenSaver::getInstance() return screenSaver; } +void CScreenSaver::thrExit() +{ + if(thrScreenSaver) + { + dprintf(DEBUG_NORMAL,"[%s] %s: exit screensaver thread\n", __file__, __func__); + thr_exit = true; + thrScreenSaver->join(); + delete thrScreenSaver; + thrScreenSaver = NULL; + dprintf(DEBUG_NORMAL,"\033[32m[CScreenSaver] [%s - %d] screensaver thread stopped\033[0m\n", __func__, __LINE__); + } +} + void CScreenSaver::Start() { - OnBeforeStart(); + if (!OnBeforeStart.empty()) + OnBeforeStart(); + status_mute = CAudioMute::getInstance()->getStatus(); CAudioMute::getInstance()->enableMuteIcon(false); if(!CInfoClock::getInstance()->isBlocked()) - CInfoClock::getInstance()->disableInfoClock(); + CInfoClock::getInstance()->block(); //NI status_icons = CInfoIcons::getInstance()->getStatus(); CInfoIcons::getInstance()->enableInfoIcons(false); + if (g_RadiotextWin) + g_Radiotext->OnAfterDecodeLine.block(); + #ifdef ENABLE_PIP pip_channel_id = CZapit::getInstance()->GetPipChannelID(); if (pip_channel_id) @@ -125,26 +155,30 @@ void CScreenSaver::Start() m_frameBuffer->showFrame("blackscreen.jpg"); #endif m_frameBuffer->stopFrame(); - + if(!thrScreenSaver) { - //printf("[%s] %s: starting thread\n", __file__, __FUNCTION__); - pthread_create(&thrScreenSaver, NULL, ScreenSaverPrg, (void*) this); - pthread_detach(thrScreenSaver); + dprintf(DEBUG_NORMAL,"[%s] %s: starting thread\n", __file__, __func__); + thr_exit = false; + thrScreenSaver = new std::thread (ScreenSaverPrg, this); + std::string tn = "screen_saver"; + set_threadname(tn.c_str()); + dprintf(DEBUG_NORMAL,"\033[32m[CScreenSaver] [%s - %d] thread [%p] [%s] started\033[0m\n", __func__, __LINE__, thrScreenSaver, tn.c_str()); } + if (!OnAfterStart.empty()) + OnAfterStart(); } void CScreenSaver::Stop() { - if(thrScreenSaver) - { - pthread_cancel(thrScreenSaver); - thrScreenSaver = 0; - } + //exit thread + thrExit(); + resetIdleTime(); if (scr_clock){ + std::lock_guard g(scr_mutex); scr_clock->Stop(); delete scr_clock; scr_clock = NULL; @@ -161,47 +195,51 @@ void CScreenSaver::Stop() CInfoIcons::getInstance()->enableInfoIcons(status_icons); //NI CAudioMute::getInstance()->enableMuteIcon(status_mute); - if (!OnAfterStop.empty()){ + + CInfoClock::getInstance()->ClearDisplay(); //provokes reinit + CInfoClock::getInstance()->enableInfoClock(); + + if (g_RadiotextWin) + g_Radiotext->OnAfterDecodeLine.unblock(); + + if (!OnAfterStop.empty()) OnAfterStop(); - }else{ - CInfoClock::getInstance()->ClearDisplay(); //provokes reinit - CInfoClock::getInstance()->enableInfoClock(); - } } -void* CScreenSaver::ScreenSaverPrg(void* arg) +void CScreenSaver::ScreenSaverPrg(CScreenSaver *scr) { - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); - - CScreenSaver * PScreenSaver = static_cast(arg); - - PScreenSaver->m_frameBuffer->Clear(); + scr->m_frameBuffer->Clear(); if (g_settings.screensaver_timeout) { - while(PScreenSaver) + while(!scr->thr_exit) { if (g_settings.screensaver_mode == SCR_MODE_IMAGE) - PScreenSaver->ReadDir(); + scr->ReadDir(); - PScreenSaver->paint(); - int t = g_settings.screensaver_timeout; - while (t--) + scr->paint(); + + int corr = 1; +#if HAVE_COOL_HARDWARE //time offset + corr = 10; +#endif + int t = 1000/corr * g_settings.screensaver_timeout; //sleep and exit handle + while (t > 0) { - sleep(1); - if (PScreenSaver->force_refresh) + if (!scr->thr_exit) + this_thread::sleep_for(std::chrono::milliseconds(1)); + t--; + + if (scr->force_refresh) //NOTE: Do we really need this ? { - PScreenSaver->force_refresh = false; + scr->force_refresh = false; break; } } } } else - PScreenSaver->paint(); - - return 0; + scr->paint(); } bool CScreenSaver::ReadDir() @@ -245,7 +283,6 @@ bool CScreenSaver::ReadDir() struct dirent *dirpointer; DIR *dir; char curr_ext[5]; - int curr_lenght; bool ret = false; v_bg_files.clear(); @@ -257,9 +294,9 @@ bool CScreenSaver::ReadDir() } /* read complete dir */ - while((dirpointer=readdir(dir)) != NULL) + while((dirpointer=readdir(dir)) != NULL) // TODO: use threadsave readdir_r instead readdir { - curr_lenght = strlen((*dirpointer).d_name); + int curr_lenght = strlen((*dirpointer).d_name); string str = dir_name; //printf("%d\n",curr_lenght); if(curr_lenght > 4) @@ -309,19 +346,26 @@ void CScreenSaver::paint() { if (scr_clock) { - scr_clock->kill(); - scr_clock->allowPaint(false); - if (g_settings.screensaver_mode == SCR_MODE_IMAGE){ + if (g_settings.screensaver_mode != SCR_MODE_CLOCK_COLOR && g_settings.screensaver_mode != SCR_MODE_CLOCK) + { + std::lock_guard g(scr_mutex); delete scr_clock; scr_clock = NULL; } + else + { + scr_clock->kill(0); + scr_clock->clearSavedScreen(); + scr_clock->doPaintBg(false); + } } + if (g_settings.screensaver_mode == SCR_MODE_IMAGE && v_bg_files.empty()) m_frameBuffer->paintBackground(); - if (g_settings.screensaver_mode == SCR_MODE_IMAGE && !v_bg_files.empty()){ - - if( (index >= v_bg_files.size()) || (access(v_bg_files.at(index).c_str(), F_OK)) ) + if (g_settings.screensaver_mode == SCR_MODE_IMAGE && !v_bg_files.empty()) + { + if( (index >= v_bg_files.size()) || (access(v_bg_files.at(index).c_str(), F_OK))) { ReadDir(); index = 0; @@ -329,45 +373,93 @@ void CScreenSaver::paint() } dprintf(DEBUG_INFO, "[CScreenSaver] %s - %d : %s\n", __func__, __LINE__, v_bg_files.at(index).c_str()); +#if 0 + hideRadioText(); +#endif + //m_frameBuffer->showFrame(v_bg_files.at(index), CFrameBuffer::SHOW_FRAME_FALLBACK_MODE_IMAGE); m_viewer->ShowImage(v_bg_files.at(index).c_str(), false /*unscaled*/); +#if 1 + handleRadioText(); +#endif if (!g_settings.screensaver_random) index++; else - index = rand() % v_bg_files.size(); + index = rand_r(&seed[0]) % v_bg_files.size(); if(index == v_bg_files.size()) index = 0; } - else{ - if (!scr_clock){ - scr_clock = new CComponentsFrmClock(1, 1, NULL, "%H:%M:%S", "%H:%M.%S", true, 1, NULL, CC_SHADOW_OFF, COL_BLACK, COL_BLACK); + else + { + if (!scr_clock) + { + scr_clock = new CComponentsFrmClock(1, 1, NULL, "%H:%M:%S", "%H:%M.%S", false, 1, NULL, CC_SHADOW_OFF, COL_BLACK, COL_BLACK); scr_clock->setItemName("scr_clock"); scr_clock->setCornerType(CORNER_NONE); scr_clock->setClockFont(g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_NUMBER]); - scr_clock->disableSaveBg(); + scr_clock->enableSaveBg(); scr_clock->doPaintBg(false); +#if HAVE_COOL_HARDWARE + paintImage("blackscreen.jpg", 0, 0, m_frameBuffer->getScreenWidth(true), m_frameBuffer->getScreenHeight(true)); +#endif + } +#if !HAVE_COOL_HARDWARE +#if 0 //example for callback + m_frameBuffer->OnFallbackShowFrame.connect(sigc::bind(sigc::mem_fun(CFrameBuffer::getInstance(), + &CFrameBuffer::paintBoxRel), + scr_clock->getXPos(), scr_clock->getYPos(), + scr_clock->getWidth(), scr_clock->getHeight(), + COL_BLACK, + 0, + CORNER_ALL) + ); +#endif + m_frameBuffer->showFrame("blackscreen.jpg", CFrameBuffer::SHOW_FRAME_FALLBACK_MODE_CALLBACK | CFrameBuffer::SHOW_FRAME_FALLBACK_MODE_BLACKSCREEN); +#endif + + handleRadioText(); + + if (scr_clock) + { + scr_clock->setTextColor(clr.i_color); + //check position and size use only possible available screen size + int x_cl, y_cl, w_cl, h_cl; + scr_clock->getDimensions(&x_cl, &y_cl, &w_cl, &h_cl); + int x_random = rand_r(&seed[1]) % ((g_settings.screen_EndX - w_cl - g_settings.screen_StartX) + 1) + g_settings.screen_StartX; + int y_random = rand_r(&seed[2]) % ((g_settings.screen_EndY - h_cl - g_settings.screen_StartY) + 1) + g_settings.screen_StartY; + + if (g_RadiotextWin) + { + // avoid overlapping of clock and radio text window + int y_min = g_RadiotextWin->getYPos() - scr_clock->getHeight(); + int y_max = g_RadiotextWin->getYPos() + g_RadiotextWin->getHeight(); + while (y_random > (y_min - scr_clock->getHeight()) && y_random < y_max) + y_random = rand_r(&seed[2]) % ((g_settings.screen_EndY - h_cl - g_settings.screen_StartY) + 1) + g_settings.screen_StartY; + } + + scr_clock->setPos(x_random, y_random); + + if (!scr_clock->isRun()) + scr_clock->Start(); + else + scr_clock->paint(true); + + if (g_RadiotextWin) + scr_clock->allowPaint(g_RadiotextWin->isPainted()); + else + scr_clock->allowPaint(true); } - scr_clock->setTextColor(clr.i_color); - //check position and size use only possible available screen size - int x_cl, y_cl, w_cl, h_cl; - scr_clock->getDimensions(&x_cl, &y_cl, &w_cl, &h_cl); - int x_random = rand() % ((g_settings.screen_EndX - w_cl - g_settings.screen_StartX) + 1) + g_settings.screen_StartX; - int y_random = rand() % ((g_settings.screen_EndY - h_cl - g_settings.screen_StartY) + 1) + g_settings.screen_StartY; - scr_clock->setPos(x_random, y_random); - scr_clock->allowPaint(true); - if (!scr_clock->isRun()) - scr_clock->Start(); - - if (g_settings.screensaver_mode == SCR_MODE_CLOCK_COLOR) { + if (g_settings.screensaver_mode == SCR_MODE_CLOCK_COLOR) + { srand (time(NULL)); uint32_t brightness; // sorcery, no darkness do { - clr.i_color = rand(); + clr.i_color = rand_r(&seed[3]); brightness = (unsigned int)clr.uc_color.r * 19595 + (unsigned int)clr.uc_color.g * 38469 + (unsigned int)clr.uc_color.b * 7471; //printf("[%s] %s: brightness: %d\n", __file__, __FUNCTION__, brightness>> 16); } @@ -381,6 +473,54 @@ void CScreenSaver::paint() } } +void CScreenSaver::handleRadioText() +{ + if (!g_RadiotextWin) + return; + + if (g_RadiotextWin->isPainted() || g_settings.screensaver_mode == SCR_MODE_IMAGE) + { + g_RadiotextWin->hide(); + g_RadiotextWin->clearSavedScreen(); + } + else + g_RadiotextWin->kill(/*COL_BLACK*/); //ensure black paintBackground before repaint + + //check position and size, use only possible available screen size + int x_rt, y_rt, w_rt, h_rt; + g_RadiotextWin->getDimensions(&x_rt, &y_rt, &w_rt, &h_rt); + int rt_x_random = rand_r(&seed[4]) % ((g_settings.screen_EndX - w_rt - g_settings.screen_StartX - OFFSET_SHADOW) + 1) + g_settings.screen_StartX; + int rt_y_random = rand_r(&seed[5]) % ((g_settings.screen_EndY - h_rt - g_settings.screen_StartY - OFFSET_SHADOW) + 1) + g_settings.screen_StartY; + g_RadiotextWin->setPos(rt_x_random, rt_y_random); + g_RadiotextWin->allowPaint(true); + + if (g_RadiotextWin->hasLines()) + { + if (scr_clock) + scr_clock->cl_sl_show.block(); + g_RadiotextWin->CRadioTextGUI::paint(CC_SAVE_SCREEN_YES); + if (scr_clock) + scr_clock->cl_sl_show.unblock(); + } +} + +void CScreenSaver::hideRadioText() +{ + if (!g_RadiotextWin) + return; + + g_RadiotextWin->sl_after_decode_line.block(); + + if (scr_clock) + scr_clock->cl_sl_show.block(); + + g_RadiotextWin->kill(); + g_RadiotextWin->hide(); + + if (scr_clock) + scr_clock->cl_sl_show.unblock(); +} + bool CScreenSaver::canStart() { if (g_settings.screensaver_delay && (time(NULL) - idletime > g_settings.screensaver_delay*60)) @@ -412,5 +552,11 @@ bool CScreenSaver::ignoredMsg(neutrino_msg_t msg) || msg == NeutrinoMessages::EVT_BACK_ZAP_COMPLETE ) return true; + return false; } + +CComponentsFrmClock* CScreenSaver::getClockObject() +{ + return scr_clock; +} diff --git a/src/gui/screensaver.h b/src/gui/screensaver.h index 9e2070048..4836899e0 100644 --- a/src/gui/screensaver.h +++ b/src/gui/screensaver.h @@ -28,6 +28,9 @@ #include #include #include +#include +#include + class CFrameBuffer; class CPictureViewer; @@ -36,15 +39,22 @@ class CScreenSaver : public sigc::trackable private: CFrameBuffer *m_frameBuffer; CPictureViewer *m_viewer; - CComponentsFrmClock *scr_clock; - pthread_t thrScreenSaver; - static void* ScreenSaverPrg(void *arg); + + std::thread *thrScreenSaver; + static void ScreenSaverPrg(CScreenSaver *scr); + bool thr_exit; + std::mutex scr_mutex; + std::vector v_bg_files; unsigned int index; t_channel_id pip_channel_id; bool force_refresh; bool status_mute; bool status_icons; //NI + uint seed[6]; + + void handleRadioText(); + void hideRadioText(); bool ReadDir(); void paint(); @@ -59,6 +69,8 @@ class CScreenSaver : public sigc::trackable }; u_color clr; + void thrExit(); + sigc::slot sl_scr_stop; public: enum @@ -76,11 +88,13 @@ class CScreenSaver : public sigc::trackable void Stop(); bool ignoredMsg(neutrino_msg_t msg); sigc::signal OnBeforeStart; + sigc::signal OnAfterStart; sigc::signal OnAfterStop; void resetIdleTime() { idletime = time(NULL); } time_t getIdleTime() { return idletime; } void forceRefresh() { force_refresh = true; } + static CComponentsFrmClock* getClockObject(); }; #endif // __CSCREENSAVER_H__ diff --git a/src/system/settings.h b/src/system/settings.h index 540a50d31..c81ecb4b9 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -778,6 +778,8 @@ struct SNeutrinoSettings FONT_TYPE_MESSAGE_TEXT, FONT_TYPE_BUTTON_TEXT, FONT_TYPE_WINDOW_GENERAL, + FONT_TYPE_WINDOW_RADIOTEXT_TITLE, + FONT_TYPE_WINDOW_RADIOTEXT_DESC, FONT_TYPE_COUNT };