vdr-plugin-tvguide/channelepg.c

400 lines
12 KiB
C
Raw Normal View History

2019-07-11 12:06:18 +02:00
#include "channelepg.h"
2013-12-07 15:51:50 +01:00
#include "dummygrid.h"
2013-01-17 13:16:44 +01:00
2019-07-11 14:34:31 +02:00
cChannelEpg::cChannelEpg(int num, const cChannel *channel, cTimeManager *timeManager) {
2013-05-26 11:38:05 +02:00
this->channel = channel;
this->num = num;
2019-07-11 14:34:31 +02:00
this->timeManager = timeManager;
#if VDRVERSNUM < 20301
2013-05-26 11:38:05 +02:00
hasTimer = channel->HasTimer();
2018-03-08 13:02:38 +01:00
#endif
2013-07-09 00:17:42 +02:00
hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
#if VDRVERSNUM < 20301
2013-05-26 12:00:02 +02:00
schedulesLock = new cSchedulesLock(false, 100);
2018-03-08 13:02:38 +01:00
#endif
2013-05-31 13:58:22 +02:00
header = NULL;
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
cChannelEpg::~cChannelEpg(void) {
2013-05-31 13:58:22 +02:00
if (header)
delete header;
2013-05-26 11:38:05 +02:00
grids.Clear();
#if VDRVERSNUM < 20301
delete schedulesLock;
2018-03-08 13:02:38 +01:00
#endif
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::clearGrids() {
2013-05-26 11:38:05 +02:00
grids.Clear();
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::createHeader() {
header = new cHeaderGrid();
header->createBackground(num);
header->drawChannel(channel);
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::drawHeader() {
header->setPosition(num);
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
bool cChannelEpg::readGrids() {
#if VDRVERSNUM >= 20301
2018-04-01 13:39:31 +02:00
const cSchedules* schedules;
{
2018-03-08 13:02:38 +01:00
LOCK_SCHEDULES_READ;
2018-04-01 13:39:31 +02:00
schedules = Schedules;
}
2018-03-08 13:02:38 +01:00
#else
schedules = cSchedules::Schedules(*schedulesLock);
2018-03-08 13:02:38 +01:00
#endif
2013-05-26 11:38:05 +02:00
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule) {
2019-07-11 14:34:31 +02:00
addDummyGrid(timeManager->GetStart(), timeManager->GetEnd(), NULL, false);
return true;
2013-05-26 11:38:05 +02:00
}
bool eventFound = false;
bool dummyAtStart = false;
2019-07-11 14:34:31 +02:00
const cEvent *startEvent = Schedule->GetEventAround(timeManager->GetStart());
2013-05-26 11:38:05 +02:00
if (startEvent != NULL) {
eventFound = true;
} else {
for (int i=1; i<6; i++) {
2019-07-11 14:34:31 +02:00
startEvent = Schedule->GetEventAround(timeManager->GetStart()+i*5*60);
2013-05-26 11:38:05 +02:00
if (startEvent) {
eventFound = true;
dummyAtStart = true;
2013-05-26 11:38:05 +02:00
break;
}
}
}
if (eventFound) {
bool col = true;
if (dummyAtStart) {
2019-07-11 14:34:31 +02:00
addDummyGrid(timeManager->GetStart(), startEvent->StartTime(), NULL, col);
col = !col;
}
bool dummyNeeded = true;
bool toFarInFuture = false;
2019-07-11 14:34:31 +02:00
time_t endLast = timeManager->GetStart();
const cEvent *event = startEvent;
const cEvent *eventLast = NULL;
2013-05-26 11:38:05 +02:00
for (; event; event = Schedule->Events()->Next(event)) {
if (endLast < event->StartTime()) {
//gap, dummy needed
time_t endTime = event->StartTime();
2019-07-11 14:34:31 +02:00
if (endTime > timeManager->GetEnd()) {
endTime = timeManager->GetEnd();
toFarInFuture = true;
}
addDummyGrid(endLast, endTime, NULL, col);
col = !col;
}
if (toFarInFuture) {
break;
}
addEpgGrid(event, NULL, col);
2013-05-26 11:38:05 +02:00
col = !col;
endLast = event->EndTime();
2019-07-11 14:34:31 +02:00
if (event->EndTime() > timeManager->GetEnd()) {
dummyNeeded = false;
2013-05-26 11:38:05 +02:00
break;
}
eventLast = event;
2013-05-26 11:38:05 +02:00
}
if (dummyNeeded) {
2019-07-11 14:34:31 +02:00
addDummyGrid(eventLast->EndTime(), timeManager->GetEnd(), NULL, col);
}
2013-05-26 11:38:05 +02:00
return true;
} else {
2019-07-11 14:34:31 +02:00
addDummyGrid(timeManager->GetStart(), timeManager->GetEnd(), NULL, false);
return true;
}
return false;
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::drawGrids() {
2019-07-11 15:06:07 +02:00
for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) {
2013-05-26 11:38:05 +02:00
grid->SetViewportHeight();
grid->PositionPixmap();
grid->Draw();
}
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
int cChannelEpg::getX() {
2013-12-21 11:25:03 +01:00
return geoManager.timeLineWidth + num*geoManager.colWidth;
2013-05-24 16:23:23 +02:00
}
2019-07-11 12:06:18 +02:00
int cChannelEpg::getY() {
2013-12-21 11:25:03 +01:00
return geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::getActive() {
2019-07-11 14:34:31 +02:00
cTimeManager t;
2013-05-26 11:38:05 +02:00
t.Now();
2019-07-11 15:06:07 +02:00
for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) {
2013-05-26 11:38:05 +02:00
if (grid->Match(t.Get()))
return grid;
}
return grids.First();
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::getNext(cGridElement *activeGrid) {
2013-05-26 11:38:05 +02:00
if (activeGrid == NULL)
return NULL;
2019-07-11 15:06:07 +02:00
cGridElement *next = grids.Next(activeGrid);
2013-05-26 11:38:05 +02:00
if (next)
return next;
return NULL;
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::getPrev(cGridElement *activeGrid) {
2013-05-26 11:38:05 +02:00
if (activeGrid == NULL)
return NULL;
2019-07-11 15:06:07 +02:00
cGridElement *prev = grids.Prev(activeGrid);
2013-05-26 11:38:05 +02:00
if (prev)
return prev;
return NULL;
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::getNeighbor(cGridElement *activeGrid) {
2013-05-26 11:38:05 +02:00
if (!activeGrid)
return NULL;
2019-07-11 15:06:07 +02:00
cGridElement *neighbor = NULL;
2013-05-26 11:38:05 +02:00
int overlap = 0;
int overlapNew = 0;
2019-07-11 15:06:07 +02:00
cGridElement *grid = NULL;
2013-05-26 11:38:05 +02:00
grid = grids.First();
if (grid) {
for (; grid; grid = grids.Next(grid)) {
if ( (grid->StartTime() == activeGrid->StartTime()) ) {
neighbor = grid;
break;
}
overlapNew = activeGrid->calcOverlap(grid);
if (overlapNew > overlap) {
neighbor = grid;
overlap = overlapNew;
}
}
}
if (!neighbor)
neighbor = grids.First();
return neighbor;
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
bool cChannelEpg::isFirst(cGridElement *grid) {
if (grid == grids.First())
return true;
return false;
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::AddNewGridsAtStart() {
2019-07-11 15:06:07 +02:00
cGridElement *firstGrid = NULL;
2013-05-26 11:38:05 +02:00
firstGrid = grids.First();
if (firstGrid == NULL)
2013-05-26 11:38:05 +02:00
return;
//if first event is long enough, nothing to do.
2019-07-11 14:34:31 +02:00
if (firstGrid->StartTime() <= timeManager->GetStart()) {
return;
}
//if not, i have to add new ones to the list
#if VDRVERSNUM >= 20301
2018-04-01 13:39:31 +02:00
const cSchedules* schedules;
{
2018-03-08 13:02:38 +01:00
LOCK_SCHEDULES_READ;
2018-04-01 13:39:31 +02:00
schedules = Schedules;
}
2018-03-08 13:02:38 +01:00
#else
schedules = cSchedules::Schedules(*schedulesLock);
2018-03-08 13:02:38 +01:00
#endif
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule) {
if (firstGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
firstGrid->SetStartTime(timeManager->GetStart());
firstGrid->SetEndTime(timeManager->GetEnd());
}
return;
}
bool col = !(firstGrid->IsColor1());
bool dummyNeeded = true;
2013-05-26 11:38:05 +02:00
for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) {
if (!event)
break;
2019-07-11 14:34:31 +02:00
if (event->EndTime() < timeManager->GetStart()) {
break;
}
2019-07-11 15:06:07 +02:00
cGridElement *grid = addEpgGrid(event, firstGrid, col);
col = !col;
firstGrid = grid;
2019-07-11 14:34:31 +02:00
if (event->StartTime() <= timeManager->GetStart()) {
dummyNeeded = false;
2013-05-26 11:38:05 +02:00
break;
}
}
if (dummyNeeded) {
firstGrid = grids.First();
if (firstGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
firstGrid->SetStartTime(timeManager->GetStart());
if (firstGrid->EndTime() >= timeManager->GetEnd())
firstGrid->SetEndTime(timeManager->GetEnd());
} else {
2019-07-11 14:34:31 +02:00
addDummyGrid(timeManager->GetStart(), firstGrid->StartTime(), firstGrid, col);
}
}
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::AddNewGridsAtEnd() {
2019-07-11 15:06:07 +02:00
cGridElement *lastGrid = NULL;
2013-05-26 11:38:05 +02:00
lastGrid = grids.Last();
if (lastGrid == NULL)
return;
//if last event is long enough, nothing to do.
2019-07-11 14:34:31 +02:00
if (lastGrid->EndTime() >= timeManager->GetEnd()) {
return;
2013-05-26 11:38:05 +02:00
}
//if not, i have to add new ones to the list
#if VDRVERSNUM >= 20301
2018-04-01 13:39:31 +02:00
const cSchedules* schedules;
{
2018-03-08 13:02:38 +01:00
LOCK_SCHEDULES_READ;
2018-04-01 13:39:31 +02:00
schedules = Schedules;
}
2018-03-08 13:02:38 +01:00
#else
2013-05-26 11:38:05 +02:00
schedules = cSchedules::Schedules(*schedulesLock);
2018-03-08 13:02:38 +01:00
#endif
2013-05-26 11:38:05 +02:00
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule) {
if (lastGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
lastGrid->SetStartTime(timeManager->GetStart());
lastGrid->SetEndTime(timeManager->GetEnd());
}
return;
}
2013-05-26 11:38:05 +02:00
bool col = !(lastGrid->IsColor1());
bool dummyNeeded = true;
2013-05-26 11:38:05 +02:00
for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) {
if (!event)
break;
2019-07-11 14:34:31 +02:00
if (event->StartTime() > timeManager->GetEnd()) {
break;
}
addEpgGrid(event, NULL, col);
col = !col;
2019-07-11 14:34:31 +02:00
if (event->EndTime() > timeManager->GetEnd()) {
dummyNeeded = false;
2013-05-26 11:38:05 +02:00
break;
}
}
if (dummyNeeded) {
lastGrid = grids.Last();
if (lastGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
lastGrid->SetEndTime(timeManager->GetEnd());
if (lastGrid->StartTime() <= timeManager->GetStart())
lastGrid->SetStartTime(timeManager->GetStart());
} else {
2019-07-11 14:34:31 +02:00
addDummyGrid(lastGrid->EndTime(), timeManager->GetEnd(), NULL, col);
}
}
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::ClearOutdatedStart() {
2019-07-11 15:06:07 +02:00
cGridElement *firstGrid = NULL;
2013-05-26 11:38:05 +02:00
while (true) {
firstGrid = grids.First();
if (!firstGrid)
break;
2019-07-11 14:34:31 +02:00
if (firstGrid->EndTime() <= timeManager->GetStart()) {
grids.Del(firstGrid);
firstGrid = NULL;
2013-05-26 11:38:05 +02:00
} else {
if (firstGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
firstGrid->SetStartTime(timeManager->GetStart());
2019-07-11 15:06:07 +02:00
cGridElement *next = getNext(firstGrid);
if (next) {
firstGrid->SetEndTime(next->StartTime());
} else {
2019-07-11 14:34:31 +02:00
firstGrid->SetEndTime(timeManager->GetEnd());
}
}
break;
2013-05-26 11:38:05 +02:00
}
}
2013-01-17 13:16:44 +01:00
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::ClearOutdatedEnd() {
2019-07-11 15:06:07 +02:00
cGridElement *lastGrid = NULL;
2013-05-26 11:38:05 +02:00
while (true) {
lastGrid = grids.Last();
if (!lastGrid)
break;
2019-07-11 14:34:31 +02:00
if (lastGrid->StartTime() >= timeManager->GetEnd()) {
grids.Del(lastGrid);
lastGrid = NULL;
2013-05-26 11:38:05 +02:00
} else {
if (lastGrid->isDummy()) {
2019-07-11 14:34:31 +02:00
lastGrid->SetEndTime(timeManager->GetEnd());
2019-07-11 15:06:07 +02:00
cGridElement *prev = getPrev(lastGrid);
if (prev) {
lastGrid->SetStartTime(prev->EndTime());
} else {
2019-07-11 14:34:31 +02:00
lastGrid->SetStartTime(timeManager->GetStart());
}
}
break;
2013-05-26 11:38:05 +02:00
}
}
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::addEpgGrid(const cEvent *event, cGridElement *firstGrid, bool color) {
cGridElement *grid = new cEpgGrid(this, event);
grid->setText();
grid->SetColor(color);
if (!firstGrid)
grids.Add(grid);
else
grids.Ins(grid, firstGrid);
return grid;
2013-01-17 13:16:44 +01:00
}
2019-07-11 15:06:07 +02:00
cGridElement *cChannelEpg::addDummyGrid(time_t start, time_t end, cGridElement *firstGrid, bool color) {
cGridElement *dummy = new cDummyGrid(this, start, end);
dummy->setText();
dummy->SetColor(color);
if (!firstGrid)
grids.Add(dummy);
else
grids.Ins(dummy, firstGrid);
return dummy;
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::SetTimers() {
#if VDRVERSNUM < 20301
2013-07-09 00:17:42 +02:00
hasTimer = channel->HasTimer();
2018-03-08 13:02:38 +01:00
#endif
2013-07-09 00:17:42 +02:00
hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
2019-07-11 15:06:07 +02:00
for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) {
2013-07-09 00:17:42 +02:00
bool gridHadTimer = grid->HasTimer();
grid->SetTimer();
if (gridHadTimer || gridHadTimer != grid->HasTimer())
2013-07-09 00:17:42 +02:00
grid->SetDirty();
bool gridHadSwitchTimer = grid->HasSwitchTimer();
grid->SetSwitchTimer();
if (gridHadSwitchTimer != grid->HasSwitchTimer())
grid->SetDirty();
grid->Draw();
}
}
2019-07-11 12:06:18 +02:00
void cChannelEpg::dumpGrids() {
2013-07-15 17:27:55 +02:00
esyslog("tvguide: ------Channel %s %d: %d entires ---------", channel->Name(), num, grids.Count());
int i=1;
2019-07-11 15:06:07 +02:00
for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) {
2019-07-11 14:34:31 +02:00
esyslog("tvguide: grid %d: start: %s, stop: %s", i, *cTimeManager::printTime(grid->StartTime()), *cTimeManager::printTime(grid->EndTime()));
i++;
}
2018-04-01 13:39:31 +02:00
}