/*
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();
}