mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-28 16:01:10 +02:00
Replacing messagebox, hintbox_ext and some derivated parts with
basic class hintbox and derivated class CMsgBox. This should unify
window handling and avoids maintain of multiple classes with quasi
same purpose and adds more functionality.
TODO: fix and optimize details
Origin commit data
------------------
Branch: ni/coolstream
Commit: dde298b1b7
Author: Thilo Graf <dbt@novatux.de>
Date: 2016-04-04 (Mon, 04 Apr 2016)
------------------
This commit was generated by Migit
2757 lines
86 KiB
C++
2757 lines
86 KiB
C++
/*
|
|
Neutrino-GUI - DBoxII-Project
|
|
|
|
Copyright (C) 2001 Steffen Hehn 'McClean'
|
|
Copyright (C) 2007-2016 Stefan Seyfried
|
|
|
|
Kommentar:
|
|
|
|
Diese GUI wurde von Grund auf neu programmiert und sollte nun vom
|
|
Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert
|
|
auf der Client-Server Idee, diese GUI ist also von der direkten DBox-
|
|
Steuerung getrennt. Diese wird dann von Daemons uebernommen.
|
|
|
|
|
|
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., 51 Franklin St, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
#include <sstream>
|
|
|
|
#include <gui/channellist.h>
|
|
|
|
#include <unistd.h>
|
|
#include <global.h>
|
|
#include <neutrino.h>
|
|
|
|
#include <driver/screen_max.h>
|
|
#include <driver/abstime.h>
|
|
#include <driver/record.h>
|
|
#include <driver/fade.h>
|
|
#include <driver/display.h>
|
|
#include <driver/radiotext.h>
|
|
|
|
#include <gui/color.h>
|
|
#include <gui/color_custom.h>
|
|
#include <gui/epgview.h>
|
|
#include <gui/eventlist.h>
|
|
#include <gui/infoviewer.h>
|
|
#include <gui/osd_setup.h>
|
|
#include <gui/components/cc.h>
|
|
#include <gui/widget/stringinput.h>
|
|
#include <gui/widget/keyboard_input.h>
|
|
#include <gui/widget/buttons.h>
|
|
#include <gui/widget/icons.h>
|
|
#include <gui/movieplayer.h>
|
|
#include <gui/infoclock.h>
|
|
#if 0
|
|
#include <gui/widget/messagebox.h>
|
|
#include <gui/widget/hintbox.h>
|
|
#else
|
|
#include <gui/widget/msgbox.h>
|
|
#endif
|
|
#include <system/settings.h>
|
|
#include <system/set_threadname.h>
|
|
|
|
#include <gui/bouquetlist.h>
|
|
#include <daemonc/remotecontrol.h>
|
|
#include <zapit/client/zapittools.h>
|
|
#include <gui/pictureviewer.h>
|
|
#include <gui/bedit/bouqueteditor_chanselect.h>
|
|
|
|
#include <zapit/zapit.h>
|
|
#include <zapit/satconfig.h>
|
|
#include <zapit/getservices.h>
|
|
#include <zapit/femanager.h>
|
|
#include <zapit/debug.h>
|
|
|
|
#include <eitd/sectionsd.h>
|
|
|
|
extern CBouquetList * bouquetList; /* neutrino.cpp */
|
|
extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */
|
|
extern CBouquetList * AllFavBouquetList;
|
|
extern CBouquetList * TVfavList;
|
|
extern CBouquetList * RADIOfavList;
|
|
|
|
extern bool autoshift;
|
|
static CComponentsPIP *cc_minitv = NULL;
|
|
extern CBouquetManager *g_bouquetManager;
|
|
extern int old_b_id;
|
|
static CComponentsChannelLogoScalable* CChannelLogo = NULL;
|
|
static CComponentsHeader *header = NULL;
|
|
extern bool timeset;
|
|
|
|
CChannelList::CChannelList(const char * const pName, bool phistoryMode, bool _vlist)
|
|
{
|
|
frameBuffer = CFrameBuffer::getInstance();
|
|
x = y = 0;
|
|
info_height = 0;
|
|
name = pName;
|
|
selected = 0;
|
|
selected_in_new_mode = 0;
|
|
liststart = 0;
|
|
tuned = 0xfffffff;
|
|
zapProtection = NULL;
|
|
this->historyMode = phistoryMode;
|
|
vlist = _vlist;
|
|
new_zap_mode = 0;
|
|
selected_chid = 0;
|
|
footerHeight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_FOOT]->getHeight()+6; //initial height value for buttonbar
|
|
theight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->getHeight();
|
|
fheight = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getHeight();
|
|
fdescrheight = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getHeight();
|
|
|
|
previous_channellist_additional = -1;
|
|
eventFont = SNeutrinoSettings::FONT_TYPE_CHANNELLIST_EVENT;
|
|
dline = NULL;
|
|
cc_minitv = NULL;
|
|
logo_off = 0;
|
|
pig_on_win = false;
|
|
CChannelLogo = NULL;
|
|
headerNew = true;
|
|
bouquet = NULL;
|
|
chanlist = &channels;
|
|
move_state = beDefault;
|
|
edit_state = false;
|
|
channelsChanged = false;
|
|
|
|
paint_events_index = -2;
|
|
}
|
|
|
|
CChannelList::~CChannelList()
|
|
{
|
|
ResetModules();
|
|
}
|
|
|
|
void CChannelList::SetChannelList(ZapitChannelList* zlist)
|
|
{
|
|
channels = *zlist;
|
|
}
|
|
|
|
void CChannelList::addChannel(CZapitChannel* channel)
|
|
{
|
|
(*chanlist).push_back(channel);
|
|
}
|
|
|
|
/* update the events for the visible channel list entries
|
|
from = start entry, to = end entry. If both = zero, update all */
|
|
void CChannelList::updateEvents(unsigned int from, unsigned int to)
|
|
{
|
|
if ((*chanlist).empty())
|
|
return;
|
|
|
|
if (to == 0 || to > (*chanlist).size())
|
|
to = (*chanlist).size();
|
|
|
|
if (from > (*chanlist).size() || from >= to)
|
|
return;
|
|
|
|
size_t chanlist_size = to - from;
|
|
if (chanlist_size <= 0) // WTF???
|
|
return;
|
|
|
|
CChannelEventList events;
|
|
if (displayNext) {
|
|
time_t atime = time(NULL);
|
|
unsigned int count;
|
|
for (count = from; count < to; count++) {
|
|
CEitManager::getInstance()->getEventsServiceKey((*chanlist)[count]->getEpgID(), events);
|
|
(*chanlist)[count]->nextEvent.startTime = (long)0x7fffffff;
|
|
for ( CChannelEventList::iterator e= events.begin(); e != events.end(); ++e ) {
|
|
if ((long)e->startTime > atime &&
|
|
(e->startTime < (long)(*chanlist)[count]->nextEvent.startTime))
|
|
{
|
|
(*chanlist)[count]->nextEvent = *e;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
t_channel_id *p_requested_channels;
|
|
p_requested_channels = new t_channel_id[chanlist_size];
|
|
if (! p_requested_channels) {
|
|
fprintf(stderr,"%s:%d allocation failed!\n", __FUNCTION__, __LINE__);
|
|
return;
|
|
}
|
|
for (uint32_t count = 0; count < chanlist_size; count++)
|
|
p_requested_channels[count] = (*chanlist)[count + from]->getEpgID();
|
|
|
|
CChannelEventList levents;
|
|
CEitManager::getInstance()->getChannelEvents(levents, p_requested_channels, chanlist_size);
|
|
for (uint32_t count=0; count < chanlist_size; count++) {
|
|
(*chanlist)[count + from]->currentEvent = CChannelEvent();
|
|
for (CChannelEventList::iterator e = levents.begin(); e != levents.end(); ++e) {
|
|
if (((*chanlist)[count + from]->getEpgID()&0xFFFFFFFFFFFFULL) == e->get_channel_id()) {
|
|
(*chanlist)[count + from]->currentEvent = *e;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
levents.clear();
|
|
delete[] p_requested_channels;
|
|
}
|
|
}
|
|
|
|
void CChannelList::SortAlpha(void)
|
|
{
|
|
sort((*chanlist).begin(), (*chanlist).end(), CmpChannelByChName());
|
|
}
|
|
|
|
void CChannelList::SortSat(void)
|
|
{
|
|
sort((*chanlist).begin(), (*chanlist).end(), CmpChannelBySat());
|
|
}
|
|
|
|
void CChannelList::SortTP(void)
|
|
{
|
|
sort((*chanlist).begin(), (*chanlist).end(), CmpChannelByFreq());
|
|
}
|
|
|
|
void CChannelList::SortChNumber(void)
|
|
{
|
|
sort((*chanlist).begin(), (*chanlist).end(), CmpChannelByChNum());
|
|
}
|
|
|
|
CZapitChannel* CChannelList::getChannel(int number)
|
|
{
|
|
for (uint32_t i=0; i< (*chanlist).size(); i++) {
|
|
if ((*chanlist)[i]->number == number)
|
|
return (*chanlist)[i];
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
CZapitChannel* CChannelList::getChannel(t_channel_id channel_id)
|
|
{
|
|
for (uint32_t i=0; i< (*chanlist).size(); i++) {
|
|
if ((*chanlist)[i]->getChannelID() == channel_id)
|
|
return (*chanlist)[i];
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
int CChannelList::getKey(int id)
|
|
{
|
|
if (id > -1 && id < (int)(*chanlist).size())
|
|
return (*chanlist)[id]->number;
|
|
return 0;
|
|
}
|
|
|
|
const std::string CChannelList::getActiveChannelName(void) const
|
|
{
|
|
static const std::string empty_string;
|
|
if (selected < (*chanlist).size())
|
|
return (*chanlist)[selected]->getName();
|
|
return empty_string;
|
|
}
|
|
|
|
t_satellite_position CChannelList::getActiveSatellitePosition(void) const
|
|
{
|
|
if (selected < (*chanlist).size())
|
|
return (*chanlist)[selected]->getSatellitePosition();
|
|
return 0;
|
|
}
|
|
|
|
t_channel_id CChannelList::getActiveChannel_ChannelID(void) const
|
|
{
|
|
if (selected < (*chanlist).size())
|
|
return (*chanlist)[selected]->getChannelID();
|
|
return 0;
|
|
}
|
|
|
|
int CChannelList::getActiveChannelNumber(void) const
|
|
{
|
|
if (selected < (*chanlist).size())
|
|
return (*chanlist)[selected]->number;
|
|
return 0;
|
|
}
|
|
|
|
CZapitChannel * CChannelList::getActiveChannel(void) const
|
|
{
|
|
static CZapitChannel channel("Channel not found", 0, 0, 0, 0);
|
|
if (selected < (*chanlist).size())
|
|
return (*chanlist)[selected];
|
|
return &channel;
|
|
}
|
|
|
|
int CChannelList::doChannelMenu(void)
|
|
{
|
|
int select = -1;
|
|
int shortcut = 0;
|
|
static int old_selected = 0;
|
|
char cnt[5];
|
|
bool unlocked = true;
|
|
int ret = 0;
|
|
|
|
if(g_settings.minimode)
|
|
return 0;
|
|
|
|
CMenuWidget* menu = new CMenuWidget(LOCALE_CHANNELLIST_EDIT, NEUTRINO_ICON_SETTINGS);
|
|
menu->enableFade(false);
|
|
menu->enableSaveScreen(true);
|
|
|
|
//ensure stop info clock before paint context menu
|
|
CInfoClock::getInstance()->block();
|
|
|
|
//ensure stop header clock before paint context menu
|
|
if (g_settings.menu_pos == CMenuWidget::MENU_POS_TOP_RIGHT){
|
|
//using native callback to ensure stop header clock before paint this menu window
|
|
menu->OnBeforePaint.connect(sigc::mem_fun(header->getClockObject(), &CComponentsFrmClock::block));
|
|
//... and start header clock after hide menu window
|
|
menu->OnAfterHide.connect(sigc::mem_fun(header->getClockObject(), &CComponentsFrmClock::unblock));
|
|
}
|
|
|
|
CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select);
|
|
|
|
bool empty = (*chanlist).empty();
|
|
bool allow_edit = (bouquet && bouquet->zapitBouquet && !bouquet->zapitBouquet->bOther && !bouquet->zapitBouquet->bWebtv);
|
|
bool got_history = (CNeutrinoApp::getInstance()->channelList->getLastChannels().size() > 1);
|
|
|
|
int i = 0;
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_BOUQUETEDITOR_NAME, allow_edit, NULL, selector, cnt, CRCInput::RC_red), old_selected == i++);
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_EXTRA_ADD_TO_BOUQUET, !empty, NULL, selector, cnt, CRCInput::RC_green), old_selected == i++);
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_FAVORITES_MENUEADD, !empty, NULL, selector, cnt, CRCInput::RC_yellow), old_selected == i++);
|
|
|
|
bool reset_enabled = empty ? false : (*chanlist)[selected]->flags & CZapitChannel::NEW;
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_CHANNELLIST_RESET_FLAGS, reset_enabled, NULL, selector, cnt, CRCInput::convertDigitToKey(shortcut++)), old_selected == i++);
|
|
|
|
bool reset_all = !empty && (name == g_Locale->getText(LOCALE_BOUQUETNAME_NEW));
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_CHANNELLIST_RESET_ALL, reset_all, NULL, selector, cnt, CRCInput::convertDigitToKey(shortcut++)), old_selected == i++);
|
|
|
|
menu->addItem(GenericMenuSeparator);
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_CHANNELLIST_HISTORY_CLEAR, got_history, NULL, selector, cnt, CRCInput::convertDigitToKey(shortcut++)), old_selected == i++);
|
|
|
|
menu->addItem(new CMenuSeparator(CMenuSeparator::LINE));
|
|
snprintf(cnt, sizeof(cnt), "%d", i);
|
|
menu->addItem(new CMenuForwarder(LOCALE_MAINMENU_SETTINGS, true, NULL, selector, cnt, CRCInput::convertDigitToKey(shortcut++)), old_selected == i++);
|
|
menu->exec(NULL, "");
|
|
delete menu;
|
|
delete selector;
|
|
|
|
if(select >= 0) {
|
|
//signed int bouquet_id = 0;
|
|
old_selected = select;
|
|
t_channel_id channel_id = empty ? 0 : (*chanlist)[selected]->getChannelID();
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
CBouquetList *blist = tvmode ? TVfavList : RADIOfavList;
|
|
bool fav_found = true;
|
|
switch(select) {
|
|
case 0: // edit mode
|
|
if (g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_CHANGETOLOCKED) {
|
|
int pl_z = g_settings.parentallock_zaptime * 60;
|
|
if (g_settings.personalize[SNeutrinoSettings::P_MSER_BOUQUET_EDIT] == CPersonalizeGui::PERSONALIZE_MODE_PIN) {
|
|
unlocked = false;
|
|
} else if (bouquet && bouquet->zapitBouquet && bouquet->zapitBouquet->bLocked) {
|
|
/* on locked bouquet, enough to check any channel */
|
|
unlocked = ((*chanlist)[selected]->last_unlocked_time + pl_z > time_monotonic());
|
|
} else {
|
|
/* check all locked channels for last_unlocked_time, overwrite only if already unlocked */
|
|
for (unsigned int j = 0 ; j < (*chanlist).size(); j++) {
|
|
if ((*chanlist)[j]->bLocked)
|
|
unlocked = unlocked && ((*chanlist)[j]->last_unlocked_time + pl_z > time_monotonic());
|
|
}
|
|
}
|
|
if (!unlocked) {
|
|
CZapProtection *zp = new CZapProtection(g_settings.parentallock_pincode, 0x100);
|
|
unlocked = zp->check();
|
|
delete zp;
|
|
}
|
|
}
|
|
if (unlocked)
|
|
editMode(true);
|
|
ret = -1;
|
|
break;
|
|
case 1: // add to
|
|
if (!addChannelToBouquet())
|
|
return -1;
|
|
ret = 1;
|
|
break;
|
|
case 2: // add to my favorites
|
|
for (unsigned n = 0; n < AllFavBouquetList->Bouquets.size(); n++) {
|
|
if (AllFavBouquetList->Bouquets[n]->zapitBouquet && AllFavBouquetList->Bouquets[n]->zapitBouquet->bFav) {
|
|
CZapitChannel *ch = AllFavBouquetList->Bouquets[n]->zapitBouquet->getChannelByChannelID(channel_id);
|
|
if (ch == NULL) {
|
|
AllFavBouquetList->Bouquets[n]->zapitBouquet->addService((*chanlist)[selected]);
|
|
fav_found = false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
for (unsigned n = 0; n < blist->Bouquets.size() && !fav_found; n++) {
|
|
if (blist->Bouquets[n]->zapitBouquet && blist->Bouquets[n]->zapitBouquet->bFav) {
|
|
blist->Bouquets[n]->zapitBouquet->getChannels(blist->Bouquets[n]->channelList->channels, tvmode);
|
|
saveChanges();
|
|
fav_found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!fav_found) {
|
|
CNeutrinoApp::getInstance()->MarkFavoritesChanged();
|
|
CNeutrinoApp::getInstance()->MarkChannelsInit();
|
|
}
|
|
ret = 1;
|
|
break;
|
|
case 3: // reset new
|
|
case 4: // reset all new
|
|
if (select == 3) {
|
|
(*chanlist)[selected]->flags = CZapitChannel::UPDATED;
|
|
} else {
|
|
for (unsigned int j = 0 ; j < (*chanlist).size(); j++)
|
|
(*chanlist)[j]->flags = CZapitChannel::UPDATED;
|
|
}
|
|
CNeutrinoApp::getInstance()->MarkChannelsChanged();
|
|
/* if make_new_list == ON, signal to re-init services */
|
|
if(g_settings.make_new_list)
|
|
CNeutrinoApp::getInstance()->MarkChannelsInit();
|
|
break;
|
|
case 5: // clear channel history
|
|
{
|
|
CNeutrinoApp::getInstance()->channelList->getLastChannels().clear();
|
|
printf("%s:%d lastChList cleared\n", __FUNCTION__, __LINE__);
|
|
ret = -2; // exit channellist
|
|
}
|
|
break;
|
|
case 6: // settings
|
|
{
|
|
previous_channellist_additional = g_settings.channellist_additional;
|
|
COsdSetup osd_setup;
|
|
osd_setup.showContextChanlistMenu(this);
|
|
//FIXME check font/options changed ?
|
|
hide();
|
|
calcSize();
|
|
ret = -1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int CChannelList::exec()
|
|
{
|
|
displayNext = 0; // always start with current events
|
|
displayList = 1; // always start with event list
|
|
int nNewChannel = show();
|
|
if ( nNewChannel > -1 && nNewChannel < (int) (*chanlist).size()) {
|
|
if(this->historyMode && (*chanlist)[nNewChannel]) {
|
|
int new_mode = CNeutrinoApp::getInstance()->channelList->getLastChannels().get_mode((*chanlist)[nNewChannel]->getChannelID());
|
|
if(new_mode >= 0)
|
|
CNeutrinoApp::getInstance()->SetChannelMode(new_mode);
|
|
}
|
|
CNeutrinoApp::getInstance()->channelList->zapToChannel((*chanlist)[nNewChannel]);
|
|
}
|
|
|
|
return nNewChannel;
|
|
}
|
|
|
|
void CChannelList::calcSize()
|
|
{
|
|
CVFD::getInstance()->setMode(CVFD::MODE_MENU_UTF8 /*, name.c_str()*/);
|
|
|
|
// recalculate theight, fheight and footerHeight for a possilble change of fontsize factor
|
|
theight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->getHeight();
|
|
fheight = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getHeight();
|
|
fdescrheight = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getHeight();
|
|
|
|
if (fheight == 0)
|
|
fheight = 1; /* avoid div-by-zero crash on invalid font */
|
|
footerHeight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_FOOT]->getHeight()+6;
|
|
|
|
pig_on_win = ( (g_settings.channellist_additional == 2) /* with miniTV */ && (CNeutrinoApp::getInstance()->getMode() != NeutrinoMessages::mode_ts) );
|
|
// calculate width
|
|
full_width = pig_on_win ? (frameBuffer->getScreenWidth()-2*ConnectLineBox_Width) : frameBuffer->getScreenWidthRel();
|
|
|
|
if (g_settings.channellist_additional)
|
|
width = full_width / 3 * 2;
|
|
else
|
|
width = full_width;
|
|
|
|
// calculate height (the infobox below mainbox is handled outside height)
|
|
if (g_settings.channellist_show_infobox)
|
|
info_height = 2*fheight + fdescrheight + 10;
|
|
else
|
|
info_height = 0;
|
|
height = pig_on_win ? frameBuffer->getScreenHeight(): frameBuffer->getScreenHeightRel();
|
|
height = height - OFFSET_INTER - info_height;
|
|
|
|
// calculate x position
|
|
x = getScreenStartX(full_width);
|
|
if (x < ConnectLineBox_Width)
|
|
x = ConnectLineBox_Width;
|
|
|
|
// calculate header height
|
|
const int pic_h = 39;
|
|
theight = std::max(theight, pic_h);
|
|
|
|
// calculate max entrys in mainbox
|
|
listmaxshow = (height - theight - footerHeight) / fheight;
|
|
|
|
// recalculate height to avoid spaces between last entry in mainbox and footer
|
|
height = theight + listmaxshow*fheight + footerHeight;
|
|
|
|
// calculate y position
|
|
y = getScreenStartY(height + OFFSET_INTER + info_height);
|
|
|
|
// calculate width/height of right info_zone and pip-box
|
|
infozone_width = full_width - width;
|
|
pig_width = infozone_width;
|
|
if ( pig_on_win /* with miniTV */ )
|
|
pig_height = (pig_width * 9) / 16;
|
|
else
|
|
pig_height = 0;
|
|
infozone_height = height - theight - pig_height - footerHeight;
|
|
|
|
ChannelList_Rec = 0;
|
|
int icon_w, h;
|
|
int recmode_icon_max = 0;
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_REC, &icon_w, &h);
|
|
recmode_icon_max = std::max(recmode_icon_max, icon_w);
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_AUTO_SHIFT, &icon_w, &h);
|
|
recmode_icon_max = std::max(recmode_icon_max, icon_w);
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_PIP, &icon_w, &h);
|
|
recmode_icon_max = std::max(recmode_icon_max, icon_w);
|
|
|
|
for (uint32_t i = 0; i < (*chanlist).size(); i++) {
|
|
if (CRecordManager::getInstance()->GetRecordMode((*chanlist)[i]->getChannelID()) ||
|
|
(*chanlist)[i]->getChannelID() == CZapit::getInstance()->GetPipChannelID()) {
|
|
ChannelList_Rec = recmode_icon_max;
|
|
break;
|
|
}
|
|
}
|
|
if (ChannelList_Rec > 0)
|
|
ChannelList_Rec += 8;
|
|
}
|
|
|
|
bool CChannelList::updateSelection(int newpos)
|
|
{
|
|
bool actzap = false;
|
|
if((int) selected == newpos)
|
|
return actzap;
|
|
|
|
int prev_selected = selected;
|
|
selected = newpos;
|
|
if (move_state == beMoving) {
|
|
internalMoveChannel(prev_selected, selected);
|
|
} else {
|
|
unsigned int oldliststart = liststart;
|
|
|
|
liststart = (selected/listmaxshow)*listmaxshow;
|
|
if (oldliststart != liststart) {
|
|
paintBody();
|
|
updateVfd();
|
|
} else {
|
|
paintItem(prev_selected - liststart);
|
|
paintItem(selected - liststart);
|
|
showChannelLogo();
|
|
}
|
|
|
|
if(!edit_state && (new_zap_mode == 2 /* active */) && SameTP()) {
|
|
actzap = true;
|
|
zapTo(selected);
|
|
}
|
|
}
|
|
return actzap;
|
|
}
|
|
|
|
int CChannelList::getPrevNextBouquet(bool next)
|
|
{
|
|
bool found = true;
|
|
int dir = next ? 1 : -1;
|
|
int b_size = bouquetList->Bouquets.size(); /* bigger than 0 */
|
|
int nNext = (bouquetList->getActiveBouquetNumber() + b_size + dir) % b_size;
|
|
if(bouquetList->Bouquets[nNext]->channelList->isEmpty() ) {
|
|
found = false;
|
|
int n_old = nNext;
|
|
nNext = (nNext + b_size + dir) % b_size;
|
|
for (int i = nNext; i != n_old; i = (i + b_size + dir) % b_size) {
|
|
if( !bouquetList->Bouquets[i]->channelList->isEmpty() ) {
|
|
found = true;
|
|
nNext = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (found)
|
|
return nNext;
|
|
|
|
return -1;
|
|
}
|
|
|
|
#define CHANNEL_SMSKEY_TIMEOUT 800
|
|
/* return: >= 0 to zap, -1 on cancel, -3 on list mode change, -4 list edited, -2 zap but no restore old list/chan ?? */
|
|
int CChannelList::show()
|
|
{
|
|
int res = CHANLIST_CANCEL;
|
|
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
bool actzap = 0;
|
|
|
|
new_zap_mode = g_settings.channellist_new_zap_mode;
|
|
|
|
calcSize();
|
|
displayNext = false;
|
|
|
|
COSDFader fader(g_settings.theme.menu_Content_alpha);
|
|
fader.StartFadeIn();
|
|
CInfoClock::getInstance()->ClearDisplay();
|
|
paint();
|
|
|
|
int oldselected = selected;
|
|
int zapOnExit = false;
|
|
bool bShowBouquetList = false;
|
|
|
|
uint64_t timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_CHANLIST]);
|
|
|
|
bool loop=true;
|
|
bool dont_hide = false;
|
|
while (loop) {
|
|
g_RCInput->getMsgAbsoluteTimeout(&msg, &data, &timeoutEnd, true);
|
|
if ( msg <= CRCInput::RC_MaxRC )
|
|
timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_CHANLIST]);
|
|
|
|
bool empty = (*chanlist).empty();
|
|
if((msg == NeutrinoMessages::EVT_TIMER) && (data == fader.GetFadeTimer())) {
|
|
if(fader.FadeDone())
|
|
loop = false;
|
|
}
|
|
else if ( ( msg == CRCInput::RC_timeout ) || ( msg == (neutrino_msg_t)g_settings.key_channelList_cancel) ) {
|
|
if (move_state == beMoving) {
|
|
cancelMoveChannel();
|
|
} else if (edit_state) {
|
|
editMode(false);
|
|
paint();
|
|
} else {
|
|
res = CHANLIST_CANCEL;
|
|
if(!actzap) {
|
|
selected = oldselected;
|
|
} else {
|
|
res = CHANLIST_NO_RESTORE;
|
|
selected = selected_in_new_mode;
|
|
}
|
|
if(fader.StartFadeOut()) {
|
|
timeoutEnd = CRCInput::calcTimeoutEnd( 1 );
|
|
msg = 0;
|
|
} else
|
|
loop=false;
|
|
}
|
|
}
|
|
else if(!edit_state && !empty && msg == (neutrino_msg_t) g_settings.key_record) { //start direct recording from channellist
|
|
if((g_settings.recording_type != CNeutrinoApp::RECORDING_OFF) && SameTP() /* && !IS_WEBTV((*chanlist)[selected]->getChannelID()) */) {
|
|
printf("[neutrino channellist] start direct recording...\n");
|
|
hide();
|
|
if (!CRecordManager::getInstance()->Record((*chanlist)[selected]->getChannelID())) {
|
|
paint();
|
|
} else {
|
|
selected = oldselected;
|
|
loop=false;
|
|
}
|
|
}
|
|
}
|
|
else if(!edit_state && !empty && msg == CRCInput::RC_stop ) { //stop recording
|
|
if(CRecordManager::getInstance()->RecordingStatus((*chanlist)[selected]->getChannelID())){
|
|
int recmode = CRecordManager::getInstance()->GetRecordMode((*chanlist)[selected]->getChannelID());
|
|
bool timeshift = recmode & CRecordManager::RECMODE_TSHIFT;
|
|
bool tsplay = CMoviePlayerGui::getInstance().timeshift;
|
|
if (recmode && !(timeshift && tsplay))
|
|
{
|
|
if (CRecordManager::getInstance()->AskToStop((*chanlist)[selected]->getChannelID()))
|
|
{
|
|
CRecordManager::getInstance()->Stop((*chanlist)[selected]->getChannelID());
|
|
calcSize();
|
|
paintBody();
|
|
}
|
|
}else{
|
|
// stop TSHIFT: go to play mode
|
|
g_RCInput->postMsg (msg, data);
|
|
res = CHANLIST_CANCEL_ALL;
|
|
loop = false;
|
|
}
|
|
}
|
|
}
|
|
else if (!empty && ((msg == CRCInput::RC_red) || (msg == CRCInput::RC_epg))) {
|
|
if (edit_state) {
|
|
if (move_state != beMoving && msg == CRCInput::RC_red)
|
|
deleteChannel();
|
|
} else {
|
|
hide();
|
|
|
|
/* RETURN_EXIT_ALL on FAV/SAT buttons or messages_return::cancel_all from CNeutrinoApp::getInstance()->handleMsg() */
|
|
if ( g_EventList->exec((*chanlist)[selected]->getChannelID(), (*chanlist)[selected]->getName()) == menu_return::RETURN_EXIT_ALL) {
|
|
res = CHANLIST_CANCEL_ALL;
|
|
loop = false;
|
|
} else {
|
|
paint();
|
|
timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_CHANLIST]);
|
|
}
|
|
}
|
|
}
|
|
else if (!empty && msg == CRCInput::RC_yellow) {
|
|
if (edit_state) {
|
|
beginMoveChannel();
|
|
paintItem(selected - liststart);
|
|
} else {
|
|
bShowBouquetList = true;
|
|
loop = false;
|
|
}
|
|
}
|
|
else if (CNeutrinoApp::getInstance()->listModeKey(msg)) {
|
|
if (!edit_state) {
|
|
//FIXME: what about LIST_MODE_WEBTV?
|
|
int newmode = msg == CRCInput::RC_sat ? LIST_MODE_SAT : LIST_MODE_FAV;
|
|
CNeutrinoApp::getInstance()->SetChannelMode(newmode);
|
|
res = CHANLIST_CHANGE_MODE;
|
|
loop = false;
|
|
}
|
|
}
|
|
else if (!edit_state && msg == CRCInput::RC_setup) {
|
|
fader.StopFade();
|
|
int ret = doChannelMenu();
|
|
if (ret > 0) {
|
|
/* select next entry */
|
|
if (selected + 1 < (*chanlist).size())
|
|
selected++;
|
|
}
|
|
if (ret == -2) // exit channellist
|
|
loop = false;
|
|
else {
|
|
if (ret != 0)
|
|
paint();
|
|
timeoutEnd = CRCInput::calcTimeoutEnd(g_settings.timing[SNeutrinoSettings::TIMING_CHANLIST]);
|
|
}
|
|
}
|
|
else if (!empty && msg == (neutrino_msg_t) g_settings.key_list_start) {
|
|
actzap = updateSelection(0);
|
|
}
|
|
else if (!empty && msg == (neutrino_msg_t) g_settings.key_list_end) {
|
|
actzap = updateSelection((*chanlist).size()-1);
|
|
}
|
|
else if (!empty && (msg == CRCInput::RC_up || (int)msg == g_settings.key_pageup ||
|
|
msg == CRCInput::RC_down || (int)msg == g_settings.key_pagedown))
|
|
{
|
|
displayList = 1;
|
|
int new_selected = UpDownKey((*chanlist), msg, listmaxshow, selected);
|
|
if (new_selected >= 0)
|
|
actzap = updateSelection(new_selected);
|
|
}
|
|
else if (!edit_state && (msg == (neutrino_msg_t)g_settings.key_bouquet_up ||
|
|
msg == (neutrino_msg_t)g_settings.key_bouquet_down)) {
|
|
if (dline)
|
|
dline->kill(); //kill details line on change to next page
|
|
if (!bouquetList->Bouquets.empty()) {
|
|
int nNext = getPrevNextBouquet(msg == (neutrino_msg_t)g_settings.key_bouquet_up);
|
|
if(nNext >= 0) {
|
|
bouquetList->activateBouquet(nNext, false);
|
|
res = bouquetList->showChannelList();
|
|
loop = false;
|
|
}
|
|
dont_hide = true;
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_ok ) {
|
|
if (!empty) {
|
|
if (move_state == beMoving) {
|
|
finishMoveChannel();
|
|
} else if (edit_state) {
|
|
zapTo(selected);
|
|
actzap = true;
|
|
oldselected = selected;
|
|
paintBody(); // refresh zapped vs selected
|
|
} else if(SameTP()) {
|
|
zapOnExit = true;
|
|
loop=false;
|
|
}
|
|
}
|
|
}
|
|
else if (!edit_state && ( msg == CRCInput::RC_spkr ) && new_zap_mode ) {
|
|
if(CNeutrinoApp::getInstance()->getMode() != NeutrinoMessages::mode_ts) {
|
|
switch (new_zap_mode) {
|
|
case 2: /* active */
|
|
new_zap_mode = 1; /* allow */
|
|
break;
|
|
case 1: /* allow */
|
|
new_zap_mode = 2; /* active */
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
paintButtonBar(SameTP());
|
|
}
|
|
}
|
|
else if (!empty && CRCInput::isNumeric(msg) && (this->historyMode || g_settings.sms_channel)) {
|
|
if (this->historyMode) { //numeric zap
|
|
selected = CRCInput::getNumericValue(msg);
|
|
zapOnExit = true;
|
|
loop = false;
|
|
}
|
|
else if(g_settings.sms_channel) {
|
|
unsigned char smsKey = 0;
|
|
SMSKeyInput smsInput;
|
|
smsInput.setTimeout(CHANNEL_SMSKEY_TIMEOUT);
|
|
|
|
do {
|
|
smsKey = smsInput.handleMsg(msg);
|
|
//printf("SMS new key: %c\n", smsKey);
|
|
g_RCInput->getMsg_ms(&msg, &data, CHANNEL_SMSKEY_TIMEOUT-100);
|
|
} while ((msg >= CRCInput::RC_1) && (msg <= CRCInput::RC_9));
|
|
|
|
if (msg == CRCInput::RC_timeout || msg == CRCInput::RC_nokey) {
|
|
uint32_t i;
|
|
for(i = selected+1; i < (*chanlist).size(); i++) {
|
|
char firstCharOfTitle = (*chanlist)[i]->getName().c_str()[0];
|
|
if(tolower(firstCharOfTitle) == smsKey) {
|
|
//printf("SMS chan found was= %d selected= %d i= %d %s\n", was_sms, selected, i, (*chanlist)[i]->channel->getName().c_str());
|
|
break;
|
|
}
|
|
}
|
|
if(i >= (*chanlist).size()) {
|
|
for(i = 0; i < (*chanlist).size(); i++) {
|
|
char firstCharOfTitle = (*chanlist)[i]->getName().c_str()[0];
|
|
if(tolower(firstCharOfTitle) == smsKey) {
|
|
//printf("SMS chan found was= %d selected= %d i= %d %s\n", was_sms, selected, i, (*chanlist)[i]->channel->getName().c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(i < (*chanlist).size())
|
|
updateSelection(i);
|
|
|
|
smsInput.resetOldKey();
|
|
}
|
|
}
|
|
}
|
|
else if(CRCInput::isNumeric(msg)) {
|
|
if (!edit_state) {
|
|
//pushback key if...
|
|
selected = oldselected;
|
|
g_RCInput->postMsg( msg, data );
|
|
loop = false;
|
|
}
|
|
}
|
|
else if (!empty && msg == CRCInput::RC_blue )
|
|
{
|
|
if (edit_state) { // rename
|
|
if (move_state != beMoving)
|
|
renameChannel();
|
|
} else {
|
|
if (g_settings.channellist_additional)
|
|
displayList = !displayList;
|
|
else
|
|
displayNext = !displayNext;
|
|
|
|
paint();
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_green )
|
|
{
|
|
if (edit_state) {
|
|
if (move_state != beMoving)
|
|
addChannel();
|
|
} else {
|
|
int mode = CNeutrinoApp::getInstance()->GetChannelMode();
|
|
if(mode != LIST_MODE_FAV) {
|
|
g_settings.channellist_sort_mode++;
|
|
if(g_settings.channellist_sort_mode > SORT_MAX-1)
|
|
g_settings.channellist_sort_mode = SORT_ALPHA;
|
|
CNeutrinoApp::getInstance()->SetChannelMode(mode);
|
|
oldselected = selected;
|
|
paint();
|
|
}
|
|
}
|
|
}
|
|
else if (!empty && edit_state && move_state != beMoving && msg == CRCInput::RC_stop )
|
|
{
|
|
lockChannel();
|
|
}
|
|
else if (!empty && edit_state && move_state != beMoving && msg == CRCInput::RC_forward )
|
|
{
|
|
moveChannelToBouquet();
|
|
}
|
|
#ifdef ENABLE_PIP
|
|
else if (!empty && ((msg == CRCInput::RC_play) || (msg == (neutrino_msg_t) g_settings.key_pip_close))) {
|
|
if(SameTP()) {
|
|
if (CZapit::getInstance()->GetPipChannelID() == (*chanlist)[selected]->getChannelID()) {
|
|
g_Zapit->stopPip();
|
|
calcSize();
|
|
paintBody();
|
|
} else {
|
|
handleMsg(NeutrinoMessages::EVT_PROGRAMLOCKSTATUS, 0x100, true);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
else if (!empty && ((msg == CRCInput::RC_info) || (msg == CRCInput::RC_help))) {
|
|
hide();
|
|
CChannelEvent *p_event=NULL;
|
|
if (displayNext)
|
|
p_event = &((*chanlist)[selected]->nextEvent);
|
|
|
|
if(p_event && p_event->eventID)
|
|
g_EpgData->show((*chanlist)[selected]->getChannelID(), p_event->eventID, &(p_event->startTime));
|
|
else
|
|
g_EpgData->show((*chanlist)[selected]->getChannelID());
|
|
|
|
paint();
|
|
} else if (msg == NeutrinoMessages::EVT_SERVICESCHANGED || msg == NeutrinoMessages::EVT_BOUQUETSCHANGED) {
|
|
g_RCInput->postMsg(msg, data);
|
|
loop = false;
|
|
res = CHANLIST_CANCEL_ALL;
|
|
} else {
|
|
if ( CNeutrinoApp::getInstance()->handleMsg( msg, data ) & messages_return::cancel_all ) {
|
|
loop = false;
|
|
res = CHANLIST_CANCEL_ALL;
|
|
}
|
|
}
|
|
}
|
|
|
|
paint_events(-2); // cancel paint_events thread
|
|
|
|
if (move_state == beMoving)
|
|
cancelMoveChannel();
|
|
if (edit_state)
|
|
editMode(false);
|
|
|
|
if(!dont_hide){
|
|
if (new_zap_mode && (g_settings.channellist_new_zap_mode != new_zap_mode))
|
|
g_settings.channellist_new_zap_mode = new_zap_mode;
|
|
new_zap_mode = 0;
|
|
|
|
hide();
|
|
fader.StopFade();
|
|
}
|
|
|
|
if (bShowBouquetList) {
|
|
res = bouquetList->exec(true);
|
|
printf("CChannelList:: bouquetList->exec res %d\n", res);
|
|
}
|
|
|
|
|
|
if(NeutrinoMessages::mode_ts == CNeutrinoApp::getInstance()->getMode())
|
|
return -1;
|
|
|
|
if(zapOnExit)
|
|
res = selected;
|
|
|
|
printf("CChannelList::show *********** res %d\n", res);
|
|
return(res);
|
|
}
|
|
|
|
void CChannelList::hide()
|
|
{
|
|
if ((g_settings.channellist_additional == 2) || (previous_channellist_additional == 2)) // with miniTV
|
|
{
|
|
if (cc_minitv)
|
|
delete cc_minitv;
|
|
cc_minitv = NULL;
|
|
}
|
|
|
|
header->kill();
|
|
if (CChannelLogo){
|
|
CChannelLogo->kill();
|
|
delete CChannelLogo;
|
|
CChannelLogo = NULL;
|
|
}
|
|
|
|
frameBuffer->paintBackgroundBoxRel(x, y, full_width, height + OFFSET_INTER + info_height);
|
|
clearItem2DetailsLine();
|
|
CInfoClock::getInstance()->enableInfoClock(!CInfoClock::getInstance()->isBlocked());
|
|
}
|
|
|
|
bool CChannelList::showInfo(int number, int epgpos)
|
|
{
|
|
CZapitChannel* channel = getChannel(number);
|
|
if(channel == NULL)
|
|
return false;
|
|
|
|
g_InfoViewer->showTitle(channel, true, epgpos); // UTF-8
|
|
return true;
|
|
}
|
|
|
|
int CChannelList::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data, bool pip)
|
|
{
|
|
if (msg != NeutrinoMessages::EVT_PROGRAMLOCKSTATUS) // right now the only message handled here.
|
|
return messages_return::unhandled;
|
|
checkLockStatus(data, pip);
|
|
return messages_return::handled;
|
|
|
|
}
|
|
|
|
bool CChannelList::checkLockStatus(neutrino_msg_data_t data, bool pip)
|
|
{
|
|
bool startvideo = true;
|
|
//printf("===> program-lock-status: %d zp: %d\n", data, zapProtection != NULL);
|
|
if (g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_NEVER)
|
|
goto out;
|
|
|
|
// 0x100 als FSK-Status zeigt an, dass (noch) kein EPG zu einem Kanal der NICHT angezeigt
|
|
// werden sollte (vorgesperrt) da ist
|
|
// oder das bouquet des Kanals ist vorgesperrt
|
|
|
|
if (zapProtection != NULL) {
|
|
zapProtection->fsk = data;
|
|
startvideo = false;
|
|
goto out;
|
|
}
|
|
|
|
// require password if either
|
|
// CHANGETOLOCK mode and channel/bouquet is pre locked (0x100)
|
|
// ONSIGNAL mode and fsk(data) is beyond configured value
|
|
// if program has already been unlocked, dont require pin
|
|
if (data < (neutrino_msg_data_t)g_settings.parentallock_lockage)
|
|
goto out;
|
|
|
|
/* already unlocked */
|
|
if ((*chanlist)[selected]->last_unlocked_EPGid == g_RemoteControl->current_EPGid && g_RemoteControl->current_EPGid != 0)
|
|
goto out;
|
|
|
|
/* PARENTALLOCK_PROMPT_CHANGETOLOCKED: only pre-locked channels, don't care for fsk sent in SI */
|
|
if (g_settings.parentallock_prompt == PARENTALLOCK_PROMPT_CHANGETOLOCKED && data < 0x100)
|
|
goto out;
|
|
|
|
/* if a pre-locked channel is inside the zap time, open it. */
|
|
if (data >= 0x100 && (*chanlist)[selected]->last_unlocked_time + g_settings.parentallock_zaptime * 60 > time_monotonic())
|
|
goto out;
|
|
|
|
if (pip && (*chanlist)[selected]->Locked() == g_settings.parentallock_defaultlocked)
|
|
goto out;
|
|
|
|
/* OK, let's ask for a PIN */
|
|
if (!pip) {
|
|
g_RemoteControl->is_video_started = true;
|
|
g_RemoteControl->stopvideo();
|
|
//printf("stopped video\n");
|
|
}
|
|
zapProtection = new CZapProtection(g_settings.parentallock_pincode, data);
|
|
|
|
if (zapProtection->check())
|
|
{
|
|
// remember it for the next time
|
|
/* data < 0x100: lock age -> remember EPG ID */
|
|
if (data < 0x100)
|
|
(*chanlist)[selected]->last_unlocked_EPGid = g_RemoteControl->current_EPGid;
|
|
else
|
|
{
|
|
/* data >= 0x100: pre-locked bouquet -> remember unlock time */
|
|
(*chanlist)[selected]->last_unlocked_time = time_monotonic();
|
|
int bnum = bouquetList->getActiveBouquetNumber();
|
|
/* unlock only real locked bouquet, not whole satellite or all channels! */
|
|
if (bnum >= 0 && bouquetList->Bouquets[bnum]->zapitBouquet &&
|
|
bouquetList->Bouquets[bnum]->zapitBouquet->bLocked != g_settings.parentallock_defaultlocked)
|
|
{
|
|
/* unlock the whole bouquet */
|
|
int i;
|
|
for (i = 0; i < bouquetList->Bouquets[bnum]->channelList->getSize(); i++)
|
|
bouquetList->Bouquets[bnum]->channelList->getChannelFromIndex(i)->last_unlocked_time = (*chanlist)[selected]->last_unlocked_time;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* last_unlocked_time == 0 is the magic to tell zapTo() to not record the time.
|
|
Without that, zapping to a locked channel twice would open it without the PIN */
|
|
(*chanlist)[selected]->last_unlocked_time = 0;
|
|
startvideo = false;
|
|
}
|
|
delete zapProtection;
|
|
zapProtection = NULL;
|
|
|
|
out:
|
|
if (startvideo) {
|
|
if(pip) {
|
|
#ifdef ENABLE_PIP
|
|
if (CNeutrinoApp::getInstance()->StartPip((*chanlist)[selected]->getChannelID())) {
|
|
calcSize();
|
|
paintBody();
|
|
}
|
|
#endif
|
|
} else
|
|
g_RemoteControl->startvideo();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CChannelList::adjustToChannelID(const t_channel_id channel_id)
|
|
{
|
|
printf("CChannelList::adjustToChannelID me %p [%s] list size %d channel_id %" PRIx64 "\n", this, getName(), (int)(*chanlist).size(), channel_id);
|
|
selected_chid = channel_id;
|
|
for (unsigned int i = 0; i < (*chanlist).size(); i++) {
|
|
if ((*chanlist)[i]->getChannelID() == channel_id) {
|
|
selected = i;
|
|
tuned = i;
|
|
return true;
|
|
}
|
|
}
|
|
//printf("CChannelList::adjustToChannelID me %x to %llx bToo %s FAILED\n", (int) this, channel_id, bToo ? "yes" : "no");fflush(stdout);
|
|
|
|
return false;
|
|
}
|
|
|
|
#if 0
|
|
int CChannelList::hasChannel(int nChannelNr)
|
|
{
|
|
for (uint32_t i=0; i<(*chanlist).size(); i++) {
|
|
if (getKey(i) == nChannelNr)
|
|
return(i);
|
|
}
|
|
return(-1);
|
|
}
|
|
#endif
|
|
|
|
int CChannelList::hasChannelID(t_channel_id channel_id)
|
|
{
|
|
for (uint32_t i=0; i < (*chanlist).size(); i++) {
|
|
if ((*chanlist)[i]->getChannelID() == channel_id)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// for adjusting bouquet's channel list after numzap or quickzap
|
|
void CChannelList::setSelected( int nChannelNr)
|
|
{
|
|
//printf("CChannelList::setSelected me %s %d -> %s\n", name.c_str(), nChannelNr, (nChannelNr < (*chanlist).size() && (*chanlist)[nChannelNr] != NULL) ? (*chanlist)[nChannelNr]->getName().c_str() : "********* NONE *********");
|
|
//FIXME real difference between tuned and selected ?!
|
|
selected_chid = 0;
|
|
tuned = nChannelNr;
|
|
if (nChannelNr < (int) (*chanlist).size()) {
|
|
selected = nChannelNr;
|
|
selected_chid = (*chanlist)[tuned]->getChannelID();
|
|
}
|
|
}
|
|
|
|
// -- Zap to channel with channel_id
|
|
bool CChannelList::zapTo_ChannelID(const t_channel_id channel_id, bool force)
|
|
{
|
|
printf("**************************** CChannelList::zapTo_ChannelID %" PRIx64 "\n", channel_id);
|
|
for (unsigned int i = 0; i < (*chanlist).size(); i++) {
|
|
if ((*chanlist)[i]->getChannelID() == channel_id) {
|
|
zapTo(i, force);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CChannelList::showEmptyError()
|
|
{
|
|
if ((*chanlist).empty()) {
|
|
DisplayErrorMessage(g_Locale->getText(LOCALE_CHANNELLIST_NONEFOUND)); // UTF-8
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* forceStoreToLastChannels defaults to false */
|
|
/* TODO make this private to call only from "current" list, where selected/pos not means channel number */
|
|
void CChannelList::zapTo(int pos, bool force)
|
|
{
|
|
if(showEmptyError())
|
|
return;
|
|
|
|
if ( (pos >= (signed int) (*chanlist).size()) || (pos < 0) ) {
|
|
pos = 0;
|
|
}
|
|
CZapitChannel* chan = (*chanlist)[pos];
|
|
|
|
zapToChannel(chan, force);
|
|
tuned = pos;
|
|
if(edit_state || new_zap_mode == 2 /* active */)
|
|
selected_in_new_mode = pos;
|
|
else
|
|
selected = pos;
|
|
}
|
|
|
|
/* to replace zapTo_ChannelID and zapTo from "whole" list ? */
|
|
void CChannelList::zapToChannel(CZapitChannel *channel, bool force)
|
|
{
|
|
if(showEmptyError())
|
|
return;
|
|
|
|
if(channel == NULL)
|
|
return;
|
|
|
|
/* we record when we switched away from a channel, so that the parental-PIN code can
|
|
check for timeout. last_unlocked_time == 0 means: the PIN was not entered
|
|
"tuned" is the *old* channel, before zap */
|
|
if (tuned < (*chanlist).size() && (*chanlist)[tuned]->last_unlocked_time != 0)
|
|
(*chanlist)[tuned]->last_unlocked_time = time_monotonic();
|
|
|
|
printf("**************************** CChannelList::zapToChannel me %p %s tuned %d new %s -> %" PRIx64 "\n", this, name.c_str(), tuned, channel->getName().c_str(), channel->getChannelID());
|
|
if(tuned < (*chanlist).size())
|
|
selected_chid = (*chanlist)[tuned]->getChannelID();
|
|
|
|
if(force || (selected_chid != channel->getChannelID())) {
|
|
if ((g_settings.radiotext_enable) && ((CNeutrinoApp::getInstance()->getMode()) == NeutrinoMessages::mode_radio) && (g_Radiotext))
|
|
{
|
|
// stop radiotext PES decoding before zapping
|
|
g_Radiotext->radiotext_stop();
|
|
}
|
|
|
|
selected_chid = channel->getChannelID();
|
|
g_RemoteControl->zapTo_ChannelID(selected_chid, channel->getName(), channel->number, (channel->Locked() == g_settings.parentallock_defaultlocked));
|
|
CNeutrinoApp::getInstance()->adjustToChannelID(channel->getChannelID());
|
|
}
|
|
if(new_zap_mode != 2 /* not active */) {
|
|
/* remove recordModeActive from infobar */
|
|
if(g_settings.auto_timeshift && !CNeutrinoApp::getInstance()->recordingstatus)
|
|
g_InfoViewer->handleMsg(NeutrinoMessages::EVT_RECORDMODE, 0);
|
|
|
|
g_RCInput->postMsg( NeutrinoMessages::SHOW_INFOBAR, 0 );
|
|
CNeutrinoApp::getInstance()->channelList->getLastChannels().set_mode(channel->getChannelID());
|
|
}
|
|
}
|
|
|
|
/* Called only from "all" channel list */
|
|
int CChannelList::numericZap(int key)
|
|
{
|
|
int res = -1;
|
|
if(showEmptyError())
|
|
return res;
|
|
|
|
// -- quickzap "0" to last seen channel...
|
|
if (key == g_settings.key_lastchannel) {
|
|
t_channel_id channel_id = lastChList.getlast(1);
|
|
if(channel_id && SameTP(channel_id)) {
|
|
lastChList.clear_storedelay(); // ignore store delay
|
|
int new_mode = lastChList.get_mode(channel_id);
|
|
if(new_mode >= 0)
|
|
CNeutrinoApp::getInstance()->SetChannelMode(new_mode);
|
|
zapTo_ChannelID(channel_id);
|
|
res = 0;
|
|
}
|
|
return res;
|
|
}
|
|
if ((key == g_settings.key_zaphistory) || (key == g_settings.key_current_transponder)) {
|
|
if((!autoshift && CNeutrinoApp::getInstance()->recordingstatus) || (key == g_settings.key_current_transponder)) {
|
|
CChannelList * orgList = CNeutrinoApp::getInstance()->channelList;
|
|
CChannelList * channelList = new CChannelList(g_Locale->getText(LOCALE_CHANNELLIST_CURRENT_TP), false, true);
|
|
|
|
if(key == g_settings.key_current_transponder) {
|
|
t_channel_id recid = (*chanlist)[selected]->getChannelID() >> 16;
|
|
for ( unsigned int i = 0 ; i < (*orgList->chanlist).size(); i++) {
|
|
if(((*orgList->chanlist)[i]->getChannelID() >> 16) == recid)
|
|
channelList->addChannel((*orgList->chanlist)[i]);
|
|
}
|
|
} else {
|
|
for ( unsigned int i = 0 ; i < (*orgList->chanlist).size(); i++) {
|
|
if(SameTP((*orgList->chanlist)[i]))
|
|
channelList->addChannel((*orgList->chanlist)[i]);
|
|
}
|
|
}
|
|
if ( !channelList->isEmpty()) {
|
|
channelList->adjustToChannelID(orgList->getActiveChannel_ChannelID());
|
|
this->frameBuffer->paintBackground();
|
|
res = channelList->exec();
|
|
CVFD::getInstance()->setMode(CVFD::MODE_TVRADIO);
|
|
}
|
|
delete channelList;
|
|
return res;
|
|
}
|
|
// -- zap history bouquet, similar to "0" quickzap, but shows a menue of last channels
|
|
if (this->lastChList.size() > 1) {
|
|
CChannelList * channelList = new CChannelList(g_Locale->getText(LOCALE_CHANNELLIST_HISTORY), true, true);
|
|
|
|
for(unsigned int i = 1; i < this->lastChList.size() ; ++i) {
|
|
t_channel_id channel_id = this->lastChList.getlast(i);
|
|
if(channel_id) {
|
|
CZapitChannel* channel = getChannel(channel_id);
|
|
if(channel) channelList->addChannel(channel);
|
|
}
|
|
}
|
|
if ( !channelList->isEmpty() ) {
|
|
this->frameBuffer->paintBackground();
|
|
res = channelList->exec();
|
|
CVFD::getInstance()->setMode(CVFD::MODE_TVRADIO);
|
|
}
|
|
delete channelList;
|
|
}
|
|
return res;
|
|
}
|
|
size_t maxchansize = MaxChanNr().size();
|
|
int fw = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getMaxDigitWidth();
|
|
int sx = maxchansize * fw + (fw/2);
|
|
int sy = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getHeight() + 6;
|
|
|
|
int ox = frameBuffer->getScreenX() + (frameBuffer->getScreenWidth() - sx)/2;
|
|
int oy = frameBuffer->getScreenY() + (frameBuffer->getScreenHeight() - sy)/2;
|
|
char valstr[10];
|
|
int chn = CRCInput::getNumericValue(key);
|
|
int pos = 1;
|
|
int lastchan= -1;
|
|
bool doZap = false;
|
|
bool showEPG = false;
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
g_InfoViewer->setSwitchMode(CInfoViewer::IV_MODE_NUMBER_ZAP);
|
|
|
|
while(1) {
|
|
if (lastchan != chn) {
|
|
snprintf(valstr, sizeof(valstr), "%d", chn);
|
|
|
|
while(strlen(valstr) < maxchansize)
|
|
strcat(valstr,"-"); //"_"
|
|
frameBuffer->paintBoxRel(ox, oy, sx, sy, COL_INFOBAR_PLUS_0);
|
|
|
|
for (int i = maxchansize-1; i >= 0; i--) {
|
|
valstr[i+ 1] = 0;
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->RenderString(ox+fw/3+ i*fw, oy+sy-3, sx, &valstr[i], COL_INFOBAR_TEXT);
|
|
}
|
|
|
|
showInfo(chn);
|
|
lastchan = chn;
|
|
}
|
|
|
|
g_RCInput->getMsg( &msg, &data, g_settings.timing[SNeutrinoSettings::TIMING_NUMERICZAP] * 10 );
|
|
|
|
if (msg == CRCInput::RC_timeout || msg == CRCInput::RC_ok) {
|
|
doZap = true;
|
|
break;
|
|
}
|
|
else if (CNeutrinoApp::getInstance()->listModeKey(msg) || msg == CRCInput::RC_right) {
|
|
// do nothing
|
|
}
|
|
else if (CRCInput::isNumeric(msg)) {
|
|
if (pos == 4) {
|
|
chn = 0;
|
|
pos = 1;
|
|
} else {
|
|
chn *= 10;
|
|
pos++;
|
|
}
|
|
chn += CRCInput::getNumericValue(msg);
|
|
}
|
|
else if (msg == (neutrino_msg_t)g_settings.key_quickzap_down) {
|
|
if(chn > 1)
|
|
chn--;
|
|
}
|
|
else if (msg == (neutrino_msg_t)g_settings.key_quickzap_up) {
|
|
chn++;
|
|
}
|
|
else if (msg == CRCInput::RC_left) {
|
|
/* "backspace" */
|
|
if(pos > 0) {
|
|
pos--;
|
|
if(chn > 10)
|
|
chn /= 10;
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_home)
|
|
{
|
|
break;
|
|
}
|
|
else if (msg == CRCInput::RC_red) {
|
|
showEPG = true;
|
|
break;
|
|
}
|
|
else if (CNeutrinoApp::getInstance()->handleMsg( msg, data ) & messages_return::cancel_all) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
frameBuffer->paintBackgroundBoxRel(ox, oy, sx, sy);
|
|
|
|
CZapitChannel* chan = getChannel(chn);
|
|
if (doZap) {
|
|
if(g_settings.timing[SNeutrinoSettings::TIMING_INFOBAR] == 0)
|
|
g_InfoViewer->killTitle();
|
|
|
|
if(chan && SameTP(chan)) {
|
|
zapToChannel(chan);
|
|
res = 0;
|
|
} else
|
|
g_InfoViewer->killTitle();
|
|
|
|
} else {
|
|
g_InfoViewer->showTitle(getActiveChannel(), true);
|
|
g_InfoViewer->killTitle();
|
|
if (chan && showEPG)
|
|
g_EventList->exec(chan->getChannelID(), chan->getName());
|
|
}
|
|
g_InfoViewer->resetSwitchMode();
|
|
return res;
|
|
}
|
|
|
|
CZapitChannel* CChannelList::getPrevNextChannel(int key, unsigned int &sl)
|
|
{
|
|
if(sl >= (*chanlist).size())
|
|
sl = (*chanlist).size()-1;
|
|
|
|
CZapitChannel* channel = NULL;
|
|
int bsize = bouquetList->Bouquets.size();
|
|
int bactive = bouquetList->getActiveBouquetNumber();
|
|
|
|
if(!g_settings.zap_cycle && bsize > 1) {
|
|
size_t cactive = sl;
|
|
|
|
printf("CChannelList::getPrevNextChannel: selected %d total %d active bouquet %d total %d\n", (int)cactive, (int)(*chanlist).size(), bactive, bsize);
|
|
if ((key == g_settings.key_quickzap_down) || (key == CRCInput::RC_left)) {
|
|
if(cactive == 0) {
|
|
bactive = getPrevNextBouquet(false);
|
|
if (bactive >= 0) {
|
|
bouquetList->activateBouquet(bactive, false);
|
|
cactive = bouquetList->Bouquets[bactive]->channelList->getSize() - 1;
|
|
}
|
|
} else
|
|
--cactive;
|
|
}
|
|
else if ((key == g_settings.key_quickzap_up) || (key == CRCInput::RC_right)) {
|
|
cactive++;
|
|
if(cactive >= (*chanlist).size()) {
|
|
bactive = getPrevNextBouquet(true);
|
|
if (bactive >= 0) {
|
|
bouquetList->activateBouquet(bactive, false);
|
|
cactive = 0;
|
|
}
|
|
}
|
|
}
|
|
sl = cactive;
|
|
channel = bouquetList->Bouquets[bactive]->channelList->getChannelFromIndex(cactive);
|
|
printf("CChannelList::getPrevNextChannel: selected %u total %d active bouquet %d total %d channel %x (%s)\n",
|
|
cactive, (*chanlist).size(), bactive, bsize, (int) channel, channel ? channel->getName().c_str(): "");
|
|
} else {
|
|
if ((key == g_settings.key_quickzap_down) || (key == CRCInput::RC_left)) {
|
|
if(sl == 0)
|
|
sl = (*chanlist).size()-1;
|
|
else
|
|
sl--;
|
|
}
|
|
else if ((key==g_settings.key_quickzap_up) || (key == CRCInput::RC_right)) {
|
|
sl = (sl+1)%(*chanlist).size();
|
|
}
|
|
channel = (*chanlist)[sl];
|
|
}
|
|
return channel;
|
|
}
|
|
|
|
void CChannelList::virtual_zap_mode(bool up)
|
|
{
|
|
if(showEmptyError())
|
|
return;
|
|
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
|
|
unsigned int sl = selected;
|
|
int old_bactive = bouquetList->getActiveBouquetNumber();
|
|
int bactive = old_bactive;
|
|
|
|
CZapitChannel* channel = getPrevNextChannel(up ? CRCInput::RC_right : CRCInput::RC_left, sl);
|
|
|
|
bool doZap = false;
|
|
bool showEPG = false;
|
|
int epgpos = 0;
|
|
|
|
while(1) {
|
|
if (channel)
|
|
g_InfoViewer->showTitle(channel, true, epgpos);
|
|
|
|
epgpos = 0;
|
|
g_RCInput->getMsg(&msg, &data, 15*10); // 15 seconds, not user changable
|
|
|
|
if ((msg == CRCInput::RC_left) || (msg == CRCInput::RC_right)) {
|
|
channel = bouquetList->Bouquets[bactive]->channelList->getPrevNextChannel(msg, sl);
|
|
bactive = bouquetList->getActiveBouquetNumber();
|
|
}
|
|
else if (msg == CRCInput::RC_up || msg == CRCInput::RC_down) {
|
|
epgpos = (msg == CRCInput::RC_up) ? -1 : 1;
|
|
}
|
|
else if ((msg == CRCInput::RC_ok) || (msg == CRCInput::RC_home) || (msg == CRCInput::RC_timeout)) {
|
|
if(msg == CRCInput::RC_ok)
|
|
doZap = true;
|
|
break;
|
|
}
|
|
else if (msg == CRCInput::RC_red) {
|
|
showEPG = true;
|
|
break;
|
|
}
|
|
else if (CNeutrinoApp::getInstance()->handleMsg(msg, data) & messages_return::cancel_all) {
|
|
break;
|
|
}
|
|
}
|
|
g_InfoViewer->resetSwitchMode(); //disable virtual_zap_mode
|
|
|
|
if (doZap) {
|
|
if(g_settings.timing[SNeutrinoSettings::TIMING_INFOBAR] == 0)
|
|
g_InfoViewer->killTitle();
|
|
if(channel && SameTP(channel))
|
|
zapToChannel(channel);
|
|
else
|
|
g_InfoViewer->killTitle();
|
|
} else {
|
|
g_InfoViewer->showTitle(getActiveChannel(), true);
|
|
g_InfoViewer->killTitle();
|
|
bouquetList->activateBouquet(old_bactive, false);
|
|
|
|
if (showEPG && channel)
|
|
g_EventList->exec(channel->getChannelID(), channel->getName());
|
|
}
|
|
}
|
|
|
|
bool CChannelList::quickZap(int key, bool /* cycle */)
|
|
{
|
|
if((*chanlist).empty())
|
|
return true;
|
|
|
|
unsigned int sl = selected;
|
|
/* here selected value doesnt matter, zap will do adjust */
|
|
CZapitChannel* channel = getPrevNextChannel(key, sl);
|
|
bool ret = false;
|
|
if(channel && SameTP(channel)) {
|
|
CNeutrinoApp::getInstance()->channelList->zapToChannel(channel);
|
|
ret = true;
|
|
}
|
|
g_RCInput->clearRCMsg(); //FIXME test for n.103
|
|
return ret;
|
|
}
|
|
|
|
void CChannelList::paintDetails(int index)
|
|
{
|
|
if (!g_settings.channellist_show_infobox)
|
|
return;
|
|
|
|
int ypos = y + height + OFFSET_INTER;
|
|
int ypos_a = ypos + OFFSET_INNER_SMALL;
|
|
|
|
CChannelEvent *p_event = NULL;
|
|
|
|
//colored_events init
|
|
bool colored_event_C = (g_settings.theme.colored_events_channellist == 1);
|
|
bool colored_event_N = (g_settings.theme.colored_events_channellist == 2);
|
|
|
|
frameBuffer->paintBoxRel(x, ypos, full_width, info_height, COL_MENUCONTENTDARK_PLUS_0, RADIUS_LARGE);
|
|
frameBuffer->paintBoxFrame(x, ypos, full_width, info_height, 2, COL_FRAME_PLUS_0, RADIUS_LARGE);
|
|
|
|
if ((*chanlist).empty())
|
|
return;
|
|
|
|
if (displayNext)
|
|
p_event = &(*chanlist)[index]->nextEvent;
|
|
else
|
|
p_event = &(*chanlist)[index]->currentEvent;
|
|
|
|
if (/* !IS_WEBTV((*chanlist)[index]->getChannelID()) && */ !p_event->description.empty()) {
|
|
char cNoch[50] = {0}; // UTF-8
|
|
char cSeit[50] = {0}; // UTF-8
|
|
|
|
struct tm *pStartZeit = localtime(&p_event->startTime);
|
|
unsigned seit = ( time(NULL) - p_event->startTime ) / 60;
|
|
snprintf(cSeit, sizeof(cSeit), "%s %02d:%02d",(displayNext) ? g_Locale->getText(LOCALE_CHANNELLIST_START):g_Locale->getText(LOCALE_CHANNELLIST_SINCE), pStartZeit->tm_hour, pStartZeit->tm_min);
|
|
if (displayNext) {
|
|
snprintf(cNoch, sizeof(cNoch), "(%d %s)", p_event->duration / 60, unit_short_minute);
|
|
} else {
|
|
int noch = (p_event->startTime + p_event->duration - time(NULL)) / 60;
|
|
if ((noch< 0) || (noch>=10000))
|
|
noch= 0;
|
|
snprintf(cNoch, sizeof(cNoch), "(%u / %d %s)", seit, noch, unit_short_minute);
|
|
}
|
|
int seit_len = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getRenderWidth(cSeit);
|
|
int noch_len = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getRenderWidth(cNoch);
|
|
|
|
std::string text1= p_event->description;
|
|
std::string text2= p_event->text;
|
|
|
|
int xstart = 10;
|
|
if (g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(text1) > (full_width - 30 - seit_len) )
|
|
{
|
|
// zu breit, Umbruch versuchen...
|
|
int pos;
|
|
do {
|
|
pos = text1.find_last_of("[ -.]+");
|
|
if ( pos!=-1 )
|
|
text1 = text1.substr( 0, pos );
|
|
} while ( ( pos != -1 ) && (g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(text1) > (full_width - 30 - seit_len) ) );
|
|
|
|
std::string text3 = ""; /* not perfect, but better than crashing... */
|
|
if (p_event->description.length() > text1.length())
|
|
text3 = p_event->description.substr(text1.length()+ 1);
|
|
|
|
if (!text2.empty() && !text3.empty())
|
|
text3= text3+ " - ";
|
|
|
|
xstart += g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(text3);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + 2*fheight, full_width - 30- noch_len, text3, colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
|
|
if (!(text2.empty())) {
|
|
while ( text2.find_first_of("[ -.+*#?=!$%&/]+") == 0 )
|
|
text2 = text2.substr( 1 );
|
|
text2 = text2.substr( 0, text2.find('\n') );
|
|
#if 0 //FIXME: to discuss, eat too much cpu time if string long enough
|
|
int pos = 0;
|
|
while ( ( pos != -1 ) && (g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(text2) > (full_width - 30 - noch_len) ) ) {
|
|
pos = text2.find_last_of(" ");
|
|
|
|
if ( pos!=-1 ) {
|
|
text2 = text2.substr( 0, pos );
|
|
}
|
|
}
|
|
#endif
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ xstart, ypos_a + fdescrheight+ fheight, full_width- xstart- 30- noch_len, text2, colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + fheight, full_width - 30 - seit_len, text1, colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ full_width- 10- seit_len, ypos_a + fheight , seit_len, cSeit, colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ full_width- 10- noch_len, ypos_a + fdescrheight+ fheight, noch_len, cNoch, colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
else if (IS_WEBTV((*chanlist)[index]->getChannelID())) {
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + fheight, full_width - 30, (*chanlist)[index]->getDesc(), colored_event_C ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT, 0, true);
|
|
}
|
|
if (IS_WEBTV((*chanlist)[index]->getChannelID())) {
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + 2*fheight + fdescrheight, full_width - 30, (*chanlist)[index]->getUrl(), COL_MENUCONTENTDARK_TEXT, 0, true);
|
|
} else if(g_settings.channellist_foot == 0) {
|
|
transponder t;
|
|
CServiceManager::getInstance()->GetTransponder((*chanlist)[index]->getTransponderId(), t);
|
|
|
|
std::string desc = t.description();
|
|
if((*chanlist)[index]->pname)
|
|
desc = desc + " (" + std::string((*chanlist)[index]->pname) + ")";
|
|
else
|
|
desc = desc + " (" + CServiceManager::getInstance()->GetSatelliteName((*chanlist)[index]->getSatellitePosition()) + ")";
|
|
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + 2*fheight +fdescrheight, full_width - 30, desc.c_str(), COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
else if( !displayNext && g_settings.channellist_foot == 1) { // next Event
|
|
|
|
CSectionsdClient::CurrentNextInfo CurrentNext;
|
|
CEitManager::getInstance()->getCurrentNextServiceKey((*chanlist)[index]->getChannelID(), CurrentNext);
|
|
if (!CurrentNext.next_name.empty()) {
|
|
char buf[128] = {0};
|
|
char cFrom[50] = {0}; // UTF-8
|
|
struct tm *pStartZeit = localtime (& CurrentNext.next_zeit.startzeit);
|
|
snprintf(cFrom, sizeof(cFrom), "%s %02d:%02d",g_Locale->getText(LOCALE_WORD_FROM),pStartZeit->tm_hour, pStartZeit->tm_min );
|
|
snprintf(buf, sizeof(buf), "%s", CurrentNext.next_name.c_str());
|
|
int from_len = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getRenderWidth(cFrom);
|
|
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, ypos_a + 2*fheight+ fdescrheight, full_width - 30 - from_len, buf, colored_event_N ? COL_COLORED_EVENTS_TEXT :COL_MENUCONTENTDARK_TEXT);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ full_width- 10- from_len, ypos_a + 2*fheight+ fdescrheight, from_len, cFrom, colored_event_N ? COL_COLORED_EVENTS_TEXT : COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CChannelList::clearItem2DetailsLine()
|
|
{
|
|
paintItem2DetailsLine (-1);
|
|
}
|
|
|
|
void CChannelList::paintItem2DetailsLine (int pos)
|
|
{
|
|
if (dline){
|
|
dline->kill(); //kill details line
|
|
delete dline;
|
|
dline = NULL;
|
|
}
|
|
|
|
if (!g_settings.channellist_show_infobox)
|
|
return;
|
|
|
|
int xpos = x - ConnectLineBox_Width;
|
|
int ypos1 = y + theight + pos*fheight + (fheight/2);
|
|
int ypos2 = y + height + OFFSET_INTER + (info_height/2);
|
|
|
|
// paint Line if detail info (and not valid list pos)
|
|
if (pos >= 0) {
|
|
if (dline == NULL)
|
|
dline = new CComponentsDetailLine(xpos, ypos1, ypos2, fheight/2, info_height-RADIUS_LARGE*2);
|
|
dline->paint(false);
|
|
}
|
|
}
|
|
|
|
void CChannelList::paintAdditionals(int index)
|
|
{
|
|
if (g_settings.channellist_additional)
|
|
{
|
|
if (displayList)
|
|
paint_events(index);
|
|
else
|
|
showdescription(selected);
|
|
}
|
|
}
|
|
|
|
void CChannelList::showChannelLogo() //TODO: move into an own handler, eg. header, channel logo should be paint inside header object
|
|
{
|
|
if ((*chanlist).empty())
|
|
return;
|
|
if(g_settings.channellist_show_channellogo){
|
|
int logo_w_max = full_width / 4;
|
|
if (CChannelLogo) {
|
|
if (headerNew)
|
|
CChannelLogo->clearSavedScreen();
|
|
else
|
|
CChannelLogo->hide();
|
|
delete CChannelLogo;
|
|
}
|
|
CChannelLogo = new CComponentsChannelLogoScalable(0, 0, (*chanlist)[selected]->getName(), (*chanlist)[selected]->getChannelID());
|
|
|
|
if (CChannelLogo->hasLogo()){
|
|
CChannelLogo->setWidth(min(CChannelLogo->getWidth(), logo_w_max), true);
|
|
if (CChannelLogo->getHeight() > theight) //scale image if required
|
|
CChannelLogo->setHeight(theight, true);
|
|
CChannelLogo->setXPos(x + full_width - logo_off - CChannelLogo->getWidth());
|
|
CChannelLogo->setYPos(y + (theight - CChannelLogo->getHeight()) / 2);
|
|
CChannelLogo->paint();
|
|
} else {
|
|
CChannelLogo->hide();
|
|
delete CChannelLogo;
|
|
CChannelLogo = NULL;
|
|
}
|
|
headerNew = false;
|
|
}
|
|
}
|
|
|
|
#define NUM_LIST_BUTTONS_SORT 9
|
|
struct button_label SChannelListButtons_SMode[NUM_LIST_BUTTONS_SORT] =
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED, LOCALE_MISCSETTINGS_EPG_HEAD},
|
|
{ NEUTRINO_ICON_BUTTON_GREEN, LOCALE_CHANNELLIST_FOOT_SORT_ALPHA},
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_BOUQUETLIST_HEAD},
|
|
{ NEUTRINO_ICON_BUTTON_BLUE, LOCALE_INFOVIEWER_NEXT},
|
|
{ NEUTRINO_ICON_BUTTON_RECORD_INACTIVE, NONEXISTANT_LOCALE},
|
|
{ NEUTRINO_ICON_BUTTON_PLAY, LOCALE_EXTRA_KEY_PIP_CLOSE},
|
|
{ NEUTRINO_ICON_BUTTON_INFO_SMALL, NONEXISTANT_LOCALE},
|
|
{ NEUTRINO_ICON_BUTTON_MENU_SMALL, NONEXISTANT_LOCALE},
|
|
{ NEUTRINO_ICON_BUTTON_MUTE_ZAP_ACTIVE, NONEXISTANT_LOCALE}
|
|
};
|
|
|
|
#define NUM_LIST_BUTTONS_EDIT 6
|
|
const struct button_label SChannelListButtons_Edit[NUM_LIST_BUTTONS_EDIT] =
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED , LOCALE_BOUQUETEDITOR_DELETE },
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_BOUQUETEDITOR_ADD },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_BOUQUETEDITOR_MOVE },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_BOUQUETEDITOR_RENAME },
|
|
{ NEUTRINO_ICON_BUTTON_FORWARD , LOCALE_BOUQUETEDITOR_MOVE_TO },
|
|
{ NEUTRINO_ICON_BUTTON_STOP , LOCALE_BOUQUETEDITOR_LOCK }
|
|
};
|
|
|
|
void CChannelList::paintButtonBar(bool is_current)
|
|
{
|
|
//printf("[neutrino channellist] %s...%d, selected %d\n", __FUNCTION__, __LINE__, selected);
|
|
unsigned int smode = CNeutrinoApp::getInstance()->GetChannelMode();
|
|
|
|
int y_foot = y + (height - footerHeight);
|
|
if (edit_state) {
|
|
::paintButtons(x, y_foot, full_width, NUM_LIST_BUTTONS_EDIT, SChannelListButtons_Edit, full_width, footerHeight);
|
|
return;
|
|
}
|
|
t_channel_id channel_id = 0;
|
|
if (!(*chanlist).empty())
|
|
channel_id = (*chanlist)[selected]->getChannelID();
|
|
|
|
struct button_label Button[NUM_LIST_BUTTONS_SORT];
|
|
bool do_record = CRecordManager::getInstance()->RecordingStatus(getActiveChannel_ChannelID());
|
|
|
|
int bcnt = 0;
|
|
for (int i = 0; i < NUM_LIST_BUTTONS_SORT; i++) {
|
|
Button[bcnt] = SChannelListButtons_SMode[i];
|
|
if (!channel_id && i != 2 && i != 7)
|
|
continue;
|
|
if (i == 1) {
|
|
/* check green / sort */
|
|
if(smode != LIST_MODE_FAV) {
|
|
switch (g_settings.channellist_sort_mode) {
|
|
case SORT_ALPHA:
|
|
Button[bcnt].locale = LOCALE_CHANNELLIST_FOOT_SORT_ALPHA;
|
|
break;
|
|
case SORT_TP:
|
|
Button[bcnt].locale = LOCALE_CHANNELLIST_FOOT_SORT_FREQ;
|
|
break;
|
|
case SORT_SAT:
|
|
Button[bcnt].locale = LOCALE_CHANNELLIST_FOOT_SORT_SAT;
|
|
break;
|
|
case SORT_CH_NUMBER:
|
|
Button[bcnt].locale = LOCALE_CHANNELLIST_FOOT_SORT_CHNUM;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else
|
|
continue;
|
|
}
|
|
if (i == 3) {
|
|
//manage now/next button
|
|
if (g_settings.channellist_additional) {
|
|
if (displayList)
|
|
Button[bcnt].locale = LOCALE_FONTSIZE_CHANNELLIST_DESCR;
|
|
else
|
|
Button[bcnt].locale = LOCALE_FONTMENU_EVENTLIST;
|
|
} else {
|
|
if (displayNext)
|
|
Button[bcnt].locale = LOCALE_INFOVIEWER_NOW;
|
|
else
|
|
Button[bcnt].locale = LOCALE_INFOVIEWER_NEXT;
|
|
}
|
|
}
|
|
if (i == 4) {
|
|
//manage record button
|
|
if (g_settings.recording_type == RECORDING_OFF)
|
|
continue;
|
|
if (IS_WEBTV(channel_id))
|
|
continue;
|
|
if (!displayNext){
|
|
if (do_record){
|
|
Button[bcnt].locale = LOCALE_MAINMENU_RECORDING_STOP;
|
|
Button[bcnt].button = NEUTRINO_ICON_BUTTON_STOP;
|
|
} else if (is_current) {
|
|
Button[bcnt].locale = LOCALE_MAINMENU_RECORDING;
|
|
Button[bcnt].button = NEUTRINO_ICON_BUTTON_RECORD_ACTIVE;
|
|
} else {
|
|
Button[bcnt].locale = NONEXISTANT_LOCALE;
|
|
Button[bcnt].button = NEUTRINO_ICON_BUTTON_RECORD_INACTIVE;
|
|
}
|
|
}
|
|
}
|
|
if (i == 5) {
|
|
//manage pip button
|
|
#ifdef ENABLE_PIP
|
|
if (!is_current || IS_WEBTV(channel_id))
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
if (i == 8) {
|
|
/* check mute / zap mode */
|
|
if (new_zap_mode)
|
|
Button[bcnt].button = new_zap_mode == 2 /* active */ ?
|
|
NEUTRINO_ICON_BUTTON_MUTE_ZAP_ACTIVE : NEUTRINO_ICON_BUTTON_MUTE_ZAP_INACTIVE;
|
|
else
|
|
continue;
|
|
}
|
|
bcnt++;
|
|
}
|
|
//paint buttons
|
|
::paintButtons(x, y_foot, full_width, bcnt, Button, full_width, footerHeight);
|
|
}
|
|
|
|
void CChannelList::paintItem(int pos, const bool firstpaint)
|
|
{
|
|
if( (*chanlist).empty() ){
|
|
return;
|
|
}
|
|
int ypos = y+ theight + pos*fheight;
|
|
bool is_available = true;
|
|
bool paintbuttons = false;
|
|
unsigned int curr = liststart + pos;
|
|
|
|
if (curr < (*chanlist).size())
|
|
{
|
|
if (edit_state)
|
|
is_available = !((*chanlist)[curr]->flags & CZapitChannel::NOT_PRESENT);
|
|
else
|
|
is_available = SameTP((*chanlist)[curr]);
|
|
}
|
|
|
|
if (selected >= (*chanlist).size())
|
|
selected = (*chanlist).size()-1;
|
|
|
|
bool i_selected = curr == selected;
|
|
bool i_marked = getKey(curr) == CNeutrinoApp::getInstance()->channelList->getActiveChannelNumber() && new_zap_mode != 2 /*active*/;
|
|
int i_radius = RADIUS_NONE;
|
|
|
|
fb_pixel_t color;
|
|
fb_pixel_t ecolor; // we need one more color for displayNext
|
|
fb_pixel_t bgcolor;
|
|
|
|
getItemColors(color, bgcolor, i_selected, i_marked);
|
|
ecolor = color;
|
|
|
|
if (i_selected || i_marked)
|
|
i_radius = RADIUS_LARGE;
|
|
|
|
if (i_selected)
|
|
{
|
|
paintItem2DetailsLine (pos);
|
|
paintDetails(curr);
|
|
paintAdditionals(curr);
|
|
paintbuttons = true;
|
|
}
|
|
|
|
if (displayNext)
|
|
{
|
|
/*
|
|
I think it's unnecessary to change colors in this case.
|
|
The user should know when he has pressed the blue button.
|
|
*/
|
|
if (g_settings.theme.colored_events_channellist == 2 /* next */)
|
|
ecolor = COL_COLORED_EVENTS_TEXT;
|
|
else
|
|
ecolor = COL_MENUCONTENTINACTIVE_TEXT;
|
|
}
|
|
|
|
if (!is_available)
|
|
color = COL_MENUCONTENTINACTIVE_TEXT;
|
|
|
|
if (!firstpaint || i_selected || getKey(curr) == CNeutrinoApp::getInstance()->channelList->getActiveChannelNumber())
|
|
frameBuffer->paintBoxRel(x,ypos, width- 15, fheight, bgcolor, i_radius);
|
|
|
|
if(curr < (*chanlist).size()) {
|
|
char nameAndDescription[255];
|
|
char tmp[10];
|
|
CZapitChannel* chan = (*chanlist)[curr];
|
|
int prg_offset=0;
|
|
int title_offset=0;
|
|
int rec_mode;
|
|
if(g_settings.channellist_progressbar_design != CProgressBar::PB_OFF)
|
|
{
|
|
prg_offset = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->getRenderWidth("00:00");
|
|
title_offset=6;
|
|
}
|
|
|
|
snprintf(tmp, sizeof(tmp), "%d", this->historyMode ? pos : chan->number);
|
|
|
|
CChannelEvent *p_event=NULL;
|
|
if (displayNext)
|
|
p_event = &chan->nextEvent;
|
|
else
|
|
p_event = &chan->currentEvent;
|
|
|
|
//record check
|
|
rec_mode = CRecordManager::getInstance()->GetRecordMode((*chanlist)[curr]->getChannelID());
|
|
|
|
//set recording icon
|
|
std::string rec_icon;
|
|
if (rec_mode & CRecordManager::RECMODE_REC)
|
|
rec_icon = NEUTRINO_ICON_REC;
|
|
else if (rec_mode & CRecordManager::RECMODE_TSHIFT)
|
|
rec_icon = NEUTRINO_ICON_AUTO_SHIFT;
|
|
#ifdef ENABLE_PIP
|
|
else if ((*chanlist)[curr]->getChannelID() == CZapit::getInstance()->GetPipChannelID())
|
|
rec_icon = NEUTRINO_ICON_PIP;
|
|
#endif
|
|
//calculating icons
|
|
bool isWebTV = !chan->getUrl().empty();
|
|
const char *icon = isWebTV ? NEUTRINO_ICON_STREAMING : NEUTRINO_ICON_SCRAMBLED;
|
|
int icon_x = (x+width-15-2) - RADIUS_LARGE/2;
|
|
int r_icon_w; int s_icon_h=0; int s_icon_w=0;
|
|
frameBuffer->getIconSize(icon, &s_icon_w, &s_icon_h);
|
|
r_icon_w = ChannelList_Rec;
|
|
int r_icon_x = icon_x;
|
|
|
|
//paint icon
|
|
if(chan->scrambled || isWebTV)
|
|
if (frameBuffer->paintIcon(icon, icon_x - s_icon_w, ypos, fheight))//ypos + (fheight - 16)/2);
|
|
r_icon_x = r_icon_x - s_icon_w;
|
|
|
|
//paint recording icon
|
|
if (!rec_icon.empty())
|
|
frameBuffer->paintIcon(rec_icon, r_icon_x - r_icon_w, ypos, fheight);//ypos + (fheight - 16)/2);
|
|
|
|
//paint buttons
|
|
if (paintbuttons)
|
|
paintButtonBar(is_available);
|
|
|
|
int icon_space = r_icon_w+s_icon_w;
|
|
|
|
//channel numbers
|
|
int icon_w = 0, icon_h = 0;
|
|
if (curr == selected && move_state == beMoving) {
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_BUTTON_YELLOW, &icon_w, &icon_h);
|
|
frameBuffer->paintIcon(NEUTRINO_ICON_BUTTON_YELLOW, x + 5 + numwidth - icon_w, ypos, fheight);
|
|
} else if (edit_state && chan->bLocked) {
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_LOCK, &icon_w, &icon_h);
|
|
frameBuffer->paintIcon(NEUTRINO_ICON_LOCK, x + 5 + numwidth - icon_w, ypos, fheight);
|
|
} else if (g_settings.channellist_show_numbers) {
|
|
int numpos = x+5+numwidth- g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->getRenderWidth(tmp);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->RenderString(numpos,ypos+fheight, numwidth+5, tmp, color, fheight);
|
|
} else if (!edit_state)
|
|
numwidth = -5;
|
|
|
|
int l=0;
|
|
if (this->historyMode)
|
|
l = snprintf(nameAndDescription, sizeof(nameAndDescription), ": %d %s", chan->number, chan->getName().c_str());
|
|
else
|
|
l = snprintf(nameAndDescription, sizeof(nameAndDescription), "%s", chan->getName().c_str());
|
|
|
|
int pb_space = prg_offset - title_offset;
|
|
int pb_height = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->getDigitHeight();
|
|
CProgressBar pb(x+5+numwidth + title_offset, ypos + (fheight-pb_height)/2, pb_space + 2, pb_height, COL_MENUCONTENT_PLUS_0);
|
|
pb.setType(CProgressBar::PB_TIMESCALE);
|
|
pb.setDesign(g_settings.channellist_progressbar_design);
|
|
pb.setCornerType(0);
|
|
pb.setStatusColors(COL_MENUCONTENT_PLUS_3, COL_MENUCONTENT_PLUS_1);
|
|
int pb_frame = 0;
|
|
if (g_settings.channellist_progressbar_design == CProgressBar::PB_MONO && !g_settings.progressbar_gradient)
|
|
{
|
|
// add small frame to mono progressbars w/o gradient for a better visibility
|
|
pb_frame = 1;
|
|
}
|
|
pb.setFrameThickness(pb_frame);
|
|
pb.doPaintBg(false);
|
|
int pb_max = pb_space - 4;
|
|
|
|
if (!(p_event->description.empty())) {
|
|
snprintf(nameAndDescription+l, sizeof(nameAndDescription)-l,g_settings.channellist_epgtext_align_right ? " ":" - ");
|
|
unsigned int ch_name_len = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(nameAndDescription);
|
|
unsigned int ch_desc_len = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getRenderWidth(p_event->description);
|
|
|
|
int max_desc_len = width - numwidth - prg_offset - ch_name_len - 15 - 20; // 15 = scrollbar, 20 = spaces
|
|
if (chan->scrambled || g_settings.channellist_epgtext_align_right)
|
|
max_desc_len -= icon_space+g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getWidth(); /* do we need space for the lock/rec icon? */
|
|
|
|
if (max_desc_len < 0)
|
|
max_desc_len = 0;
|
|
if ((int) ch_desc_len > max_desc_len)
|
|
ch_desc_len = max_desc_len;
|
|
|
|
if(g_settings.channellist_progressbar_design != CProgressBar::PB_OFF) {
|
|
if(displayNext)
|
|
{
|
|
struct tm *pStartZeit = localtime(&p_event->startTime);
|
|
|
|
snprintf(tmp, sizeof(tmp), "%02d:%02d", pStartZeit->tm_hour, pStartZeit->tm_min);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->RenderString(x+ 5+ numwidth+ 6, ypos + fheight, width- numwidth- 20- 15 -prg_offset, tmp, ecolor, fheight);
|
|
}
|
|
else
|
|
{
|
|
time_t jetzt=time(NULL);
|
|
int runningPercent = 0;
|
|
|
|
if (((jetzt - p_event->startTime + 30) / 60) < 0 )
|
|
runningPercent= 0;
|
|
else
|
|
runningPercent=(jetzt-p_event->startTime) * pb_max / p_event->duration;
|
|
|
|
pb.setValues(runningPercent, pb_max);
|
|
pb.paint();
|
|
}
|
|
}
|
|
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 5+ numwidth+ 10+prg_offset, ypos+ fheight, width- numwidth- 40- 15-prg_offset, nameAndDescription, color);
|
|
if (g_settings.channellist_epgtext_align_right) {
|
|
// align right
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x + width - 20 - ch_desc_len - icon_space - 4, ypos + fheight, ch_desc_len, p_event->description, ecolor);
|
|
}
|
|
else {
|
|
// align left
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ 5+ numwidth+ 10+ ch_name_len+ 5+prg_offset, ypos+ fheight, ch_desc_len, p_event->description, ecolor);
|
|
}
|
|
}
|
|
else {
|
|
if(g_settings.channellist_progressbar_design != CProgressBar::PB_OFF) {
|
|
pb.setValues(0, pb_max);
|
|
pb.paint();
|
|
}
|
|
//name
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 5+ numwidth+ 10+prg_offset, ypos+ fheight, width- numwidth- 40- 15-prg_offset, nameAndDescription, color);
|
|
}
|
|
if (!firstpaint && curr == selected)
|
|
updateVfd();
|
|
}
|
|
}
|
|
|
|
|
|
void CChannelList::updateVfd()
|
|
{
|
|
if (selected >= (*chanlist).size())
|
|
return;
|
|
|
|
CZapitChannel* chan = (*chanlist)[selected];
|
|
CChannelEvent *p_event=NULL;
|
|
if (displayNext)
|
|
p_event = &chan->nextEvent;
|
|
else
|
|
p_event = &chan->currentEvent;
|
|
|
|
if (!(chan->currentEvent.description.empty())) {
|
|
char nameAndDescription[255];
|
|
snprintf(nameAndDescription, sizeof(nameAndDescription), "%s - %s",
|
|
chan->getName().c_str(), p_event->description.c_str());
|
|
CVFD::getInstance()->showMenuText(0, nameAndDescription, -1, true); // UTF-8
|
|
} else
|
|
CVFD::getInstance()->showMenuText(0, chan->getName().c_str(), -1, true); // UTF-8
|
|
}
|
|
|
|
void CChannelList::paint()
|
|
{
|
|
TIMER_START();
|
|
paintHead();
|
|
TIMER_STOP("CChannelList::paint() after paint head");
|
|
paintBody();
|
|
TIMER_STOP("CChannelList::paint() after paint body");
|
|
updateVfd();
|
|
TIMER_STOP("CChannelList::paint() paint total");
|
|
}
|
|
|
|
void CChannelList::paintHead()
|
|
{
|
|
if (header == NULL){
|
|
header = new CComponentsHeader();
|
|
header->getTextObject()->enableTboxSaveScreen(g_settings.theme.menu_Head_gradient);//enable screen save for title text if color gradient is in use
|
|
}
|
|
|
|
header->setDimensionsAll(x, y, full_width, theight);
|
|
|
|
if (bouquet && bouquet->zapitBouquet && bouquet->zapitBouquet->bLocked != g_settings.parentallock_defaultlocked)
|
|
header->setIcon(NEUTRINO_ICON_LOCK);
|
|
|
|
string header_txt = !edit_state ? name : string(g_Locale->getText(LOCALE_CHANNELLIST_EDIT)) + ": " + name;
|
|
fb_pixel_t header_txt_col = (edit_state ? COL_RED : COL_MENUHEAD_TEXT);
|
|
header->setColorBody(COL_MENUHEAD_PLUS_0);
|
|
|
|
header->setCaption(header_txt, CTextBox::NO_AUTO_LINEBREAK, header_txt_col);
|
|
|
|
if (header->enableColBodyGradient(g_settings.theme.menu_Head_gradient, COL_MENUCONTENT_PLUS_0)){
|
|
if (CChannelLogo)
|
|
CChannelLogo->clearFbData();
|
|
}
|
|
|
|
if (timeset) {
|
|
if(!edit_state){
|
|
if (header->getContextBtnObject())
|
|
if (!header->getContextBtnObject()->empty())
|
|
header->removeContextButtons();
|
|
header->enableClock(true, "%H:%M", "%H %M", true);
|
|
logo_off = header->getClockObject()->getWidth() + 10;
|
|
|
|
header->getClockObject()->setCorner(RADIUS_LARGE, CORNER_TOP_RIGHT);
|
|
}else{
|
|
if (header->getClockObject()){
|
|
header->disableClock();
|
|
header->setContextButton(CComponentsHeader::CC_BTN_EXIT);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
logo_off = 10;
|
|
|
|
header->paint(CC_SAVE_SCREEN_NO); //TODO: paint title only, currently paint() does paint all enabled header items at once and causes flicker effects in unchanged items (e.g. clock)
|
|
}
|
|
|
|
CComponentsHeader* CChannelList::getHeaderObject()
|
|
{
|
|
return header;
|
|
}
|
|
|
|
void CChannelList::ResetModules()
|
|
{
|
|
delete header;
|
|
header = NULL;
|
|
if(dline){
|
|
delete dline;
|
|
dline = NULL;
|
|
}
|
|
if (cc_minitv){
|
|
delete cc_minitv;
|
|
cc_minitv = NULL;
|
|
}
|
|
if (CChannelLogo) {
|
|
delete CChannelLogo;
|
|
CChannelLogo = NULL;
|
|
}
|
|
}
|
|
|
|
void CChannelList::paintBody()
|
|
{
|
|
int icon_w = 0, icon_h = 0;
|
|
numwidth = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_NUMBER]->getRenderWidth(MaxChanNr());
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_BUTTON_YELLOW, &icon_w, &icon_h);
|
|
numwidth = std::max(icon_w, (int) numwidth);
|
|
frameBuffer->getIconSize(NEUTRINO_ICON_LOCK, &icon_w, &icon_h);
|
|
numwidth = std::max(icon_w, (int) numwidth);
|
|
|
|
liststart = (selected/listmaxshow)*listmaxshow;
|
|
updateEvents(this->historyMode ? 0:liststart, this->historyMode ? 0:(liststart + listmaxshow));
|
|
|
|
if (pig_on_win) // with miniTV
|
|
paintPig(x+width, y+theight, pig_width, pig_height);
|
|
|
|
// paint background for main box
|
|
frameBuffer->paintBoxRel(x, y+theight, width, height-footerHeight-theight, COL_MENUCONTENT_PLUS_0);
|
|
if (g_settings.channellist_additional)
|
|
{
|
|
// disable displayNext
|
|
displayNext = false;
|
|
// paint background for right box
|
|
frameBuffer->paintBoxRel(x+width,y+theight+pig_height,infozone_width,infozone_height,COL_MENUCONTENT_PLUS_0);
|
|
}
|
|
|
|
unit_short_minute = g_Locale->getText(LOCALE_UNIT_SHORT_MINUTE);
|
|
|
|
for(unsigned int count = 0; count < listmaxshow; count++)
|
|
paintItem(count, true);
|
|
|
|
const int ypos = y+ theight;
|
|
const int sb = height - theight - footerHeight; // paint scrollbar over full height of main box
|
|
frameBuffer->paintBoxRel(x+ width- 15,ypos, 15, sb, COL_SCROLLBAR_PASSIVE_PLUS_0);
|
|
unsigned int listmaxshow_tmp = listmaxshow ? listmaxshow : 1;//avoid division by zero
|
|
int sbc= (((*chanlist).size()- 1)/ listmaxshow_tmp)+ 1;
|
|
const int sbs= (selected/listmaxshow_tmp);
|
|
if (sbc < 1)
|
|
sbc = 1;
|
|
|
|
frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ sbs*(sb-4)/sbc, 11, (sb-4)/sbc, COL_SCROLLBAR_ACTIVE_PLUS_0);
|
|
showChannelLogo();
|
|
if ((*chanlist).empty())
|
|
paintButtonBar(false);
|
|
}
|
|
|
|
bool CChannelList::isEmpty() const
|
|
{
|
|
return (*chanlist).empty();
|
|
}
|
|
|
|
int CChannelList::getSize() const
|
|
{
|
|
return (*chanlist).size();
|
|
}
|
|
|
|
int CChannelList::getSelectedChannelIndex() const
|
|
{
|
|
return this->selected;
|
|
}
|
|
|
|
bool CChannelList::SameTP(t_channel_id channel_id)
|
|
{
|
|
bool iscurrent = true;
|
|
|
|
if(CNeutrinoApp::getInstance()->recordingstatus) {
|
|
if (IS_WEBTV(channel_id))
|
|
return true;
|
|
|
|
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id);
|
|
if(channel)
|
|
iscurrent = SameTP(channel);
|
|
else
|
|
iscurrent = false;
|
|
}
|
|
return iscurrent;
|
|
}
|
|
|
|
bool CChannelList::SameTP(CZapitChannel * channel)
|
|
{
|
|
bool iscurrent = true;
|
|
|
|
if(CNeutrinoApp::getInstance()->recordingstatus) {
|
|
if(channel == NULL)
|
|
channel = (*chanlist)[selected];
|
|
|
|
if (IS_WEBTV(channel->getChannelID()))
|
|
return true;
|
|
|
|
iscurrent = CFEManager::getInstance()->canTune(channel);
|
|
}
|
|
return iscurrent;
|
|
}
|
|
|
|
std::string CChannelList::MaxChanNr()
|
|
{
|
|
zapit_list_it_t chan_it;
|
|
std::stringstream ss;
|
|
std::string maxchansize;
|
|
int chan_nr_max = 1;
|
|
unsigned int nr = 0;
|
|
for (chan_it=(*chanlist).begin(); chan_it!=(*chanlist).end(); ++chan_it) {
|
|
chan_nr_max = std::max(chan_nr_max, (*chanlist)[nr++]->number);
|
|
}
|
|
ss << chan_nr_max;
|
|
ss >> maxchansize;
|
|
return maxchansize;
|
|
}
|
|
|
|
void CChannelList::paintPig (int _x, int _y, int w, int h)
|
|
{
|
|
//init minitv object with basic properties
|
|
if (cc_minitv == NULL){
|
|
cc_minitv = new CComponentsPIP (0, 0);
|
|
cc_minitv->setPicture(NEUTRINO_ICON_AUDIOPLAY);
|
|
cc_minitv->setFrameThickness(5);
|
|
}
|
|
//set changeable minitv properties
|
|
cc_minitv->setDimensionsAll(_x, _y, w, h);
|
|
cc_minitv->setCorner(0);
|
|
cc_minitv->setColorFrame(COL_MENUCONTENT_PLUS_0);
|
|
cc_minitv->paint(false);
|
|
}
|
|
|
|
void CChannelList::paint_events(int index)
|
|
{
|
|
if (index == -2 && paint_events_index > -2) {
|
|
pthread_mutex_lock(&paint_events_mutex);
|
|
paint_events_index = index;
|
|
sem_post(&paint_events_sem);
|
|
pthread_join(paint_events_thr, NULL);
|
|
sem_destroy(&paint_events_sem);
|
|
pthread_mutex_unlock(&paint_events_mutex);
|
|
} else if (paint_events_index == -2) {
|
|
if (index == -2)
|
|
return;
|
|
// First paint_event. No need to lock.
|
|
pthread_mutexattr_t attr;
|
|
pthread_mutexattr_init(&attr);
|
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
|
|
pthread_mutex_init(&paint_events_mutex, &attr);
|
|
|
|
sem_init(&paint_events_sem, 0, 0);
|
|
paint_events_index = index;
|
|
if (!pthread_create(&paint_events_thr, NULL, paint_events, (void *) this))
|
|
sem_post(&paint_events_sem);
|
|
else
|
|
paint_events_index = -2;
|
|
} else {
|
|
pthread_mutex_lock(&paint_events_mutex);
|
|
paint_events_index = index;
|
|
pthread_mutex_unlock(&paint_events_mutex);
|
|
sem_post(&paint_events_sem);
|
|
}
|
|
}
|
|
|
|
void *CChannelList::paint_events(void *arg)
|
|
{
|
|
CChannelList *me = (CChannelList *) arg;
|
|
me->paint_events();
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
void CChannelList::paint_events()
|
|
{
|
|
set_threadname(__func__);
|
|
|
|
while (paint_events_index != -2) {
|
|
sem_wait(&paint_events_sem);
|
|
if (paint_events_index < 0)
|
|
continue;
|
|
while(!sem_trywait(&paint_events_sem));
|
|
int current_index = paint_events_index;
|
|
|
|
CChannelEventList evtlist;
|
|
readEvents((*chanlist)[current_index]->getChannelID(), evtlist);
|
|
if (current_index == paint_events_index) {
|
|
pthread_mutex_lock(&paint_events_mutex);
|
|
if (current_index == paint_events_index)
|
|
paint_events_index = -1;
|
|
pthread_mutex_unlock(&paint_events_mutex);
|
|
paint_events(evtlist);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CChannelList::paint_events(CChannelEventList &evtlist)
|
|
{
|
|
ffheight = g_Font[eventFont]->getHeight();
|
|
frameBuffer->paintBoxRel(x+ width,y+ theight+pig_height, infozone_width, infozone_height,COL_MENUCONTENT_PLUS_0);
|
|
|
|
char startTime[10];
|
|
int eventStartTimeWidth = 4 * g_Font[eventFont]->getMaxDigitWidth() + g_Font[eventFont]->getRenderWidth(":") + 5; // use a fixed value
|
|
int startTimeWidth = 0;
|
|
CChannelEventList::iterator e;
|
|
time_t azeit;
|
|
time(&azeit);
|
|
unsigned int u_azeit = ( azeit > -1)? azeit:0;
|
|
|
|
if ( evtlist.empty() )
|
|
{
|
|
CChannelEvent evt;
|
|
|
|
evt.description = g_Locale->getText(LOCALE_EPGLIST_NOEVENTS);
|
|
evt.eventID = 0;
|
|
evt.startTime = 0;
|
|
evtlist.push_back(evt);
|
|
}
|
|
|
|
int i=1;
|
|
for (e=evtlist.begin(); e!=evtlist.end(); ++e )
|
|
{
|
|
//Remove events in the past
|
|
if ( (u_azeit > (e->startTime + e->duration)) && (!(e->eventID == 0)))
|
|
{
|
|
do
|
|
{
|
|
//printf("%d seconds in the past - deleted %s\n", dif, e->description.c_str());
|
|
e = evtlist.erase( e );
|
|
if (e == evtlist.end())
|
|
break;
|
|
}
|
|
while ( u_azeit > (e->startTime + e->duration));
|
|
}
|
|
if (e == evtlist.end())
|
|
break;
|
|
|
|
//Display the remaining events
|
|
if ((y+ theight+ pig_height + i*ffheight) < (y+ theight+ pig_height + infozone_height))
|
|
{
|
|
fb_pixel_t color = COL_MENUCONTENTDARK_TEXT;
|
|
if (e->eventID)
|
|
{
|
|
bool first = (i == 1);
|
|
if ((first && g_settings.theme.colored_events_channellist == 1 /* current */) || (!first && g_settings.theme.colored_events_channellist == 2 /* next */))
|
|
color = COL_COLORED_EVENTS_TEXT;
|
|
struct tm *tmStartZeit = localtime(&e->startTime);
|
|
strftime(startTime, sizeof(startTime), "%H:%M", tmStartZeit );
|
|
//printf("%s %s\n", startTime, e->description.c_str());
|
|
startTimeWidth = eventStartTimeWidth;
|
|
g_Font[eventFont]->RenderString(x+ width+5, y+ theight+ pig_height + i*ffheight, startTimeWidth, startTime, color);
|
|
}
|
|
g_Font[eventFont]->RenderString(x+ width+5+startTimeWidth, y+ theight+ pig_height + i*ffheight, infozone_width - startTimeWidth - 20, e->description, color);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static bool sortByDateTime (const CChannelEvent& a, const CChannelEvent& b)
|
|
{
|
|
return a.startTime < b.startTime;
|
|
}
|
|
|
|
void CChannelList::readEvents(const t_channel_id channel_id, CChannelEventList &evtlist)
|
|
{
|
|
CEitManager::getInstance()->getEventsServiceKey(channel_id , evtlist);
|
|
|
|
if ( evtlist.empty() )
|
|
{
|
|
CChannelEvent evt;
|
|
evt.description = g_Locale->getText(LOCALE_EPGLIST_NOEVENTS);
|
|
evt.eventID = 0;
|
|
evt.startTime = 0;
|
|
evtlist.push_back(evt);
|
|
}
|
|
else
|
|
sort(evtlist.begin(),evtlist.end(),sortByDateTime);
|
|
}
|
|
|
|
void CChannelList::showdescription(int index)
|
|
{
|
|
std::string strEpisode = ""; // Episode title in case info1 gets stripped
|
|
ffheight = g_Font[eventFont]->getHeight();
|
|
CZapitChannel* chan = (*chanlist)[index];
|
|
CChannelEvent *p_event = &chan->currentEvent;
|
|
epgData.info1.clear();
|
|
epgData.info2.clear();
|
|
epgText.clear();
|
|
CEitManager::getInstance()->getEPGid(p_event->eventID, p_event->startTime, &epgData);
|
|
|
|
if (!epgData.info1.empty()) {
|
|
bool bHide = false;
|
|
if (false == epgData.info2.empty()) {
|
|
// Look for the first . in info1, usually this is the title of an episode.
|
|
std::string::size_type nPosDot = epgData.info1.find('.');
|
|
if (std::string::npos != nPosDot) {
|
|
nPosDot += 2; // Skip dot and first blank
|
|
if (nPosDot < epgData.info2.length() && nPosDot < epgData.info1.length()) { // Make sure we don't overrun the buffer
|
|
|
|
// Check if the stuff after the dot equals the beginning of info2
|
|
if (0 == epgData.info2.find(epgData.info1.substr(nPosDot, epgData.info1.length() - nPosDot))) {
|
|
strEpisode = epgData.info1.substr(0, nPosDot) + "\n";
|
|
bHide = true;
|
|
}
|
|
}
|
|
}
|
|
// Compare strings normally if not positively found to be equal before
|
|
if (false == bHide && 0 == epgData.info2.find(epgData.info1)) {
|
|
bHide = true;
|
|
}
|
|
}
|
|
if (false == bHide) {
|
|
processTextToArray(epgData.info1);
|
|
}
|
|
}
|
|
|
|
//scan epg-data - sort to list
|
|
if (((epgData.info2.empty())) && (!(strEpisode.empty())))
|
|
processTextToArray(g_Locale->getText(LOCALE_EPGVIEWER_NODETAILED)); // UTF-8
|
|
else
|
|
processTextToArray(strEpisode + epgData.info2); // UTF-8
|
|
|
|
frameBuffer->paintBoxRel(x+ width,y+ theight+pig_height, infozone_width, infozone_height,COL_MENUCONTENT_PLUS_0);
|
|
for (int i = 1; (i < (int)epgText.size()+1) && ((y+ theight+ pig_height + i*ffheight) < (y+ theight+ pig_height + infozone_height)); i++)
|
|
g_Font[eventFont]->RenderString(x+ width+5, y+ theight+ pig_height + i*ffheight, infozone_width - 20, epgText[i-1].first, COL_MENUCONTENTDARK_TEXT);
|
|
}
|
|
|
|
void CChannelList::addTextToArray(const std::string & text, int screening) // UTF-8
|
|
{
|
|
//printf("line: >%s<\n", text.c_str() );
|
|
if (text==" ")
|
|
{
|
|
emptyLineCount ++;
|
|
if (emptyLineCount<2)
|
|
epgText.push_back(epg_pair(text,screening));
|
|
}
|
|
else
|
|
{
|
|
emptyLineCount = 0;
|
|
epgText.push_back(epg_pair(text,screening));
|
|
}
|
|
}
|
|
|
|
void CChannelList::processTextToArray(std::string text, int screening) // UTF-8
|
|
{
|
|
std::string aktLine = "";
|
|
std::string aktWord = "";
|
|
int aktWidth = 0;
|
|
text += ' ';
|
|
const char *text_= text.c_str();
|
|
|
|
while (*text_!=0)
|
|
{
|
|
if ( (*text_==' ') || (*text_=='\n') || (*text_=='-') || (*text_=='.') )
|
|
{
|
|
if (*text_!='\n')
|
|
aktWord += *text_;
|
|
|
|
int aktWordWidth = g_Font[eventFont]->getRenderWidth(aktWord);
|
|
if ((aktWordWidth+aktWidth)<(infozone_width - 20))
|
|
{//space ok, add
|
|
aktWidth += aktWordWidth;
|
|
aktLine += aktWord;
|
|
|
|
if (*text_=='\n')
|
|
{ //enter-handler
|
|
addTextToArray( aktLine, screening );
|
|
aktLine = "";
|
|
aktWidth= 0;
|
|
}
|
|
aktWord = "";
|
|
}
|
|
else
|
|
{//new line needed
|
|
addTextToArray( aktLine, screening);
|
|
aktLine = aktWord;
|
|
aktWidth = aktWordWidth;
|
|
aktWord = "";
|
|
if (*text_=='\n')
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aktWord += *text_;
|
|
}
|
|
text_++;
|
|
}
|
|
//add the rest
|
|
addTextToArray( aktLine + aktWord, screening );
|
|
}
|
|
|
|
void CChannelList::saveChanges(bool fav)
|
|
{
|
|
g_bouquetManager->renumServices();
|
|
if (fav)
|
|
CNeutrinoApp::getInstance()->MarkFavoritesChanged();
|
|
else
|
|
CNeutrinoApp::getInstance()->MarkBouquetsChanged();
|
|
}
|
|
|
|
void CChannelList::editMode(bool enable)
|
|
{
|
|
if (!bouquet || !bouquet->zapitBouquet)
|
|
return;
|
|
|
|
displayNext = false;
|
|
edit_state = enable;
|
|
printf("STATE: %s\n", edit_state ? "EDIT" : "SHOW");
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
if (edit_state) {
|
|
chanlist = tvmode ? &bouquet->zapitBouquet->tvChannels : &bouquet->zapitBouquet->radioChannels;
|
|
} else {
|
|
chanlist = &channels;
|
|
if (channelsChanged) {
|
|
channelsChanged = false;
|
|
bouquet->zapitBouquet->getChannels(channels, tvmode);
|
|
saveChanges(bouquet->zapitBouquet->bUser);
|
|
if (!g_settings.show_empty_favorites && (*chanlist).empty())
|
|
CNeutrinoApp::getInstance()->MarkChannelsInit();
|
|
}
|
|
if (selected >= chanlist->size())
|
|
selected = chanlist->empty() ? 0 : (chanlist->size() - 1);
|
|
}
|
|
adjustToChannelID(selected_chid);
|
|
}
|
|
|
|
void CChannelList::beginMoveChannel()
|
|
{
|
|
move_state = beMoving;
|
|
origPosition = selected;
|
|
newPosition = selected;
|
|
}
|
|
|
|
void CChannelList::finishMoveChannel()
|
|
{
|
|
move_state = beDefault;
|
|
paintBody();
|
|
}
|
|
|
|
void CChannelList::cancelMoveChannel()
|
|
{
|
|
move_state = beDefault;
|
|
internalMoveChannel(newPosition, origPosition);
|
|
channelsChanged = false;
|
|
}
|
|
|
|
void CChannelList::internalMoveChannel( unsigned int fromPosition, unsigned int toPosition)
|
|
{
|
|
if ( (int) toPosition == -1 ) return;
|
|
if ( toPosition == chanlist->size()) return;
|
|
if (!bouquet || !bouquet->zapitBouquet)
|
|
return;
|
|
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
bouquet->zapitBouquet->moveService(fromPosition, toPosition, tvmode ? 1 : 2);
|
|
|
|
channelsChanged = true;
|
|
chanlist = tvmode ? &bouquet->zapitBouquet->tvChannels : &bouquet->zapitBouquet->radioChannels;
|
|
|
|
selected = toPosition;
|
|
newPosition = toPosition;
|
|
paintBody();
|
|
}
|
|
|
|
void CChannelList::deleteChannel(bool ask)
|
|
{
|
|
if (selected >= chanlist->size())
|
|
return;
|
|
if (!bouquet || !bouquet->zapitBouquet)
|
|
return;
|
|
|
|
if (ask && ShowMsg(LOCALE_FILEBROWSER_DELETE, (*chanlist)[selected]->getName(), CMsgBox::mbrNo, CMsgBox::mbYes|CMsgBox::mbNo)!=CMsgBox::mbrYes)
|
|
return;
|
|
|
|
bouquet->zapitBouquet->removeService((*chanlist)[selected]->getChannelID());
|
|
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
chanlist = tvmode ? &bouquet->zapitBouquet->tvChannels : &bouquet->zapitBouquet->radioChannels;
|
|
|
|
if (selected >= chanlist->size())
|
|
selected = chanlist->empty() ? 0 : (chanlist->size() - 1);
|
|
|
|
channelsChanged = true;
|
|
paintBody();
|
|
updateVfd();
|
|
}
|
|
|
|
void CChannelList::addChannel()
|
|
{
|
|
if (!bouquet || !bouquet->zapitBouquet)
|
|
return;
|
|
|
|
hide();
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
std::string caption = name + ": " + g_Locale->getText(LOCALE_BOUQUETEDITOR_ADD);
|
|
|
|
CBEChannelSelectWidget* channelSelectWidget = new CBEChannelSelectWidget(caption, bouquet->zapitBouquet, tvmode ? CZapitClient::MODE_TV : CZapitClient::MODE_RADIO);
|
|
|
|
channelSelectWidget->exec(NULL, "");
|
|
if (channelSelectWidget->hasChanged())
|
|
{
|
|
channelsChanged = true;
|
|
chanlist = tvmode ? &bouquet->zapitBouquet->tvChannels : &bouquet->zapitBouquet->radioChannels;
|
|
if (selected >= chanlist->size())
|
|
selected = chanlist->empty() ? 0 : (chanlist->size() - 1);
|
|
}
|
|
delete channelSelectWidget;
|
|
paint();
|
|
}
|
|
|
|
void CChannelList::renameChannel()
|
|
{
|
|
std::string newName= inputName((*chanlist)[selected]->getName().c_str(), LOCALE_BOUQUETEDITOR_NEWBOUQUETNAME);
|
|
|
|
if (newName != (*chanlist)[selected]->getName())
|
|
{
|
|
if(newName.empty())
|
|
(*chanlist)[selected]->setUserName("");
|
|
else
|
|
(*chanlist)[selected]->setUserName(newName);
|
|
|
|
channelsChanged = true;
|
|
}
|
|
paint();
|
|
}
|
|
|
|
void CChannelList::lockChannel()
|
|
{
|
|
(*chanlist)[selected]->bLocked = !(*chanlist)[selected]->bLocked;
|
|
CNeutrinoApp::getInstance()->MarkFavoritesChanged();
|
|
if (selected + 1 < (*chanlist).size())
|
|
g_RCInput->postMsg((neutrino_msg_t) CRCInput::RC_down, 0);
|
|
else
|
|
paintItem(selected - liststart);
|
|
}
|
|
|
|
bool CChannelList::addChannelToBouquet()
|
|
{
|
|
bool fav_found = true;
|
|
signed int bouquet_id = AllFavBouquetList->exec(false);
|
|
hide();
|
|
if(bouquet_id < 0)
|
|
return false;
|
|
|
|
t_channel_id channel_id = (*chanlist)[selected]->getChannelID();
|
|
bool tvmode = CZapit::getInstance()->getMode() & CZapitClient::MODE_TV;
|
|
CBouquetList *blist = tvmode ? TVfavList : RADIOfavList;
|
|
if (AllFavBouquetList->Bouquets[bouquet_id]->zapitBouquet) {
|
|
CZapitBouquet *zapitBouquet = AllFavBouquetList->Bouquets[bouquet_id]->zapitBouquet;
|
|
CZapitChannel *ch = zapitBouquet->getChannelByChannelID(channel_id);
|
|
if (ch == NULL) {
|
|
fav_found = false;
|
|
zapitBouquet->addService((*chanlist)[selected]);
|
|
for (unsigned n = 0; n < blist->Bouquets.size(); n++) {
|
|
if (blist->Bouquets[n]->zapitBouquet == zapitBouquet) {
|
|
zapitBouquet->getChannels(blist->Bouquets[n]->channelList->channels, tvmode);
|
|
saveChanges();
|
|
fav_found = true;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
ShowMsg(LOCALE_EXTRA_ADD_TO_BOUQUET, LOCALE_EXTRA_CHALREADYINBQ, CMsgBox::mbrBack, CMsgBox::mbBack, NEUTRINO_ICON_INFO);
|
|
return false;
|
|
}
|
|
}
|
|
if (!fav_found) {
|
|
CNeutrinoApp::getInstance()->MarkFavoritesChanged();
|
|
CNeutrinoApp::getInstance()->MarkChannelsInit();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CChannelList::moveChannelToBouquet()
|
|
{
|
|
if (addChannelToBouquet())
|
|
deleteChannel(false);
|
|
else
|
|
paintBody();
|
|
|
|
paintHead();
|
|
}
|
|
|
|
std::string CChannelList::inputName(const char * const defaultName, const neutrino_locale_t caption)
|
|
{
|
|
std::string Name = defaultName;
|
|
|
|
CKeyboardInput * nameInput = new CKeyboardInput(caption, &Name);
|
|
nameInput->exec(NULL, "");
|
|
|
|
delete nameInput;
|
|
|
|
return std::string(Name);
|
|
}
|