diff options
Diffstat (limited to 'channelepg.c')
-rw-r--r-- | channelepg.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/channelepg.c b/channelepg.c new file mode 100644 index 0000000..e93eb6a --- /dev/null +++ b/channelepg.c @@ -0,0 +1,444 @@ +#include "channelepg.h" + +cChannelEpg::cChannelEpg(int position, const cChannel *channel, cTimeManager *timeManager) { + init = true; + this->channel = channel; + this->position = position; + this->timeManager = timeManager; + channelsPerPage = (config.displayMode == eHorizontal) ? config.channelsPerPageHorizontal : config.channelsPerPageVertical; + SetTimer(); + SetSwitchTimer(); + schedulesLock = new cSchedulesLock(false, 100); +} + +cChannelEpg::~cChannelEpg(void) { + grids.Clear(); + delete schedulesLock; +} + +void cChannelEpg::ClearGrids(void) { + grids.Clear(); +} + +bool cChannelEpg::ReadGrids(void) { + schedules = cSchedules::Schedules(*schedulesLock); + const cSchedule *Schedule = NULL; + Schedule = schedules->GetSchedule(channel); + if (!Schedule) { + AddDummyGrid(timeManager->GetStart(), timeManager->GetEnd()); + return true; + } + bool eventFound = false; + bool dummyAtStart = false; + const cEvent *startEvent = Schedule->GetEventAround(timeManager->GetStart()); + if (startEvent != NULL) { + eventFound = true; + } else { + for (int i=1; i<6; i++) { + startEvent = Schedule->GetEventAround(timeManager->GetStart()+i*5*60); + if (startEvent) { + eventFound = true; + dummyAtStart = true; + break; + } + } + } + if (eventFound) { + if (dummyAtStart) { + AddDummyGrid(timeManager->GetStart(), startEvent->StartTime()); + } + bool dummyNeeded = true; + bool toFarInFuture = false; + time_t endLast = timeManager->GetStart(); + const cEvent *event = startEvent; + const cEvent *eventLast = NULL; + for (; event; event = Schedule->Events()->Next(event)) { + if (endLast < event->StartTime()) { + if (dummyAtStart) { + dummyAtStart = false; + } else { + //gap, dummy needed + time_t endTime = event->StartTime(); + if (endTime > timeManager->GetEnd()) { + endTime = timeManager->GetEnd(); + toFarInFuture = true; + } + AddDummyGrid(endLast, endTime); + } + } + if (toFarInFuture) { + break; + } + if (event->StartTime() >= timeManager->GetEnd()) { + dummyNeeded = false; + break; + } + AddEpgGrid(event); + endLast = event->EndTime(); + if (event->EndTime() > timeManager->GetEnd()) { + dummyNeeded = false; + break; + } + eventLast = event; + } + if (dummyNeeded) { + AddDummyGrid(eventLast->EndTime(), timeManager->GetEnd()); + } + return true; + } else { + AddDummyGrid(timeManager->GetStart(), timeManager->GetEnd()); + return true; + } + return false; +} + +cGridElement *cChannelEpg::GetActive(void) { + cTimeManager t; + t.Now(); + for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { + if (grid->Match(t.Get())) + return grid; + } + return grids.First(); +} + +cGridElement *cChannelEpg::GetNext(cGridElement *activeGrid) { + if (activeGrid == NULL) + return NULL; + cGridElement *next = grids.Next(activeGrid); + if (next) + return next; + return NULL; +} + +cGridElement *cChannelEpg::GetPrev(cGridElement *activeGrid) { + if (activeGrid == NULL) + return NULL; + cGridElement *prev = grids.Prev(activeGrid); + if (prev) + return prev; + return NULL; +} + +cGridElement *cChannelEpg::GetNeighbor(cGridElement *activeGrid) { + if (!activeGrid) + return NULL; + cGridElement *neighbor = NULL; + int overlap = 0; + int overlapNew = 0; + cGridElement *grid = NULL; + 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; +} + +bool cChannelEpg::IsFirst(cGridElement *grid) { + if (grid == grids.First()) + return true; + return false; +} + +void cChannelEpg::AddNewGridsAtStart(void) { + cGridElement *firstGrid = NULL; + firstGrid = grids.First(); + if (firstGrid == NULL) + return; + //if first event is long enough, nothing to do. + if (firstGrid->StartTime() <= timeManager->GetStart()) { + return; + } + //if not, i have to add new ones to the list + schedules = cSchedules::Schedules(*schedulesLock); + const cSchedule *Schedule = NULL; + Schedule = schedules->GetSchedule(channel); + if (!Schedule) { + if (firstGrid->IsDummy()) { + firstGrid->SetStartTime(timeManager->GetStart()); + firstGrid->SetEndTime(timeManager->GetEnd()); + } + return; + } + bool dummyNeeded = true; + for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) { + if (!event) + break; + if (event->EndTime() < timeManager->GetStart()) { + break; + } + cGridElement *grid = AddEpgGrid(event, firstGrid); + firstGrid = grid; + if (event->StartTime() <= timeManager->GetStart()) { + dummyNeeded = false; + break; + } + } + if (dummyNeeded) { + firstGrid = grids.First(); + if (firstGrid->IsDummy()) { + firstGrid->SetStartTime(timeManager->GetStart()); + if (firstGrid->EndTime() >= timeManager->GetEnd()) + firstGrid->SetEndTime(timeManager->GetEnd()); + } else { + cGridElement *grid = AddDummyGrid(timeManager->GetStart(), firstGrid->StartTime(), firstGrid); + } + } +} + +void cChannelEpg::AddNewGridsAtEnd(void) { + cGridElement *lastGrid = NULL; + lastGrid = grids.Last(); + if (lastGrid == NULL) + return; + //if last event is long enough, nothing to do. + if (lastGrid->EndTime() >= timeManager->GetEnd()) { + return; + } + //if not, i have to add new ones to the list + schedules = cSchedules::Schedules(*schedulesLock); + const cSchedule *Schedule = NULL; + Schedule = schedules->GetSchedule(channel); + if (!Schedule) { + if (lastGrid->IsDummy()) { + lastGrid->SetStartTime(timeManager->GetStart()); + lastGrid->SetEndTime(timeManager->GetEnd()); + } + return; + } + bool dummyNeeded = true; + for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) { + if (!event) + break; + if (event->StartTime() > timeManager->GetEnd()) { + break; + } + cGridElement *grid = AddEpgGrid(event); + if (event->EndTime() > timeManager->GetEnd()) { + dummyNeeded = false; + break; + } + } + if (dummyNeeded) { + lastGrid = grids.Last(); + if (lastGrid->IsDummy()) { + lastGrid->SetEndTime(timeManager->GetEnd()); + if (lastGrid->StartTime() <= timeManager->GetStart()) + lastGrid->SetStartTime(timeManager->GetStart()); + } else { + cGridElement *grid = AddDummyGrid(lastGrid->EndTime(), timeManager->GetEnd()); + } + } +} + +void cChannelEpg::ClearOutdatedStart(void) { + deletedElements.clear(); + cGridElement *firstGrid = NULL; + while (true) { + firstGrid = grids.First(); + if (!firstGrid) + break; + if (firstGrid->EndTime() <= timeManager->GetStart()) { + deletedElements.insert(firstGrid->Id()); + grids.Del(firstGrid); + firstGrid = NULL; + } else { + if (firstGrid->IsDummy()) { + firstGrid->SetStartTime(timeManager->GetStart()); + cGridElement *next = GetNext(firstGrid); + if (next) { + firstGrid->SetEndTime(next->StartTime()); + } else { + firstGrid->SetEndTime(timeManager->GetEnd()); + } + } + break; + } + } +} + +void cChannelEpg::ClearOutdatedEnd(void) { + deletedElements.clear(); + cGridElement *lastGrid = NULL; + while (true) { + lastGrid = grids.Last(); + if (!lastGrid) + break; + if (lastGrid->StartTime() >= timeManager->GetEnd()) { + deletedElements.insert(lastGrid->Id()); + grids.Del(lastGrid); + lastGrid = NULL; + } else { + if (lastGrid->IsDummy()) { + lastGrid->SetEndTime(timeManager->GetEnd()); + cGridElement *prev = GetPrev(lastGrid); + if (prev) { + lastGrid->SetStartTime(prev->EndTime()); + } else { + lastGrid->SetStartTime(timeManager->GetStart()); + } + } + break; + } + } +} + +void cChannelEpg::SetTimers(void) { + SetTimer(); + SetSwitchTimer(); + for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { + bool gridHadTimer = grid->HasTimer(); + grid->SetTimer(); + if (gridHadTimer != grid->HasTimer()) { + grid->Dirty(); + } + bool gridHadSwitchTimer = grid->HasSwitchTimer(); + grid->SetSwitchTimer(); + if (gridHadSwitchTimer != grid->HasSwitchTimer()) + grid->Dirty(); + } +} + +void cChannelEpg::DrawHeader(cViewGrid *channelsGrid) { + + double x, y, width, height; + + if (config.displayMode == eHorizontal) { + x = 0.0; + width = 1.0; + height = (double)1 / (double)channelsPerPage; + y = height * (double)position; + } else { + y = 0.0; + height = 1.0; + width = (double)1 / (double)channelsPerPage; + x = width * (double)position; + } + + int id = channel->Number(); + if (init) { + channelsGrid->ClearTokens(); + channelsGrid->AddIntToken("number", id); + channelsGrid->AddStringToken("name", channel->Name()); + string channelId = *(channel->GetChannelID().ToString()); + bool channelLogoExisis = channelsGrid->ChannelLogoExists(channelId); + channelsGrid->AddStringToken("channelid", channelId); + channelsGrid->AddIntToken("channellogoexists", channelLogoExisis); + channelsGrid->SetGrid(id, x, y, width, height); + init = false; + } else { + channelsGrid->MoveGrid(id, x, y, width, height); + } +} + +void cChannelEpg::DrawGrids(cViewGrid *epgGrid) { + int displaySeconds = timeManager->GetDisplaySeconds(); + + double x, y, width, height; + if (config.displayMode == eHorizontal) { + x = 0.0; + width = 0.0; + height = (double)1 / (double)channelsPerPage; + y = height * (double)position; + } else { + y = 0.0; + height = 0.0; + width = (double)1 / (double)channelsPerPage; + x = width * (double)position; + } + time_t startTime = timeManager->GetStart(); + time_t stopTime = timeManager->GetEnd(); + + for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { + time_t gridStart = grid->StartTime(); + time_t gridStop = grid->EndTime(); + if (grid->IsNew()) { + epgGrid->ClearTokens(); + epgGrid->AddIntToken("color", grid->Id() % 2); + epgGrid->AddIntToken("dummy", grid->IsDummy()); + epgGrid->AddIntToken("timer", grid->HasTimer()); + epgGrid->AddIntToken("switchtimer", grid->HasSwitchTimer()); + epgGrid->AddStringToken("title", grid->Title()); + epgGrid->AddStringToken("shorttext", grid->ShortText()); + epgGrid->AddStringToken("start", *TimeString(gridStart)); + epgGrid->AddStringToken("stop", *TimeString(gridStop)); + } + + if (gridStart < startTime) { + gridStart = startTime; + } + if (gridStop > stopTime) { + gridStop = stopTime; + } + if (config.displayMode == eHorizontal) { + int xGrid = gridStart - startTime; + x = (double)xGrid / (double)displaySeconds; + int duration = gridStop - gridStart; + width = (double)duration / (double)displaySeconds; + } else { + int yGrid = gridStart - startTime; + y = (double)yGrid / (double)displaySeconds; + int duration = gridStop - gridStart; + height = (double)duration / (double)displaySeconds; + } + + if (grid->IsNew()) { + epgGrid->SetGrid(grid->Id(), x, y, width, height); + grid->InitFinished(); + } else { + epgGrid->MoveGrid(grid->Id(), x, y, width, height); + } + if (grid->Active()) + epgGrid->SetCurrent(grid->Id(), true); + + } +} + +void cChannelEpg::DeleteOutdated(cViewGrid *epgGrid) { + for (set<long>::iterator it = deletedElements.begin(); it != deletedElements.end(); it++) { + epgGrid->Delete(*it); + } +} + +void cChannelEpg::DeleteGridViews(cViewGrid *epgGrid) { + for (cGridElement *ge = grids.First(); ge; ge = grids.Next(ge)) { + epgGrid->Delete(ge->Id()); + } +} + +cGridElement *cChannelEpg::AddEpgGrid(const cEvent *event, cGridElement *after) { + cGridElement *grid = new cEpgElement(event, this); + if (!after) + grids.Add(grid); + else + grids.Ins(grid, after); + return grid; +} + +cGridElement *cChannelEpg::AddDummyGrid(time_t start, time_t end, cGridElement *after) { + cGridElement *dummy = new cDummyElement(start, end, this); + if (!after) + grids.Add(dummy); + else + grids.Ins(dummy, after); + return dummy; +} + +void cChannelEpg::Debug(void) { + esyslog("tvguideng: channel %s", channel->Name()); + for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { + grid->Debug(); + } +}
\ No newline at end of file |