diff options
author | horchi <vdr@jwendel.de> | 2017-03-05 14:51:57 +0100 |
---|---|---|
committer | horchi <vdr@jwendel.de> | 2017-03-05 14:51:57 +0100 |
commit | 5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f (patch) | |
tree | 392875cb707b94aaba9d8941113eae35efaf2ec2 /menusched.c | |
download | vdr-plugin-epg2vdr-5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f.tar.gz vdr-plugin-epg2vdr-5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f.tar.bz2 |
Diffstat (limited to 'menusched.c')
-rw-r--r-- | menusched.c | 1204 |
1 files changed, 1204 insertions, 0 deletions
diff --git a/menusched.c b/menusched.c new file mode 100644 index 0000000..452c7b4 --- /dev/null +++ b/menusched.c @@ -0,0 +1,1204 @@ +/* + * menusched.c: EPG2VDR plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + */ + +#define __STL_CONFIG_H + +#include <string> + +#include <vdr/menuitems.h> +#include <vdr/status.h> +#include <vdr/menu.h> + +#include "plgconfig.h" +#include "menu.h" +#include "ttools.h" + +class cMenuEpgScheduleItem; + +//*************************************************************************** +// Class cEpgCommandMenu +//*************************************************************************** + +class cEpgCommandMenu : public cOsdMenu +{ + public: + + cEpgCommandMenu(const char* title, cMenuDb* db, const cMenuEpgScheduleItem* aItem); + virtual ~cEpgCommandMenu() { }; + + virtual eOSState ProcessKey(eKeys key); + + protected: + + const cMenuEpgScheduleItem* item; + cMenuDb* menuDb; +}; + +cEpgCommandMenu::cEpgCommandMenu(const char* title, cMenuDb* db, const cMenuEpgScheduleItem* aItem) + : cOsdMenu(title) +{ + item = aItem; + menuDb = db; + + SetMenuCategory(mcMain); + SetHasHotkeys(yes); + Clear(); + + cOsdMenu::Add(new cOsdItem(hk(tr("Search matching Events")), osUser1)); + cOsdMenu::Add(new cOsdItem(hk(tr("Search matching Recordings")), osUser2)); + cOsdMenu::Add(new cOsdItem(hk(tr("Searchtimers")), osUser3)); + + SetHelp(0, 0, 0, 0); + + Display(); +} + +eOSState cEpgCommandMenu::ProcessKey(eKeys key) +{ + eOSState state = cOsdMenu::ProcessKey(key); + + switch (state) + { + case osUser1: + { + if (item) + return AddSubMenu(new cMenuEpgWhatsOn(item->event)); + + break; + } + + case osUser2: + { + if (item) + return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->event)); + + break; + } + + case osUser3: return AddSubMenu(new cMenuEpgSearchTimers()); + + default: ; + } + + return state; +} + +//*************************************************************************** +// Class cMenuEpgMatchRecordings +//*************************************************************************** + +cMenuEpgMatchRecordings::cMenuEpgMatchRecordings(cMenuDb* db, const cEvent* event) + : cOsdMenu(tr("Matching recordings"), 30, 30, 30, 40) +{ + cMenuDb* menuDb = db; + + Add(new cOsdItem(tr("Direct Matches:"))); + cList<cOsdItem>::Last()->SetSelectable(no); + + tell(0, "Search recordings for '%s' '%s'", event->Title(), event->ShortText()); + + menuDb->recordingListDb->clear(); + menuDb->recordingListDb->setValue("TITLE", event->Title()); + menuDb->recordingListDb->setValue("SHORTTEXT", event->ShortText()); + + for (int f = menuDb->selectRecordingForEvent->find(); f; f = menuDb->selectRecordingForEvent->fetch()) + { + const char* vdr = 0; + +#ifdef WITH_PIN + if (!cOsd::pinValid && menuDb->recordingListDb->getIntValue("FSK")) + continue; +#endif + + if (!menuDb->recordingListDb->getValue("OWNER")->isEmpty()) + { + menuDb->vdrDb->clear(); + menuDb->vdrDb->setValue("UUID", menuDb->recordingListDb->getStrValue("OWNER")); + + if (menuDb->vdrDb->find()) + vdr = menuDb->vdrDb->getStrValue("NAME"); + } + + Add(new cEpgMenuTextItem(menuDb->recordingListDb->getStrValue("MD5PATH"), + cString::sprintf("%s%s%s\t%s\t%s/%s", vdr ? vdr : "", vdr ? "\t" : "", + menuDb->recordingListDb->getStrValue("TITLE"), + menuDb->recordingListDb->getStrValue("SHORTTEXT"), + menuDb->recordingListDb->getStrValue("FOLDER"), + menuDb->recordingListDb->getStrValue("NAME")))); + } + + menuDb->selectRecordingForEvent->freeResult(); + + Add(new cOsdItem(tr("All Matches:"))); + cList<cOsdItem>::Last()->SetSelectable(no); + + menuDb->recordingListDb->clear(); + menuDb->recordingListDb->setValue("TITLE", event->Title()); + + for (int f = menuDb->selectRecordingForEventByLv->find(); f; f = menuDb->selectRecordingForEventByLv->fetch()) + { + const char* vdr = 0; + +#ifdef WITH_PIN + if (!cOsd::pinValid && menuDb->recordingListDb->getIntValue("FSK")) + continue; +#endif + + if (!menuDb->recordingListDb->getValue("OWNER")->isEmpty()) + { + menuDb->vdrDb->clear(); + menuDb->vdrDb->setValue("UUID", menuDb->recordingListDb->getStrValue("OWNER")); + + if (menuDb->vdrDb->find()) + vdr = menuDb->vdrDb->getStrValue("NAME"); + } + + Add(new cEpgMenuTextItem(menuDb->recordingListDb->getStrValue("MD5PATH"), + cString::sprintf("%s%s%s\t%s\t%s/%s", vdr ? vdr : "", vdr ? "\t" : "", + menuDb->recordingListDb->getStrValue("TITLE"), + menuDb->recordingListDb->getStrValue("SHORTTEXT"), + menuDb->recordingListDb->getStrValue("FOLDER"), + menuDb->recordingListDb->getStrValue("NAME")))); + } + + menuDb->selectRecordingForEventByLv->freeResult(); + + Display(); +} + +eOSState cMenuEpgMatchRecordings::ProcessKey(eKeys Key) +{ + eOSState state = cOsdMenu::ProcessKey(Key); + + if (state == osUnknown) + { + return osContinue; + } + + return state; +} + +//*************************************************************************** +//*************************************************************************** +// Class cMenuEpgScheduleItem +//*************************************************************************** + +cMenuEpgScheduleItem::eScheduleSortMode cMenuEpgScheduleItem::sortMode = ssmAllThis; + +//*************************************************************************** +// Object +//*************************************************************************** + +cMenuEpgScheduleItem::cMenuEpgScheduleItem(cMenuDb* db, const cEvent* Event, const cChannel* Channel, bool WithDate) +{ + menuDb = db; + + event = Event; + channel = Channel; + withDate = WithDate; + timerMatch = tmNone; + Update(yes); +} + +//*************************************************************************** +// Compare +//*************************************************************************** + +int cMenuEpgScheduleItem::Compare(const cListObject &ListObject) const +{ + cMenuEpgScheduleItem *p = (cMenuEpgScheduleItem *)&ListObject; + int r = -1; + + if (sortMode != ssmAllThis) + r = strcoll(event->Title(), p->event->Title()); + + if (sortMode == ssmAllThis || r == 0) + r = event->StartTime() - p->event->StartTime(); + + return r; +} + +//*************************************************************************** +// Update +//*************************************************************************** + +bool cMenuEpgScheduleItem::Update(bool Force) +{ + static const char* TimerMatchChars = " tT"; + static const char* TimerMatchCharsRemote = " sS"; + + bool result = false; + int oldTimerMatch = timerMatch; + int remote = no; + + if (event) + menuDb->lookupTimer(event, timerMatch, remote); // -> loads timerDb, vdrDb and set ther timerMatch + + if (Force || timerMatch != oldTimerMatch) + { + if (timerMatch && event) + tell(0, "Timer match for '%s'", event->Title()); + + cString buffer; + char t = !remote ? TimerMatchChars[timerMatch] : TimerMatchCharsRemote[timerMatch]; + char v = !event ? ' ' : event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; + char r = !event ? ' ' : event->SeenWithin(30) && event->IsRunning() ? '*' : ' '; + const char* csn = channel ? channel->ShortName(true) : 0; + cString eds = !event ? "" : event->GetDateString(); + + if (channel && withDate) + buffer = cString::sprintf("%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), + Utf8SymChars(csn, 999), csn, Utf8SymChars(eds, 6), + *eds, + !event ? "" : *event->GetTimeString(), + t, v, r, + !event ? "" : event->Title()); + else if (channel) + buffer = cString::sprintf("%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), + Utf8SymChars(csn, 999), csn, + !event ? "" : *event->GetTimeString(), + t, v, r, + !event ? "" : event->Title()); + else + buffer = cString::sprintf("%.*s\t%s\t%c%c%c\t%s", Utf8SymChars(eds, 6), *eds, + !event ? "" : *event->GetTimeString(), + t, v, r, !event ? "" : + !event ? "" : event->Title()); + + SetText(buffer); + result = true; + } + + return result; +} + +//*************************************************************************** +// SetMenuItem +//*************************************************************************** + +void cMenuEpgScheduleItem::SetMenuItem(cSkinDisplayMenu* DisplayMenu, + int Index, bool Current, bool Selectable) +{ + if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, + withDate, (eTimerMatch)timerMatch)) + { + DisplayMenu->SetItem(Text(), Index, Current, Selectable); + } +} + +//*************************************************************************** +//*************************************************************************** +// cMenuEpgScheduleSepItem +//*************************************************************************** + +class cMenuEpgScheduleSepItem : public cOsdItem +{ + public: + + cMenuEpgScheduleSepItem(const cChannel* Channel, const cEvent* Event); + ~cMenuEpgScheduleSepItem(); + + virtual bool Update(bool Force = false); + virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); + + private: + + const cChannel* channel; + const cEvent* event; + cEvent* tmpEvent; +}; + +cMenuEpgScheduleSepItem::cMenuEpgScheduleSepItem(const cChannel* Channel, const cEvent* Event) +{ + channel = Channel; + event = Event; + tmpEvent = 0; + + SetSelectable(false); + Update(true); +} + +cMenuEpgScheduleSepItem::~cMenuEpgScheduleSepItem() +{ + delete tmpEvent; +} + +bool cMenuEpgScheduleSepItem::Update(bool Force) +{ + if (channel) + { + SetText(cString::sprintf("-----\t %s -----", channel ? channel->Name() : *event->GetDateString())); + } + else if (event) + { + tmpEvent = new cEvent(0); + tmpEvent->SetTitle(cString::sprintf("-----\t %s -----", *event->GetDateString())); + SetText(tmpEvent->Title()); + } + + return true; +} + +void cMenuEpgScheduleSepItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable) +{ + if (!DisplayMenu->SetItemEvent(tmpEvent, Index, Current, Selectable, channel, no, tmNone)) + DisplayMenu->SetItem(Text(), Index, Current, Selectable); +} + +//*************************************************************************** +// cMenuEpgEvent +//*************************************************************************** + +cMenuEpgEvent::cMenuEpgEvent(cMenuDb* db, const cEvent* Event, const cSchedules* Schedules, + int timerMatch, bool DispSchedule, bool CanSwitch) + : cOsdMenu(tr("Event")) +{ + menuDb = db; + dispSchedule = DispSchedule; + schedules = Schedules; + canSwitch = CanSwitch; + SetMenuCategory(mcEvent); + setEvent(Event, timerMatch); +} + +//*************************************************************************** +// Set Event +//*************************************************************************** + +int cMenuEpgEvent::setEvent(const cEvent* Event, int timerMatch) +{ + if (Event) + { + event = Event; + +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; + const cChannel* channel = channels->GetByChannelID(event->ChannelID(), true); +#else + cChannels* channels = &Channels; + cChannel* channel = channels->GetByChannelID(event->ChannelID(), true); +#endif + + if (channel) + { + const cChannel* prevChannel = 0; + const cChannel* nextChannel = 0; + + prevTime = ""; + nextTime = ""; + + SetTitle(channel->Name()); + + if (menuDb->userTimes->current()->getMode() != cUserTimes::mSearch) + { + const cEvent* e; + + if (e = getNextPrevEvent(event, -1)) + { + if (dispSchedule) + prevTime = l2pTime(e->StartTime(), "%H:%M"); + else + prevChannel = channels->GetByChannelID(e->ChannelID(), true); + } + + if (e = getNextPrevEvent(event, +1)) + { + if (dispSchedule) + nextTime = l2pTime(e->StartTime(), "%H:%M"); + else + nextChannel = channels->GetByChannelID(e->ChannelID(), true); + } + } + + SetHelp(timerMatch == tmFull ? tr("Button$Timer") : tr("Button$Record"), + dispSchedule ? prevTime.c_str() : (prevChannel ? prevChannel->Name() : 0), + dispSchedule ? nextTime.c_str() : (nextChannel ? nextChannel->Name() : 0), + canSwitch ? tr("Button$Switch") : 0); + } + + Display(); + } + + return success; +} + +void cMenuEpgEvent::Display() +{ + cOsdMenu::Display(); + DisplayMenu()->SetEvent(event); + +#ifdef WITH_GTFT + cStatus::MsgOsdSetEvent(event); +#endif + + if (event->Description()) + cStatus::MsgOsdTextItem(event->Description()); +} + +//*************************************************************************** +// Get Next Prev Event (related to current) +//*************************************************************************** + +const cEvent* cMenuEpgEvent::getNextPrevEvent(const cEvent* event, int step) +{ +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; + const cChannel* channel = channels->GetByChannelID(event->ChannelID(), true); +#else + cChannels* channels = &Channels; + cChannel* channel = channels->GetByChannelID(event->ChannelID(), true); +#endif + + const cEvent* e = 0; + + if (dispSchedule) + { + const cSchedule* schedule = schedules->GetSchedule(channel); + + if (schedule && step == -1) + e = schedule->Events()->Prev(event); + else if (schedule && step == +1) + e = schedule->Events()->Next(event); + } + else + { + while (!e) + { + int cn = channel->Number() + step; + + if (cn < 1) + cn = channels->MaxNumber(); + else if (cn > channels->MaxNumber()) + cn = 1; + + if (!(channel = channels->GetByNumber(cn))) + return 0; + + const cSchedule* schedule = schedules->GetSchedule(channel); + + if (schedule) + { + cUserTimes::UserTime* userTime = menuDb->userTimes->current(); + + switch (userTime->getMode()) + { + case cUserTimes::mNow: e = schedule->GetPresentEvent(); break; + case cUserTimes::mNext: e = schedule->GetFollowingEvent(); break; + case cUserTimes::mTime: e = schedule->GetEventAround(userTime->getTime()); break; + } + } + } + } + + return e; +} + +//*************************************************************************** +// Process Key +//*************************************************************************** + +eOSState cMenuEpgEvent::ProcessKey(eKeys Key) +{ + switch (int(Key)) + { + case kUp|k_Repeat: + case kUp: + case kDown|k_Repeat: + case kDown: + case kLeft|k_Repeat: + case kLeft: + case kRight|k_Repeat: + case kRight: + { + DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight); + cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft); + return osContinue; + } + + case kInfo: return osBack; + default: break; + } + + if (Key == kGreen || Key == kYellow) + { + if (menuDb->userTimes->current()->getMode() == cUserTimes::mSearch) + return osContinue; + + const cEvent* e = getNextPrevEvent(event, Key == kGreen ? -1 : +1); + int remote = no; + int timerMatch = tmNone; + + // get remote and timerMatch info + + menuDb->lookupTimer(e, timerMatch, remote); + setEvent(e, timerMatch); + + return osContinue; + } + + eOSState state = cOsdMenu::ProcessKey(Key); + + if (state == osUnknown) + { + switch (Key) + { + case kOk: return osBack; + default: break; + } + } + + return state; +} + +//*************************************************************************** +//*************************************************************************** +// cMenuEpgWhatsOn +//*************************************************************************** + +int cMenuEpgWhatsOn::currentChannel = 0; +const cEvent* cMenuEpgWhatsOn::scheduleEvent = 0; + +//*************************************************************************** +// Object +//*************************************************************************** + +cMenuEpgWhatsOn::cMenuEpgWhatsOn(const cEvent* aSearchEvent) + : cOsdMenu("", CHNUMWIDTH, CHNAMWIDTH, 6, 4) +{ +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) +#else + schedulesLock = 0; +#endif + schedules = 0; + dispSchedule = no; + canSwitch = no; + helpKeys = 0; + helpKeyTime = 0; + helpKeyTimeMode = na; +// timerState = 0; + searchEvent = aSearchEvent; + menuDb = new cMenuDb; + +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; + const cChannel* channel = channels->GetByNumber(cDevice::CurrentChannel()); +#else + cChannels* channels = &Channels; + const cChannel* channel = channels->GetByNumber(cDevice::CurrentChannel()); +#endif + + if (channel) + { + currentChannel = channel->Number(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + schedules = cSchedules::GetSchedulesRead(schedulesKey); +#else + schedulesLock = new cSchedulesLock(false); + schedules = (cSchedules*)cSchedules::Schedules(*schedulesLock); +#endif + } + +// Timers.Modified(timerState); + + if (menuDb->dbConnected()) + { + menuDb->userTimes->first(); // 'whats on now' should be the first + + if (searchEvent) + LoadQuery(searchEvent); + else if (menuDb->startWithSched) + LoadSchedule(); + else + LoadAt(); + } +} + +cMenuEpgWhatsOn::~cMenuEpgWhatsOn() +{ + delete menuDb; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + if (schedules) + schedulesKey.Remove(); +#else + tell(3, "LOCK free (cMenuEpgWhatsOn)"); + delete schedulesLock; +#endif +} + +//*************************************************************************** +// Load At +//*************************************************************************** + +int cMenuEpgWhatsOn::LoadAt() +{ + dispSchedule = no; + cUserTimes::UserTime* userTime = menuDb->userTimes->current(); + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (item) + { + scheduleEvent = item->event; + + if (item->channel) + currentChannel = item->channel->Number(); + } + + if (userTime->getMode() == cUserTimes::mSearch) + return LoadSearch(userTime); + + Clear(); +// Timers.Modified(timerState); + + SetMenuCategory(userTime->getMode() == cUserTimes::mNow ? mcScheduleNow : mcScheduleNext); + + if (isEmpty(userTime->getHHMMStr())) + SetTitle(cString::sprintf(tr("Overview - %s"), userTime->getTitle())); + else + SetTitle(cString::sprintf(tr("Overview - %s (%s)"), userTime->getTitle(), userTime->getHHMMStr())); + + tell(2, "DEBUG: Loading events for '%s' %s", userTime->getTitle(), !isEmpty(userTime->getHHMMStr()) ? userTime->getHHMMStr() : ""); + +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + + // events + + for (const cChannel* Channel = channels->First(); Channel; Channel = channels->Next(Channel)) + { + if (!Channel->GroupSep()) + { + const cSchedule* Schedule = schedules->GetSchedule(Channel); + const cEvent* Event = 0; + + if (Schedule) + { + switch (userTime->getMode()) + { + case cUserTimes::mNow: Event = Schedule->GetPresentEvent(); break; + case cUserTimes::mNext: Event = Schedule->GetFollowingEvent(); break; + case cUserTimes::mTime: Event = Schedule->GetEventAround(userTime->getTime()); break; + } + } + + // #TODO + // hier ein cEpgEvent für das Event aus der Row erzeugen und dieses anstelle von cEvent für das Menü verwenden + + if (!Event && !Epg2VdrConfig.showEmptyChannels) + continue; + + Add(new cMenuEpgScheduleItem(menuDb, Event, Channel), Channel->Number() == currentChannel); + } + else + { + if (strlen(Channel->Name())) + Add(new cMenuEpgScheduleSepItem(Channel, 0)); + } + } + + Display(); + SetHelpKeys(); + + return done; +} + +//*************************************************************************** +// Load Search +//*************************************************************************** + +int cMenuEpgWhatsOn::LoadSearch(const cUserTimes::UserTime* userTime) +{ + cDbStatement* select = 0; + + Clear(); + SetMenuCategory(mcSchedule); + SetTitle(cString::sprintf(tr("Overview - %s"), userTime->getTitle())); + tell(2, "DEBUG: Loading events for search '%s'", userTime->getSearch()); + + menuDb->searchtimerDb->clear(); + menuDb->searchtimerDb->setValue("NAME", userTime->getSearch()); + + if (!menuDb->selectSearchTimerByName->find()) + return done; + + if (!(select = menuDb->search->prepareSearchStatement(menuDb->searchtimerDb->getRow(), menuDb->useeventsDb))) + return fail; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + cChannelsLock channelsLock(false); + const cChannels* channels = channelsLock.Channels(); +#else + cChannels* channels = &Channels; +#endif + + menuDb->useeventsDb->clear(); + + for (int res = select->find(); res; res = select->fetch()) + { + menuDb->useeventsDb->find(); // get all fields .. + + if (!menuDb->search->matchCriterias(menuDb->searchtimerDb->getRow(), menuDb->useeventsDb->getRow())) + continue; + + // + + const char* strChannelId = menuDb->useeventsDb->getStrValue("CHANNELID"); + const cChannel* channel = channels->GetByChannelID(tChannelID::FromString(strChannelId)); + const cSchedule* schedule = schedules->GetSchedule(channel); + const cEvent* event = !schedule ? 0 : schedule->GetEvent(menuDb->useeventsDb->getIntValue("USEID")); + + if (event) + Add(new cMenuEpgScheduleItem(menuDb, event, channel, yes)); + } + + select->freeResult(); + menuDb->selectSearchTimerByName->freeResult(); + + Display(); + SetHelpKeys(); + + return Count(); +} + +//*************************************************************************** +// Load Schedule +//*************************************************************************** + +int cMenuEpgWhatsOn::LoadSchedule() +{ + Clear(); + SetCols(7, 6, 4); + dispSchedule = yes; + +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; + const cChannel* channel = channels->GetByNumber(currentChannel); +#else + cChannels* channels = &Channels; + const cChannel* channel = channels->GetByNumber(currentChannel); +#endif + + cMenuEpgScheduleItem::SetSortMode(cMenuEpgScheduleItem::ssmAllThis); + SetMenuCategory(mcSchedule); + SetTitle(cString::sprintf(tr("Schedule - %s"), channel->Name())); + + if (schedules && channel) + { + const cSchedule* Schedule = schedules->GetSchedule(channel); + + if (Schedule) + { + int lastDay = 0; + const cEvent* PresentEvent = scheduleEvent ? scheduleEvent : Schedule->GetPresentEvent(); + time_t now = time(0) - Setup.EPGLinger * 60; + + for (const cEvent* ev = Schedule->Events()->First(); ev; ev = Schedule->Events()->Next(ev)) + { + time_t stime = ev->StartTime(); + struct tm tmSTime; + localtime_r(&stime, &tmSTime); + + if (lastDay != 0 && tmSTime.tm_mday != lastDay) + Add(new cMenuEpgScheduleSepItem(0, ev)); + + if (ev->EndTime() > now || ev == PresentEvent) + Add(new cMenuEpgScheduleItem(menuDb, ev, channel), ev == PresentEvent); + + lastDay = tmSTime.tm_mday; + } + } + } + + Display(); + SetHelpKeys(); + + return done; +} + +//*************************************************************************** +// Load Query +//*************************************************************************** + +int cMenuEpgWhatsOn::LoadQuery(const cEvent* searchEvent) +{ + Clear(); + SetMenuCategory(mcSchedule); + cMenuEpgScheduleItem::SetSortMode(cMenuEpgScheduleItem::ssmAllThis); + +#if APIVERSNUM >= 20301 + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + + tell(1, "Lookup events with title '%s'", searchEvent->Title()); + + for (const cChannel* channel = channels->First(); channel; channel = channels->Next(channel)) + { + const cSchedule* schedule = schedules->GetSchedule(channel); + + if (schedule) + { + for (const cEvent* event = schedule->Events()->First(); event; event = schedule->Events()->Next(event)) + { + if (strcasecmp(event->Title(), searchEvent->Title()) == 0 && + event->StartTime() > time(0)) + Add(new cMenuEpgScheduleItem(menuDb, event, channel, yes)); + } + } + } + + Sort(); + SetTitle(cString::sprintf("%d %s - %s", Count(), tr("Search results"), searchEvent->Title())); + + Display(); + SetHelpKeys(); + + return Count(); +} + +//*************************************************************************** +// Display +//*************************************************************************** + +void cMenuEpgWhatsOn::Display() +{ + cOsdMenu::Display(); + +#ifdef WITH_GTFT + if (Count() > 0) + { + int ni = 0; + + for (cOsdItem *item = First(); item; item = Next(item)) + cStatus::MsgOsdEventItem(((cMenuEpgScheduleItem*)item)->event, item->Text(), ni++, Count()); + } +#endif +} + +//*************************************************************************** +// Update +//*************************************************************************** + +bool cMenuEpgWhatsOn::Update() +{ + bool result = false; + + for (cOsdItem* item = First(); item; item = Next(item)) + { + if (((cMenuEpgScheduleItem*)item)->Update()) + result = true; + } + + return result; +} + +//*************************************************************************** +// SetHelpKeys +//*************************************************************************** + +void cMenuEpgWhatsOn::SetHelpKeys() +{ + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem *)Get(Current()); + canSwitch = no; + int NewHelpKeys = 0; + + if (item) + { + if (item->timerMatch == tmFull) + NewHelpKeys |= 0x02; // "Timer" + else + NewHelpKeys |= 0x01; // "Record" + + if (!dispSchedule) + NewHelpKeys |= 0x04; // "Schedule" + + if (item->channel) + { + if (item->channel->Number() != cDevice::CurrentChannel()) + { + NewHelpKeys |= 0x10; // "Switch" + canSwitch = yes; + } + } + } + + cUserTimes::UserTime* userTimeGreen = !dispSchedule ? menuDb->userTimes->getNext() : menuDb->userTimes->current(); + + if (NewHelpKeys != helpKeys || helpKeyTime != userTimeGreen->getTime() || helpKeyTimeMode != userTimeGreen->getMode()) + { + const char* Red[] = { 0, tr("Button$Record"), tr("Button$Timer") }; + + if (searchEvent) + { + helpKeys = 0; + helpKeyTime = 0; + helpKeyTimeMode = na; + + SetHelp(Red[NewHelpKeys & 0x03], 0, 0, 0); + } + else + { + SetHelp(Red[NewHelpKeys & 0x03], // red + userTimeGreen->getHelpKey(), // green + !dispSchedule + ? tr("Button$Schedule") // yellow + : menuDb->userTimes->current() == menuDb->userTimes->getFirst() + ? tr(menuDb->userTimes->getNext()->getHelpKey()) // yellow + : tr(menuDb->userTimes->getFirst()->getHelpKey()), // yellow + Epg2VdrConfig.xchgOkBlue ? tr("Button$Info") : canSwitch ? tr("Button$Switch") : 0); // blue + + helpKeyTime = userTimeGreen->getTime(); + helpKeyTimeMode = userTimeGreen->getMode(); + helpKeys = NewHelpKeys; + } + } +} + +//*************************************************************************** +// Switch +//*************************************************************************** + +eOSState cMenuEpgWhatsOn::Switch() +{ + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (cDevice::PrimaryDevice()->SwitchChannel(item->channel, true)) + return osEnd; + + Skins.Message(mtError, tr("Can't switch channel!")); + + return osContinue; +} + +//*************************************************************************** +// Record +//*************************************************************************** + +eOSState cMenuEpgWhatsOn::Record() +{ + int timerMatch = tmNone; + cEpgTimer* timer = 0; + long timerid = 0; + int remote = no; + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (!item) + return osContinue; + + if (timerid = menuDb->lookupTimer(item->event, timerMatch, remote)) // -> loads timerDb and vdrDb + { + menuDb->timerDb->clear(); + menuDb->timerDb->setValue("ID", timerid); + + if (!menuDb->selectTimerById->find()) + { + tell(0, "Fatal, Can't find timer (%ld)", timerid); + return osContinue; + } + + timer = newTimerObjectFromRow(menuDb->timerDb->getRow(), menuDb->vdrDb->getRow()); + } + + if (timer) + return AddSubMenu(new cMenuEpgEditTimer(menuDb, timer)); + + // neuen Timer anlegen + + cDbRow* timerRow = newTimerRowFromEvent(item->event); + char timerDefaultVDRuuid[150+TB] = ""; + + menuDb->getParameter(menuDb->user.c_str(), "timerDefaultVDRuuid", timerDefaultVDRuuid); + + // Menü bei 'aktuellem' Event Timer Dialog öffen -> #TODO + + if (timer && timer->Event() && timer->Event()->StartTime() < time(0) + NEWTIMERLIMIT) + { + // timer = newTimerObjectFromRow(timerRow, xxxxx); + // return AddSubMenu(new cMenuEpgEditTimer(menuDb, timer)); + } + + // ansonsten direkt anlegen + + menuDb->createTimer(timerRow, isEmpty(timerDefaultVDRuuid) || Epg2VdrConfig.createTimerLocal ? Epg2VdrConfig.uuid : timerDefaultVDRuuid); + delete timerRow; + + if (HasSubMenu()) + CloseSubMenu(); + + sleep(1); + + if (Update()) + Display(); + + SetHelpKeys(); + + return osContinue; +} + +//*************************************************************************** +// ProcessKey +//*************************************************************************** + +eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) +{ + bool HadSubMenu = HasSubMenu(); + eOSState state = cOsdMenu::ProcessKey(Key); + + if (!menuDb->dbConnected()) + return state; + + if (state == osUnknown) + { + if (searchEvent && Key != kOk && Key != kRed && Key != kRecord) + return osContinue; + + if (Epg2VdrConfig.xchgOkBlue && !HasSubMenu()) + { + if (Key == kBlue) Key = kOk; + else if (Key == kOk) Key = kBlue; + } + + switch (Key) + { + case k0: // command menu + { + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + return AddSubMenu(new cEpgCommandMenu("Commands", menuDb, item)); + } + + case k1: // search repeat of event + { + if (Get(Current())) + { + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (item) + return AddSubMenu(new cMenuEpgWhatsOn(item->event)); + } + + break; + } + + case k2: // search matching recordings + { + if (Get(Current())) + { + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (item) + return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->event)); + } + + break; + } + + case k3: // search timer dialog + { + return AddSubMenu(new cMenuEpgSearchTimers()); + } + + case k4: // Umschalt Timer erstellen + { + break; + } + + case kRecord: + case kRed: + return Record(); + + case kYellow: + { + if (!dispSchedule && Get(Current())) + { + cMenuEpgScheduleItem* mi = (cMenuEpgScheduleItem*)Get(Current()); + + if (mi) + { + scheduleEvent = mi->event; + currentChannel = mi->channel->Number(); + LoadSchedule(); + } + } + else + { + if (menuDb->userTimes->current() == menuDb->userTimes->getFirst()) + menuDb->userTimes->next(); + else + menuDb->userTimes->first(); + + LoadAt(); + } + + return osContinue; + } + case kGreen: + { + if (!dispSchedule) + menuDb->userTimes->next(); + + LoadAt(); + + return osContinue; + } + + case kBlue: + { + if (canSwitch) + return Switch(); + + break; + } + + case kInfo: + case kOk: + { + if (Get(Current())) + { + cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); + + if (item) + { + const cEvent* event = item->event; + + if (Count() && event) + return AddSubMenu(new cMenuEpgEvent(menuDb, event, schedules, + item->timerMatch, dispSchedule, canSwitch)); + } + } + + break; + } + + default: + break; + } + } + + if (!HasSubMenu()) + { + if (HadSubMenu && Update()) + Display(); + + if (Key != kNone) + SetHelpKeys(); + } + + return state; +} + +//*************************************************************************** |