summaryrefslogtreecommitdiff
path: root/channelepg.c
diff options
context:
space:
mode:
Diffstat (limited to 'channelepg.c')
-rw-r--r--channelepg.c444
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