#include "channelepg.h" #include "dummygrid.h" cChannelEpg::cChannelEpg(int num, const cChannel *channel, cTimeManager *timeManager) { this->channel = channel; this->num = num; this->timeManager = timeManager; #if VDRVERSNUM < 20301 hasTimer = channel->HasTimer(); #endif hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel); #if VDRVERSNUM < 20301 schedulesLock = new cSchedulesLock(false, 100); #endif header = NULL; } cChannelEpg::~cChannelEpg(void) { if (header) delete header; grids.Clear(); #if VDRVERSNUM < 20301 delete schedulesLock; #endif } void cChannelEpg::clearGrids() { grids.Clear(); } void cChannelEpg::createHeader() { header = new cHeaderGrid(); header->createBackground(num); header->drawChannel(channel); } void cChannelEpg::drawHeader() { header->setPosition(num); } bool cChannelEpg::readGrids() { #if VDRVERSNUM >= 20301 const cSchedules* schedules; { LOCK_SCHEDULES_READ; schedules = Schedules; } #else schedules = cSchedules::Schedules(*schedulesLock); #endif const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); if (!Schedule) { addDummyGrid(timeManager->GetStart(), timeManager->GetEnd(), NULL, false); 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) { bool col = true; if (dummyAtStart) { addDummyGrid(timeManager->GetStart(), startEvent->StartTime(), NULL, col); col = !col; } 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()) { //gap, dummy needed time_t endTime = event->StartTime(); if (endTime > timeManager->GetEnd()) { endTime = timeManager->GetEnd(); toFarInFuture = true; } addDummyGrid(endLast, endTime, NULL, col); col = !col; } if (toFarInFuture) { break; } addEpgGrid(event, NULL, col); col = !col; endLast = event->EndTime(); if (event->EndTime() > timeManager->GetEnd()) { dummyNeeded = false; break; } eventLast = event; } if (dummyNeeded) { addDummyGrid(eventLast->EndTime(), timeManager->GetEnd(), NULL, col); } return true; } else { addDummyGrid(timeManager->GetStart(), timeManager->GetEnd(), NULL, false); return true; } return false; } void cChannelEpg::drawGrids() { for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { grid->SetViewportHeight(); grid->PositionPixmap(); grid->Draw(); } } int cChannelEpg::getX() { return geoManager.timeLineWidth + num*geoManager.colWidth; } int cChannelEpg::getY() { return geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight; } cGridElement *cChannelEpg::getActive(bool last) { cTimeManager t; t.Now(); if (last) return grids.Last(); 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() { 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 #if VDRVERSNUM >= 20301 const cSchedules* schedules; { LOCK_SCHEDULES_READ; schedules = Schedules; } #else schedules = cSchedules::Schedules(*schedulesLock); #endif const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); if (!Schedule) { if (firstGrid->IsDummy()) { firstGrid->SetStartTime(timeManager->GetStart()); firstGrid->SetEndTime(timeManager->GetEnd()); } return; } bool col = !(firstGrid->IsColor1()); 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, col); col = !col; 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 { addDummyGrid(timeManager->GetStart(), firstGrid->StartTime(), firstGrid, col); } } } void cChannelEpg::AddNewGridsAtEnd() { 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 #if VDRVERSNUM >= 20301 const cSchedules* schedules; { LOCK_SCHEDULES_READ; schedules = Schedules; } #else schedules = cSchedules::Schedules(*schedulesLock); #endif const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); if (!Schedule) { if (lastGrid->IsDummy()) { lastGrid->SetStartTime(timeManager->GetStart()); lastGrid->SetEndTime(timeManager->GetEnd()); } return; } bool col = !(lastGrid->IsColor1()); 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; } addEpgGrid(event, NULL, col); col = !col; 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 { addDummyGrid(lastGrid->EndTime(), timeManager->GetEnd(), NULL, col); } } } void cChannelEpg::ClearOutdatedStart() { cGridElement *firstGrid = NULL; while (true) { firstGrid = grids.First(); if (!firstGrid) break; if (firstGrid->EndTime() <= timeManager->GetStart()) { 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() { cGridElement *lastGrid = NULL; while (true) { lastGrid = grids.Last(); if (!lastGrid) break; if (lastGrid->StartTime() >= timeManager->GetEnd()) { 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; } } } 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; } 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; } void cChannelEpg::SetTimers() { #if VDRVERSNUM < 20301 hasTimer = channel->HasTimer(); #endif hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel); for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { bool gridHadTimer = grid->HasTimer(); grid->SetTimer(); if (gridHadTimer || gridHadTimer != grid->HasTimer()) grid->SetDirty(); bool gridHadSwitchTimer = grid->HasSwitchTimer(); grid->SetSwitchTimer(); if (gridHadSwitchTimer != grid->HasSwitchTimer()) grid->SetDirty(); grid->Draw(); } } void cChannelEpg::dumpGrids() { esyslog("tvguide: ------Channel %s %d: %d entires ---------", channel->Name(), num, grids.Count()); int i=1; for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { esyslog("tvguide: grid %d: start: %s, stop: %s", i, *cTimeManager::printTime(grid->StartTime()), *cTimeManager::printTime(grid->EndTime())); i++; } }