mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-27 15:32:59 +02:00
373 lines
9.4 KiB
C++
373 lines
9.4 KiB
C++
/*
|
|
adzap.cpp
|
|
|
|
(C) 2012-2013 by martii
|
|
(C) 2016 Sven Hoefer (svenhoefer)
|
|
|
|
License: GPL
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <global.h>
|
|
#include <neutrino.h>
|
|
#include <mymenu.h>
|
|
#include <algorithm>
|
|
#include <gui/adzap.h>
|
|
#include <gui/widget/hintbox.h>
|
|
#include <eitd/sectionsd.h>
|
|
#include <driver/screen_max.h>
|
|
#include <system/helpers.h>
|
|
#include <system/set_threadname.h>
|
|
|
|
#define ZAPBACK_ALERT_PERIOD 15 // seconds
|
|
#define ADZAP_DATA "/tmp/adzap.data"
|
|
|
|
static const struct button_label CAdZapMenuFooterButtons[] = {
|
|
//{ NEUTRINO_ICON_BUTTON_RED, LOCALE_ADZAP_DISABLE },
|
|
{ NEUTRINO_ICON_BUTTON_GREEN, LOCALE_ADZAP_ENABLE },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE, LOCALE_ADZAP_MONITOR }
|
|
};
|
|
#define CAdZapMenuFooterButtonCount (sizeof(CAdZapMenuFooterButtons)/sizeof(button_label))
|
|
|
|
static CAdZapMenu *azm = NULL;
|
|
|
|
CAdZapMenu *CAdZapMenu::getInstance()
|
|
{
|
|
if (!azm)
|
|
azm = new CAdZapMenu();
|
|
return azm;
|
|
}
|
|
|
|
CAdZapMenu::CAdZapMenu()
|
|
{
|
|
frameBuffer = CFrameBuffer::getInstance();
|
|
width = 35;
|
|
|
|
sem_init(&sem, 0, 0);
|
|
|
|
channelId = -1;
|
|
armed = false;
|
|
monitor = false;
|
|
alerted = false;
|
|
|
|
pthread_t thr;
|
|
if (pthread_create(&thr, 0, CAdZapMenu::Run, this))
|
|
fprintf(stderr, "ERROR: pthread_create(CAdZapMenu::CAdZapMenu)\n");
|
|
else
|
|
pthread_detach(thr);
|
|
}
|
|
|
|
static bool sortByDateTime(const CChannelEvent & a, const CChannelEvent & b)
|
|
{
|
|
return a.startTime < b.startTime;
|
|
}
|
|
|
|
void CAdZapMenu::Init()
|
|
{
|
|
CChannelList *channelList = CNeutrinoApp::getInstance()->channelList;
|
|
channelId = channelList ? channelList->getActiveChannel_ChannelID() : -1;
|
|
if(channelList)
|
|
channelName = channelList->getActiveChannelName();
|
|
evtlist.clear();
|
|
CEitManager::getInstance()->getEventsServiceKey(channelId & 0xFFFFFFFFFFFFULL, evtlist);
|
|
monitorLifeTime.tv_sec = 0;
|
|
if (!evtlist.empty())
|
|
{
|
|
sort(evtlist.begin(), evtlist.end(), sortByDateTime);
|
|
monitorLifeTime.tv_sec = getMonitorLifeTime();
|
|
Update();
|
|
}
|
|
printf("CAdZapMenu::%s: monitorLifeTime.tv_sec: %d\n", __func__, (uint) monitorLifeTime.tv_sec);
|
|
}
|
|
|
|
time_t CAdZapMenu::getMonitorLifeTime()
|
|
{
|
|
if (evtlist.empty())
|
|
return 0;
|
|
|
|
CChannelEventList::iterator eli;
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
for (eli = evtlist.begin(); eli != evtlist.end(); ++eli)
|
|
{
|
|
if ((u_int) eli->startTime + (u_int) eli->duration > (u_int) ts.tv_sec)
|
|
return (uint) eli->startTime + eli->duration;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CAdZapMenu::Update()
|
|
{
|
|
clock_gettime(CLOCK_REALTIME, &zapBackTime);
|
|
zapBackTime.tv_sec += g_settings.adzap_zapBackPeriod - ZAPBACK_ALERT_PERIOD;
|
|
sem_post(&sem);
|
|
}
|
|
|
|
void *CAdZapMenu::Run(void *arg)
|
|
{
|
|
CAdZapMenu *me = (CAdZapMenu *) arg;
|
|
me->Run();
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
void CAdZapMenu::Run()
|
|
{
|
|
set_threadname("CAdZapMenu::Run");
|
|
while (true)
|
|
{
|
|
CChannelList *channelList = NULL;
|
|
t_channel_id curChannelId = -1;
|
|
|
|
if (monitor)
|
|
{
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
ts.tv_sec += 1;
|
|
|
|
sem_timedwait(&sem, &ts);
|
|
|
|
if (monitor && (monitorLifeTime.tv_sec > ts.tv_sec))
|
|
{
|
|
channelList = CNeutrinoApp::getInstance()->channelList;
|
|
curChannelId = channelList ? channelList->getActiveChannel_ChannelID() : -1;
|
|
if (!armed && (channelId != curChannelId))
|
|
{
|
|
armed = true;
|
|
clock_gettime(CLOCK_REALTIME, &zapBackTime);
|
|
zapBackTime.tv_sec += g_settings.adzap_zapBackPeriod - ZAPBACK_ALERT_PERIOD;
|
|
alerted = false;
|
|
}
|
|
else if (channelId == curChannelId)
|
|
{
|
|
armed = false;
|
|
alerted = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
monitor = false;
|
|
armed = false;
|
|
alerted = false;
|
|
}
|
|
}
|
|
else if (armed)
|
|
{
|
|
if (g_settings.adzap_writeData)
|
|
{
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
ts.tv_sec += 1;
|
|
|
|
sem_timedwait(&sem, &ts);
|
|
}
|
|
else
|
|
sem_timedwait(&sem, &zapBackTime);
|
|
}
|
|
else
|
|
sem_wait(&sem);
|
|
|
|
if (armed)
|
|
{
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
if (ts.tv_sec >= zapBackTime.tv_sec)
|
|
{
|
|
if (!channelList)
|
|
{
|
|
channelList = CNeutrinoApp::getInstance()->channelList;
|
|
curChannelId = channelList ? channelList->getActiveChannel_ChannelID() : -1;
|
|
}
|
|
if (!alerted)
|
|
{
|
|
if (channelId != curChannelId)
|
|
{
|
|
char name[1024];
|
|
snprintf(name, sizeof(name)-1, g_Locale->getText(LOCALE_ADZAP_ANNOUNCE), ZAPBACK_ALERT_PERIOD, channelName.c_str());
|
|
ShowHint(LOCALE_ADZAP, name);
|
|
}
|
|
alerted = true;
|
|
zapBackTime.tv_sec += ZAPBACK_ALERT_PERIOD;
|
|
}
|
|
else
|
|
{
|
|
alerted = false;
|
|
if ((channelId != curChannelId) && channelList)
|
|
channelList->zapTo_ChannelID(channelId);
|
|
armed = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_settings.adzap_writeData && (monitor || armed))
|
|
WriteData();
|
|
else
|
|
RemoveData();
|
|
}
|
|
}
|
|
|
|
void CAdZapMenu::WriteData()
|
|
{
|
|
int zp = g_settings.adzap_zapBackPeriod;
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
long int zb = armed ? zapBackTime.tv_sec + ZAPBACK_ALERT_PERIOD - ts.tv_sec : 0;
|
|
|
|
if (FILE *f = fopen(ADZAP_DATA, "w"))
|
|
{
|
|
fprintf(f, "%" PRIx64 "\n%s\n%d\n%d:%02d\n%ld\n%ld:%02ld\n",
|
|
channelId,
|
|
channelName.c_str(),
|
|
zp,
|
|
zp / 60, zp % 60,
|
|
zb,
|
|
zb / 60, zb % 60);
|
|
fclose(f);
|
|
}
|
|
else
|
|
printf("CAdZapMenu::%s: failed.\n", __func__);
|
|
}
|
|
|
|
void CAdZapMenu::RemoveData()
|
|
{
|
|
if (access(ADZAP_DATA, F_OK) == 0)
|
|
unlink(ADZAP_DATA);
|
|
}
|
|
int CAdZapMenu::exec(CMenuTarget *parent, const std::string & actionKey)
|
|
{
|
|
Init();
|
|
|
|
int res = menu_return::RETURN_EXIT_ALL;
|
|
bool marked_ok = (actionKey.length() == 1 && g_settings.adzap_zapBackPeriod == (actionKey[0] - '0') * 60);
|
|
|
|
if (actionKey == "enable" || marked_ok)
|
|
{
|
|
if (!monitor)
|
|
armed = true;
|
|
alerted = false;
|
|
Update();
|
|
return res;
|
|
}
|
|
if (actionKey == "disable")
|
|
{
|
|
armed = false;
|
|
monitor = false;
|
|
alerted = false;
|
|
Update();
|
|
return res;
|
|
}
|
|
if (actionKey == "monitor")
|
|
{
|
|
armed = false;
|
|
monitor = true;
|
|
alerted = false;
|
|
if (!evtlist.empty())
|
|
monitorLifeTime.tv_sec = getMonitorLifeTime();
|
|
printf("CAdZapMenu::%s: monitorLifeTime.tv_sec: %d\n", __func__, (uint) monitorLifeTime.tv_sec);
|
|
Update();
|
|
return res;
|
|
}
|
|
if (actionKey == "adzap")
|
|
{
|
|
if (armed || monitor) {
|
|
armed = false;
|
|
monitor = false;
|
|
alerted = false;
|
|
Update();
|
|
ShowHint(LOCALE_ADZAP, LOCALE_ADZAP_CANCEL, 450, 1);
|
|
return res;
|
|
}
|
|
}
|
|
if (actionKey.length() == 1)
|
|
{
|
|
g_settings.adzap_zapBackPeriod = actionKey[0] - '0';
|
|
for (int shortcut = 1; shortcut < 10; shortcut++)
|
|
{
|
|
bool selected = (g_settings.adzap_zapBackPeriod == shortcut);
|
|
forwarders[shortcut - 1]->setMarked(selected);
|
|
forwarders[shortcut - 1]->iconName_Info_right = selected ? NEUTRINO_ICON_MARKER_DIALOG_OK : NULL;
|
|
}
|
|
nc->setMarked(false);
|
|
g_settings.adzap_zapBackPeriod *= 60;
|
|
return menu_return::RETURN_REPAINT;
|
|
}
|
|
|
|
if (parent)
|
|
parent->hide();
|
|
|
|
monitor = false;
|
|
ShowMenu();
|
|
|
|
return res;
|
|
}
|
|
|
|
void CAdZapMenu::ShowMenu()
|
|
{
|
|
bool show_monitor = monitorLifeTime.tv_sec;
|
|
|
|
CMenuWidget *menu = new CMenuWidget(LOCALE_ADZAP, NEUTRINO_ICON_SETTINGS, width);
|
|
//menu->addKey(CRCInput::RC_red, this, "disable");
|
|
menu->addKey(CRCInput::RC_green, this, "enable");
|
|
menu->addKey(CRCInput::RC_blue, this, "monitor");
|
|
menu->addIntroItems();
|
|
|
|
CMenuOptionChooser *oc = new CMenuOptionChooser(LOCALE_ADZAP_WRITEDATA, &g_settings.adzap_writeData, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true);
|
|
oc->setHint(NEUTRINO_ICON_HINT_ADZAP, LOCALE_MENU_HINT_ADZAP_WRITEDATA);
|
|
menu->addItem(oc);
|
|
|
|
menu->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_ADZAP_SWITCHBACK));
|
|
|
|
neutrino_locale_t minute = LOCALE_ADZAP_MINUTE;
|
|
for (int shortcut = 1; shortcut < 10; shortcut++) {
|
|
char actionKey[2];
|
|
actionKey[0] = '0' + shortcut;
|
|
actionKey[1] = 0;
|
|
bool selected = g_settings.adzap_zapBackPeriod == 60 * shortcut;
|
|
forwarders[shortcut - 1] = new CMenuForwarder(minute, true, NULL, this, actionKey, CRCInput::convertDigitToKey(shortcut));
|
|
forwarders[shortcut - 1]->setMarked(selected);
|
|
forwarders[shortcut - 1]->iconName_Info_right = selected ? NEUTRINO_ICON_MARKER_DIALOG_OK : NULL;
|
|
forwarders[shortcut - 1]->setHint(NEUTRINO_ICON_HINT_ADZAP, "");
|
|
menu->addItem(forwarders[shortcut - 1], selected);
|
|
minute = LOCALE_ADZAP_MINUTES;
|
|
}
|
|
|
|
menu->addItem(GenericMenuSeparator);
|
|
|
|
int zapBackPeriod = g_settings.adzap_zapBackPeriod / 60;
|
|
nc = new CMenuOptionNumberChooser(minute, &zapBackPeriod, true, 10, 120, this, CRCInput::RC_0);
|
|
nc->setMarked(g_settings.adzap_zapBackPeriod / 60 > 9);
|
|
nc->setHint(NEUTRINO_ICON_HINT_ADZAP, "");
|
|
menu->addItem(nc);
|
|
|
|
menu->setFooter(CAdZapMenuFooterButtons, CAdZapMenuFooterButtonCount - (show_monitor ? 0 : 1));
|
|
menu->exec(NULL, "");
|
|
menu->hide();
|
|
delete menu;
|
|
Update();
|
|
}
|
|
|
|
bool CAdZapMenu::changeNotify(const neutrino_locale_t, void * data)
|
|
{
|
|
int z = (*(int *)data);
|
|
g_settings.adzap_zapBackPeriod = z * 60;
|
|
for (int shortcut = 1; shortcut < 10; shortcut++)
|
|
forwarders[shortcut - 1]->setMarked(false);
|
|
nc->setMarked(true);
|
|
return false;
|
|
}
|