/* 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)", 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 || CNeutrinoApp::getInstance()->getMode() != NeutrinoModes::mode_radio) 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()); setWindowIcon(NEUTRINO_ICON_RADIOTEXT); } 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(); }