From 4623e7b345f850ac44cdcacbd0e43e139a4baa6a Mon Sep 17 00:00:00 2001 From: louis Date: Sun, 13 Mar 2016 16:07:21 +0100 Subject: added VDR 2.3.1 compatibility --- channelepg.c | 46 +- channelepg.h | 4 +- channelgroups.c | 28 +- channeljump.c | 90 +- channeljump.h | 50 +- definitions.h | 1090 ++++++++-------- detailview.c | 1572 +++++++++++------------ detailview.h | 98 +- epgelement.c | 104 +- epgelement.h | 54 +- epggrid.c | 124 +- gridelement.c | 112 +- gridelement.h | 100 +- recmanager.c | 237 +++- recmanager.h | 10 +- recmenu.c | 1244 +++++++++---------- recmenu.h | 130 +- recmenuitem.c | 3159 ++++++++++++++++++++++++----------------------- recmenuitem.h | 990 +++++++-------- recmenus.c | 2336 ++++++++++++++++++----------------- recmenus.h | 902 +++++++------- recmenuview.c | 1757 +++++++++++++------------- recmenuview.h | 92 +- searchtimer.c | 1181 +++++++++--------- searchtimer.h | 272 ++-- services/remotetimers.h | 6 +- timemanager.c | 344 +++--- timemanager.h | 120 +- timerconflict.c | 357 +++--- timerconflict.h | 74 +- tvguidengosd.c | 16 +- 31 files changed, 8562 insertions(+), 8137 deletions(-) diff --git a/channelepg.c b/channelepg.c index bde905d..3ca9173 100644 --- a/channelepg.c +++ b/channelepg.c @@ -8,12 +8,10 @@ cChannelEpg::cChannelEpg(int position, const cChannel *channel, cTimeManager *ti 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) { @@ -21,8 +19,19 @@ void cChannelEpg::ClearGrids(void) { } bool cChannelEpg::ReadGrids(void) { - schedules = cSchedules::Schedules(*schedulesLock); + const cSchedule *Schedule = NULL; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else + cSchedulesLock schedulesLock; + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + if (!schedules) + return false; + Schedule = schedules->GetSchedule(channel); if (!Schedule) { AddDummyGrid(timeManager->GetStart(), timeManager->GetEnd()); @@ -162,7 +171,15 @@ void cChannelEpg::AddNewGridsAtStart(void) { return; } //if not, i have to add new ones to the list - schedules = cSchedules::Schedules(*schedulesLock); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else + cSchedulesLock schedulesLock; + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + if (!schedules) + return ; const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); if (!Schedule) { @@ -208,7 +225,15 @@ void cChannelEpg::AddNewGridsAtEnd(void) { return; } //if not, i have to add new ones to the list - schedules = cSchedules::Schedules(*schedulesLock); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else + cSchedulesLock schedulesLock; + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + if (!schedules) + return ; const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); if (!Schedule) { @@ -439,4 +464,13 @@ void cChannelEpg::Debug(void) { for (cGridElement *grid = grids.First(); grid; grid = grids.Next(grid)) { grid->Debug(); } -} \ No newline at end of file +} + +void cChannelEpg::SetTimer() +{ +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) +#else + hasTimer = channel->HasTimer(); +#endif + +}; diff --git a/channelepg.h b/channelepg.h index 63f24d4..177b104 100644 --- a/channelepg.h +++ b/channelepg.h @@ -23,8 +23,6 @@ private: const cChannel *channel; cList grids; set deletedElements; - cSchedulesLock *schedulesLock; - const cSchedules *schedules; bool hasTimer; bool hasSwitchTimer; cGridElement *AddEpgGrid(const cEvent *event, cGridElement *after = NULL); @@ -47,7 +45,7 @@ public: void ClearOutdatedStart(void); void ClearOutdatedEnd(void); void SetTimers(void); - void SetTimer(void) { hasTimer = channel->HasTimer(); }; + void SetTimer(void); bool HasTimer(void) { return hasTimer; }; void SetSwitchTimer() {hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);}; bool HasSwitchTimer() { return hasSwitchTimer; }; diff --git a/channelgroups.c b/channelgroups.c index 9ea8bfb..ff7efc4 100644 --- a/channelgroups.c +++ b/channelgroups.c @@ -31,12 +31,18 @@ void cChannelgroups::Init(void) { bool setStart = false; int lastChannelNumber = 0; int id = 0; - const cChannel *first = Channels.First(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + const cChannel *first = channels->First(); if (!first->GroupSep()) { channelGroups.push_back(cChannelGroup(tr("Main Program"), id++)); setStart = true; } - for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) { + for (const cChannel *channel = channels->First(); channel; channel = channels->Next(channel)) { if (setStart && (channelGroups.size() > 0)) { channelGroups[channelGroups.size()-1].SetChannelStart(channel->Number()); setStart = false; @@ -82,7 +88,14 @@ void cChannelgroups::Draw(const cChannel *start, const cChannel *stop) { int fields = 1; double offset = 0.0; - for (const cChannel *channel = Channels.Next(start); channel; channel = Channels.Next(channel)) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + + for (const cChannel *channel = channels->Next(start); channel; channel = channels->Next(channel)) { if (channel->GroupSep()) continue; if (config.hideLastChannelGroup && IsInLastGroup(channel)) { @@ -200,5 +213,12 @@ int cChannelgroups::GetLastValidChannel(void) { if (config.hideLastChannelGroup && channelGroups.size() > 1) { return channelGroups[channelGroups.size()-2].StopChannel(); } - return Channels.MaxNumber(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + return Channels->MaxNumber(); +#else + return Channels.MaxNumber(); +#endif + + } diff --git a/channeljump.c b/channeljump.c index 935a129..b149dcf 100644 --- a/channeljump.c +++ b/channeljump.c @@ -1,46 +1,46 @@ -#include -#include "channeljump.h" - -cChannelJump::cChannelJump(skindesignerapi::cViewElement *channelJump, int lastValidChannel) { - this->channelJump = channelJump; - channel = 0; - maxChannels = lastValidChannel; - startTime = 0; - timeout = Setup.ChannelEntryTimeout; -} - -cChannelJump::~cChannelJump(void) { - channelJump->Clear(); - delete channelJump; -} - -void cChannelJump::Draw(void) { - channelJump->Clear(); - channelJump->ClearTokens(); - channelJump->AddStringToken((int)eChannelJumpST::channel, *BuildChannelString()); - channelJump->Display(); -} - -void cChannelJump::Set(int key) { - startTime = cTimeMs::Now(); - if (channel == 0) { - channel = key; - return; - } - int newChannel = channel * 10 + key; - if (newChannel <= maxChannels) - channel = newChannel; -} - -cString cChannelJump::BuildChannelString(void) { - if (channel*10 <= maxChannels) - return cString::sprintf("%d-", channel); - else - return cString::sprintf("%d", channel); -} - - bool cChannelJump::TimeOut(void) { - if ((int)(cTimeMs::Now() - startTime) > timeout) - return true; - return false; +#include +#include "channeljump.h" + +cChannelJump::cChannelJump(skindesignerapi::cViewElement *channelJump, int lastValidChannel) { + this->channelJump = channelJump; + channel = 0; + maxChannels = lastValidChannel; + startTime = 0; + timeout = Setup.ChannelEntryTimeout; +} + +cChannelJump::~cChannelJump(void) { + channelJump->Clear(); + delete channelJump; +} + +void cChannelJump::Draw(void) { + channelJump->Clear(); + channelJump->ClearTokens(); + channelJump->AddStringToken((int)eChannelJumpST::channel, *BuildChannelString()); + channelJump->Display(); +} + +void cChannelJump::Set(int key) { + startTime = cTimeMs::Now(); + if (channel == 0) { + channel = key; + return; + } + int newChannel = channel * 10 + key; + if (newChannel <= maxChannels) + channel = newChannel; +} + +cString cChannelJump::BuildChannelString(void) { + if (channel*10 <= maxChannels) + return cString::sprintf("%d-", channel); + else + return cString::sprintf("%d", channel); +} + + bool cChannelJump::TimeOut(void) { + if ((int)(cTimeMs::Now() - startTime) > timeout) + return true; + return false; } \ No newline at end of file diff --git a/channeljump.h b/channeljump.h index 251482a..e431a9b 100644 --- a/channeljump.h +++ b/channeljump.h @@ -1,26 +1,26 @@ -#ifndef __TVGUIDE_CHANNELJUMP_H -#define __TVGUIDE_CHANNELJUMP_H - -#include -#include "definitions.h" - -// --- cChannelJump ------------------------------------------------------------- - -class cChannelJump { -private: - skindesignerapi::cViewElement *channelJump; - int channel; - int maxChannels; - int startTime; - int timeout; - cString BuildChannelString(void); -public: - cChannelJump(skindesignerapi::cViewElement *channelJump, int lastValidChannel); - virtual ~cChannelJump(void); - void Set(int key); - bool TimeOut(void); - void Draw(void); - int GetChannel(void) { return channel; }; -}; - +#ifndef __TVGUIDE_CHANNELJUMP_H +#define __TVGUIDE_CHANNELJUMP_H + +#include +#include "definitions.h" + +// --- cChannelJump ------------------------------------------------------------- + +class cChannelJump { +private: + skindesignerapi::cViewElement *channelJump; + int channel; + int maxChannels; + int startTime; + int timeout; + cString BuildChannelString(void); +public: + cChannelJump(skindesignerapi::cViewElement *channelJump, int lastValidChannel); + virtual ~cChannelJump(void); + void Set(int key); + bool TimeOut(void); + void Draw(void); + int GetChannel(void) { return channel; }; +}; + #endif //__TVGUIDE_CHANNELJUMP_H \ No newline at end of file diff --git a/definitions.h b/definitions.h index d2c8119..32a5c45 100644 --- a/definitions.h +++ b/definitions.h @@ -1,546 +1,546 @@ -#ifndef __DEFINITIONS_H -#define __DEFINITIONS_H - -/****************************************************************** -* Menus -*******************************************************************/ -enum class eViews { - rootView = 0, - detailView, - recMenu, - recMenu2, - recMenu3, - count -}; - -/****************************************************************** -* Viewelements -*******************************************************************/ -enum class eViewElementsRoot { - backgroundHor = 0, - backgroundVer, - headerHor, - headerVer, - footerHor, - footerVer, - timeHor, - timeVer, - dateTimelineHor, - dateTimelineVer, - timeIndicatorHor, - timeIndicatorVer, - channelJump, - count -}; - -enum class eViewElementsDetail { - background = 0, - header, - footer, - time, - count -}; - -enum class eViewElementsRecMenu { - background = 0, - scrollbar, - count -}; - -/****************************************************************** -* Viewgrids -*******************************************************************/ -enum class eViewGridsRoot { - channelsHor = 0, - channelsVer, - schedulesHor, - schedulesVer, - channelGroupsHor, - channelGroupsVer, - timelineHor, - timelineVer, - count -}; - -enum class eViewGridsRecMenu { - menu = 0, - count -}; - -/****************************************************************** -* Tokens Rootview Viewelements -*******************************************************************/ -enum class eHeaderST { - title = 0, - shorttext, - description, - start, - stop, - day, - date, - durationminutes, - channelname, - channelid, - posterpath, - count -}; - -enum class eHeaderIT { - isdummy = 0, - daynumeric, - month, - year, - running, - elapsed, - duration, - durationhours, - channelnumber, - channellogoexists, - hasposter, - posterwidth, - posterheight, - count -}; - -enum class eFooterIT { - red1 = 0, red2, red3, red4, - green1, green2, green3, green4, - yellow1, yellow2, yellow3, yellow4, - blue1, blue2, blue3, blue4, - count -}; - -enum class eFooterST { - red = 0, - green, - yellow, - blue, - count -}; - -enum class eTimeST { - time = 0, - monthname, - monthnameshort, - month, - dayleadingzero, - dayname, - daynameshort, - count -}; - -enum class eTimeIT { - sec = 0, - min, - hour, - hmins, - year, - day, - count -}; - -enum class eDateTimeST { - weekday = 0, - date, - count -}; - -enum class eTimeIndicatorIT { - percenttotal = 0, - count -}; - -enum class eChannelJumpST { - channel = 0, - count -}; - -/****************************************************************** -* Tokens Rootview Grids -*******************************************************************/ -enum class eChannelGridST { - name = 0, - channelid, - count -}; - -enum class eChannelGridIT { - number = 0, - channellogoexists, - count -}; - -enum class eSchedulesGridST { - title = 0, - shorttext, - start, - stop, - count -}; - -enum class eSchedulesGridIT { - color = 0, - dummy, - timer, - switchtimer, - count -}; - -enum class eTimelineGridST { - timestring = 0, - count -}; - -enum class eTimelineGridIT { - fullhour = 0, - count -}; - -enum class eChannelgroupsGridST { - group = 0, - count -}; - -enum class eChannelgroupsGridIT { - color = 0, - count -}; - -/****************************************************************** -* Tokens Detailview ViewElements -*******************************************************************/ -enum class eScrollbarIT { - height = 0, - offset, - count -}; - -enum class eScraperHeaderST { - posterpath = 0, - bannerpath, - count -}; - -enum class eScraperHeaderIT { - ismovie = 0, - isseries, - posteravailable, - posterwidth, - posterheight, - banneravailable, - bannerwidth, - bannerheight, - count -}; - -enum class eDetailedHeaderST { - title = eScraperHeaderST::count, - shorttext, - start, - stop, - day, - date, - durationminutes, - vps, - channelname, - channelid, - epgpicpath, - count -}; - -enum class eDetailedHeaderIT { - daynumeric = eScraperHeaderIT::count, - month, - year, - running, - elapsed, - duration, - durationhours, - channelnumber, - channellogoexists, - epgpicavailable, - count -}; - -enum class eTabsIT { - count = 0, -}; - -enum class eTabsST { - currenttab = 0, - prevtab, - nexttab, - count -}; - -enum class eTabsLT { - title = 0, - current, - count -}; - -enum class eScraperST { - movietitle = 0, - movieoriginalTitle, - movietagline, - movieoverview, - moviegenres, - moviehomepage, - moviereleasedate, - moviepopularity, - movievoteaverage, - posterpath, - fanartpath, - moviecollectionName, - collectionposterpath, - collectionfanartpath, - seriesname, - seriesoverview, - seriesfirstaired, - seriesnetwork, - seriesgenre, - seriesrating, - seriesstatus, - episodetitle, - episodefirstaired, - episodegueststars, - episodeoverview, - episoderating, - episodeimagepath, - seasonposterpath, - seriesposter1path, - seriesposter2path, - seriesposter3path, - seriesfanart1path, - seriesfanart2path, - seriesfanart3path, - seriesbanner1path, - seriesbanner2path, - seriesbanner3path, - count -}; - -enum class eScraperIT { - ismovie = 0, - moviebudget, - movierevenue, - movieadult, - movieruntime, - isseries, - posterwidth, - posterheight, - fanartwidth, - fanartheight, - movieiscollection, - collectionposterwidth, - collectionposterheight, - collectionfanartwidth, - collectionfanartheight, - epgpicavailable, - episodenumber, - episodeseason, - episodeimagewidth, - episodeimageheight, - seasonposterwidth, - seasonposterheight, - seriesposter1width, - seriesposter1height, - seriesposter2width, - seriesposter2height, - seriesposter3width, - seriesposter3height, - seriesfanart1width, - seriesfanart1height, - seriesfanart2width, - seriesfanart2height, - seriesfanart3width, - seriesfanart3height, - seriesbanner1width, - seriesbanner1height, - seriesbanner2width, - seriesbanner2height, - seriesbanner3width, - seriesbanner3height, - count -}; - -enum class eScraperLT { - //actors - name = 0, - role, - thumb, - thumbwidth, - thumbheight, - count -}; - -enum class eDetailedEpgST { - title = eScraperST::count, - shorttext, - description, - start, - stop, - day, - date, - durationminutes, - vps, - channelname, - channelid, - epgpic1path, - epgpic2path, - epgpic3path, - count -}; - -enum class eDetailedEpgIT { - daynumeric = eScraperIT::count, - month, - year, - running, - elapsed, - duration, - durationhours, - channelnumber, - channellogoexists, - hasreruns, - epgpic1avaialble, - epgpic2avaialble, - epgpic3avaialble, - count -}; - -enum class eRerunsLT { - title = 0, - shorttext, - date, - day, - start, - stop, - channelname, - channelnumber, - channelid, - channellogoexists, - count -}; - -/****************************************************************** -* Tokens RecMenu ViewElements -*******************************************************************/ -enum class eBackgroundRecMenuIT { - menuwidth = 0, - menuheight, - hasscrollbar, - count -}; - -enum class eScrollbarRecMenuIT { - menuwidth = 0, - posy, - totalheight, - height, - offset, - count -}; - -enum class eRecMenuIT { - info = 0, - lines, - button, - buttonyesno, - yes, - intselector, - value, - boolselector, - stringselector, - textinput, - editmode, - timeselector, - dayselector, - channelselector, - channelnumber, - channellogoexisis, - weekdayselector, - dayselected, - day0set, - day1set, - day2set, - day3set, - day4set, - day5set, - day6set, - directoryselector, - timerconflictheader, - overlapstartpercent, - overlapwidthpercent, - timerconflict, - infoactive, - deleteactive, - editactive, - searchactive, - timerstartpercent, - timerwidthpercent, - event, - hastimer, - recording, - recduration, - searchtimer, - timeractive, - activetimers, - recordingsdone, - timelineheader, - timerset, - channeltransponder, - timelinetimer, - timerstart, - timerwidth, - favorite, - count -}; - -enum class eRecMenuST { - line1 = 0, - line2, - line3, - line4, - value, - buttontext, - textyes, - textno, - text, - channelname, - channelid, - transponder, - day0abbr, - day1abbr, - day2abbr, - day3abbr, - day4abbr, - day5abbr, - day6abbr, - folder, - conflictstart, - conflictstop, - overlapstart, - overlapstop, - timertitle, - starttime, - stoptime, - date, - weekday, - title, - shorttext, - recname, - recstarttime, - recdate, - searchstring, - timerstart, - timerstop, - eventtitle, - eventshorttext, - eventstart, - eventstop, - favdesc, - count -}; - +#ifndef __DEFINITIONS_H +#define __DEFINITIONS_H + +/****************************************************************** +* Menus +*******************************************************************/ +enum class eViews { + rootView = 0, + detailView, + recMenu, + recMenu2, + recMenu3, + count +}; + +/****************************************************************** +* Viewelements +*******************************************************************/ +enum class eViewElementsRoot { + backgroundHor = 0, + backgroundVer, + headerHor, + headerVer, + footerHor, + footerVer, + timeHor, + timeVer, + dateTimelineHor, + dateTimelineVer, + timeIndicatorHor, + timeIndicatorVer, + channelJump, + count +}; + +enum class eViewElementsDetail { + background = 0, + header, + footer, + time, + count +}; + +enum class eViewElementsRecMenu { + background = 0, + scrollbar, + count +}; + +/****************************************************************** +* Viewgrids +*******************************************************************/ +enum class eViewGridsRoot { + channelsHor = 0, + channelsVer, + schedulesHor, + schedulesVer, + channelGroupsHor, + channelGroupsVer, + timelineHor, + timelineVer, + count +}; + +enum class eViewGridsRecMenu { + menu = 0, + count +}; + +/****************************************************************** +* Tokens Rootview Viewelements +*******************************************************************/ +enum class eHeaderST { + title = 0, + shorttext, + description, + start, + stop, + day, + date, + durationminutes, + channelname, + channelid, + posterpath, + count +}; + +enum class eHeaderIT { + isdummy = 0, + daynumeric, + month, + year, + running, + elapsed, + duration, + durationhours, + channelnumber, + channellogoexists, + hasposter, + posterwidth, + posterheight, + count +}; + +enum class eFooterIT { + red1 = 0, red2, red3, red4, + green1, green2, green3, green4, + yellow1, yellow2, yellow3, yellow4, + blue1, blue2, blue3, blue4, + count +}; + +enum class eFooterST { + red = 0, + green, + yellow, + blue, + count +}; + +enum class eTimeST { + time = 0, + monthname, + monthnameshort, + month, + dayleadingzero, + dayname, + daynameshort, + count +}; + +enum class eTimeIT { + sec = 0, + min, + hour, + hmins, + year, + day, + count +}; + +enum class eDateTimeST { + weekday = 0, + date, + count +}; + +enum class eTimeIndicatorIT { + percenttotal = 0, + count +}; + +enum class eChannelJumpST { + channel = 0, + count +}; + +/****************************************************************** +* Tokens Rootview Grids +*******************************************************************/ +enum class eChannelGridST { + name = 0, + channelid, + count +}; + +enum class eChannelGridIT { + number = 0, + channellogoexists, + count +}; + +enum class eSchedulesGridST { + title = 0, + shorttext, + start, + stop, + count +}; + +enum class eSchedulesGridIT { + color = 0, + dummy, + timer, + switchtimer, + count +}; + +enum class eTimelineGridST { + timestring = 0, + count +}; + +enum class eTimelineGridIT { + fullhour = 0, + count +}; + +enum class eChannelgroupsGridST { + group = 0, + count +}; + +enum class eChannelgroupsGridIT { + color = 0, + count +}; + +/****************************************************************** +* Tokens Detailview ViewElements +*******************************************************************/ +enum class eScrollbarIT { + height = 0, + offset, + count +}; + +enum class eScraperHeaderST { + posterpath = 0, + bannerpath, + count +}; + +enum class eScraperHeaderIT { + ismovie = 0, + isseries, + posteravailable, + posterwidth, + posterheight, + banneravailable, + bannerwidth, + bannerheight, + count +}; + +enum class eDetailedHeaderST { + title = eScraperHeaderST::count, + shorttext, + start, + stop, + day, + date, + durationminutes, + vps, + channelname, + channelid, + epgpicpath, + count +}; + +enum class eDetailedHeaderIT { + daynumeric = eScraperHeaderIT::count, + month, + year, + running, + elapsed, + duration, + durationhours, + channelnumber, + channellogoexists, + epgpicavailable, + count +}; + +enum class eTabsIT { + count = 0, +}; + +enum class eTabsST { + currenttab = 0, + prevtab, + nexttab, + count +}; + +enum class eTabsLT { + title = 0, + current, + count +}; + +enum class eScraperST { + movietitle = 0, + movieoriginalTitle, + movietagline, + movieoverview, + moviegenres, + moviehomepage, + moviereleasedate, + moviepopularity, + movievoteaverage, + posterpath, + fanartpath, + moviecollectionName, + collectionposterpath, + collectionfanartpath, + seriesname, + seriesoverview, + seriesfirstaired, + seriesnetwork, + seriesgenre, + seriesrating, + seriesstatus, + episodetitle, + episodefirstaired, + episodegueststars, + episodeoverview, + episoderating, + episodeimagepath, + seasonposterpath, + seriesposter1path, + seriesposter2path, + seriesposter3path, + seriesfanart1path, + seriesfanart2path, + seriesfanart3path, + seriesbanner1path, + seriesbanner2path, + seriesbanner3path, + count +}; + +enum class eScraperIT { + ismovie = 0, + moviebudget, + movierevenue, + movieadult, + movieruntime, + isseries, + posterwidth, + posterheight, + fanartwidth, + fanartheight, + movieiscollection, + collectionposterwidth, + collectionposterheight, + collectionfanartwidth, + collectionfanartheight, + epgpicavailable, + episodenumber, + episodeseason, + episodeimagewidth, + episodeimageheight, + seasonposterwidth, + seasonposterheight, + seriesposter1width, + seriesposter1height, + seriesposter2width, + seriesposter2height, + seriesposter3width, + seriesposter3height, + seriesfanart1width, + seriesfanart1height, + seriesfanart2width, + seriesfanart2height, + seriesfanart3width, + seriesfanart3height, + seriesbanner1width, + seriesbanner1height, + seriesbanner2width, + seriesbanner2height, + seriesbanner3width, + seriesbanner3height, + count +}; + +enum class eScraperLT { + //actors + name = 0, + role, + thumb, + thumbwidth, + thumbheight, + count +}; + +enum class eDetailedEpgST { + title = eScraperST::count, + shorttext, + description, + start, + stop, + day, + date, + durationminutes, + vps, + channelname, + channelid, + epgpic1path, + epgpic2path, + epgpic3path, + count +}; + +enum class eDetailedEpgIT { + daynumeric = eScraperIT::count, + month, + year, + running, + elapsed, + duration, + durationhours, + channelnumber, + channellogoexists, + hasreruns, + epgpic1avaialble, + epgpic2avaialble, + epgpic3avaialble, + count +}; + +enum class eRerunsLT { + title = 0, + shorttext, + date, + day, + start, + stop, + channelname, + channelnumber, + channelid, + channellogoexists, + count +}; + +/****************************************************************** +* Tokens RecMenu ViewElements +*******************************************************************/ +enum class eBackgroundRecMenuIT { + menuwidth = 0, + menuheight, + hasscrollbar, + count +}; + +enum class eScrollbarRecMenuIT { + menuwidth = 0, + posy, + totalheight, + height, + offset, + count +}; + +enum class eRecMenuIT { + info = 0, + lines, + button, + buttonyesno, + yes, + intselector, + value, + boolselector, + stringselector, + textinput, + editmode, + timeselector, + dayselector, + channelselector, + channelnumber, + channellogoexisis, + weekdayselector, + dayselected, + day0set, + day1set, + day2set, + day3set, + day4set, + day5set, + day6set, + directoryselector, + timerconflictheader, + overlapstartpercent, + overlapwidthpercent, + timerconflict, + infoactive, + deleteactive, + editactive, + searchactive, + timerstartpercent, + timerwidthpercent, + event, + hastimer, + recording, + recduration, + searchtimer, + timeractive, + activetimers, + recordingsdone, + timelineheader, + timerset, + channeltransponder, + timelinetimer, + timerstart, + timerwidth, + favorite, + count +}; + +enum class eRecMenuST { + line1 = 0, + line2, + line3, + line4, + value, + buttontext, + textyes, + textno, + text, + channelname, + channelid, + transponder, + day0abbr, + day1abbr, + day2abbr, + day3abbr, + day4abbr, + day5abbr, + day6abbr, + folder, + conflictstart, + conflictstop, + overlapstart, + overlapstop, + timertitle, + starttime, + stoptime, + date, + weekday, + title, + shorttext, + recname, + recstarttime, + recdate, + searchstring, + timerstart, + timerstop, + eventtitle, + eventshorttext, + eventstart, + eventstop, + favdesc, + count +}; + #endif //__DEFINITIONS_H \ No newline at end of file diff --git a/detailview.c b/detailview.c index 24c2e79..1dae0b9 100644 --- a/detailview.c +++ b/detailview.c @@ -1,780 +1,794 @@ -#include "helpers.h" -#include "tvguidengosd.h" -#include "detailview.h" - -cDetailView::cDetailView(skindesignerapi::cOsdView *detailView, const cEvent *event) { - init = true; - lastSecond = -1; - this->detailView = detailView; - this->event = event; - back = detailView->GetViewElement((int)eViewElementsDetail::background); - header = detailView->GetViewElement((int)eViewElementsDetail::header); - footer = detailView->GetViewElement((int)eViewElementsDetail::footer); - watch = detailView->GetViewElement((int)eViewElementsDetail::time); - tabs = detailView->GetViewTabs(); - movie = NULL; - series = NULL; -} - -cDetailView::~cDetailView() { - delete back; - delete header; - delete footer; - delete watch; - delete tabs; - delete detailView; - delete movie; - delete series; -} - -void cDetailView::Draw(void) { - if (!event) { - return; - } - if (init) { - DrawBackground(); - DrawHeader(); - DrawFooter(); - Flush(); - SetTabTokens(); - tabs->Init(); - init = false; - } - tabs->Display(); -} - -void cDetailView::Left(void) { - tabs->Left(); - tabs->Display(); -} - -void cDetailView::Right(void) { - tabs->Right(); - tabs->Display(); -} - -void cDetailView::Up(void) { - tabs->Up(); - tabs->Display(); -} - -void cDetailView::Down(void) { - tabs->Down(); - tabs->Display(); -} - -void cDetailView::DefineTokens(eViewElementsDetail ve, skindesignerapi::cTokenContainer *tk) { - switch (ve) { - case eViewElementsDetail::header: - tk->DefineIntToken("{ismovie}", (int)eScraperHeaderIT::ismovie); - tk->DefineIntToken("{isseries}", (int)eScraperHeaderIT::isseries); - tk->DefineIntToken("{posteravailable}", (int)eScraperHeaderIT::posteravailable); - tk->DefineIntToken("{posterwidth}", (int)eScraperHeaderIT::posterwidth); - tk->DefineIntToken("{posterheight}", (int)eScraperHeaderIT::posterheight); - tk->DefineIntToken("{banneravailable}", (int)eScraperHeaderIT::banneravailable); - tk->DefineIntToken("{bannerwidth}", (int)eScraperHeaderIT::bannerwidth); - tk->DefineIntToken("{bannerheight}", (int)eScraperHeaderIT::bannerheight); - tk->DefineIntToken("{daynumeric}", (int)eDetailedHeaderIT::daynumeric); - tk->DefineIntToken("{month}", (int)eDetailedHeaderIT::month); - tk->DefineIntToken("{year}", (int)eDetailedHeaderIT::year); - tk->DefineIntToken("{running}", (int)eDetailedHeaderIT::running); - tk->DefineIntToken("{elapsed}", (int)eDetailedHeaderIT::elapsed); - tk->DefineIntToken("{duration}", (int)eDetailedHeaderIT::duration); - tk->DefineIntToken("{durationhours}", (int)eDetailedHeaderIT::durationhours); - tk->DefineIntToken("{channelnumber}", (int)eDetailedHeaderIT::channelnumber); - tk->DefineIntToken("{channellogoexists}", (int)eDetailedHeaderIT::channellogoexists); - tk->DefineIntToken("{epgpicavailable}", (int)eDetailedHeaderIT::epgpicavailable); - tk->DefineStringToken("{posterpath}", (int)eScraperHeaderST::posterpath); - tk->DefineStringToken("{bannerpath}", (int)eScraperHeaderST::bannerpath); - tk->DefineStringToken("{title}", (int)eDetailedHeaderST::title); - tk->DefineStringToken("{shorttext}", (int)eDetailedHeaderST::shorttext); - tk->DefineStringToken("{start}", (int)eDetailedHeaderST::start); - tk->DefineStringToken("{stop}", (int)eDetailedHeaderST::stop); - tk->DefineStringToken("{day}", (int)eDetailedHeaderST::day); - tk->DefineStringToken("{date}", (int)eDetailedHeaderST::date); - tk->DefineStringToken("{durationminutes}", (int)eDetailedHeaderST::durationminutes); - tk->DefineStringToken("{vps}", (int)eDetailedHeaderST::vps); - tk->DefineStringToken("{channelname}", (int)eDetailedHeaderST::channelname); - tk->DefineStringToken("{channelid}", (int)eDetailedHeaderST::channelid); - tk->DefineStringToken("{epgpicpath}", (int)eDetailedHeaderST::epgpicpath); - break; - case eViewElementsDetail::footer: - tk->DefineIntToken("{red1}", (int)eFooterIT::red1); - tk->DefineIntToken("{red2}", (int)eFooterIT::red2); - tk->DefineIntToken("{red3}", (int)eFooterIT::red3); - tk->DefineIntToken("{red4}", (int)eFooterIT::red4); - tk->DefineIntToken("{green1}", (int)eFooterIT::green1); - tk->DefineIntToken("{green2}", (int)eFooterIT::green2); - tk->DefineIntToken("{green3}", (int)eFooterIT::green3); - tk->DefineIntToken("{green4}", (int)eFooterIT::green4); - tk->DefineIntToken("{yellow1}", (int)eFooterIT::yellow1); - tk->DefineIntToken("{yellow2}", (int)eFooterIT::yellow2); - tk->DefineIntToken("{yellow3}", (int)eFooterIT::yellow3); - tk->DefineIntToken("{yellow4}", (int)eFooterIT::yellow4); - tk->DefineIntToken("{blue1}", (int)eFooterIT::blue1); - tk->DefineIntToken("{blue2}", (int)eFooterIT::blue2); - tk->DefineIntToken("{blue3}", (int)eFooterIT::blue3); - tk->DefineIntToken("{blue4}", (int)eFooterIT::blue4); - tk->DefineStringToken("{red}", (int)eFooterST::red); - tk->DefineStringToken("{green}", (int)eFooterST::green); - tk->DefineStringToken("{yellow}", (int)eFooterST::yellow); - tk->DefineStringToken("{blue}", (int)eFooterST::blue); - break; - default: - break; - } -} - -void cDetailView::DefineTabTokens(skindesignerapi::cTokenContainer *tk) { - tk->DefineStringToken("{title}", (int)eDetailedEpgST::title); - tk->DefineStringToken("{shorttext}", (int)eDetailedEpgST::shorttext); - tk->DefineStringToken("{description}", (int)eDetailedEpgST::description); - tk->DefineStringToken("{start}", (int)eDetailedEpgST::start); - tk->DefineStringToken("{stop}", (int)eDetailedEpgST::stop); - tk->DefineStringToken("{day}", (int)eDetailedEpgST::day); - tk->DefineStringToken("{date}", (int)eDetailedEpgST::date); - tk->DefineStringToken("{durationminutes}", (int)eDetailedEpgST::durationminutes); - tk->DefineStringToken("{vps}", (int)eDetailedEpgST::vps); - tk->DefineStringToken("{channelname}", (int)eDetailedEpgST::channelname); - tk->DefineStringToken("{channelid}", (int)eDetailedEpgST::channelid); - tk->DefineStringToken("{epgpic1path}", (int)eDetailedEpgST::epgpic1path); - tk->DefineStringToken("{epgpic2path}", (int)eDetailedEpgST::epgpic2path); - tk->DefineStringToken("{epgpic3path}", (int)eDetailedEpgST::epgpic3path); - tk->DefineStringToken("{movietitle}", (int)eScraperST::movietitle); - tk->DefineStringToken("{movieoriginalTitle}", (int)eScraperST::movieoriginalTitle); - tk->DefineStringToken("{movietagline}", (int)eScraperST::movietagline); - tk->DefineStringToken("{movieoverview}", (int)eScraperST::movieoverview); - tk->DefineStringToken("{moviegenres}", (int)eScraperST::moviegenres); - tk->DefineStringToken("{moviehomepage}", (int)eScraperST::moviehomepage); - tk->DefineStringToken("{moviereleasedate}", (int)eScraperST::moviereleasedate); - tk->DefineStringToken("{moviepopularity}", (int)eScraperST::moviepopularity); - tk->DefineStringToken("{movievoteaverage}", (int)eScraperST::movievoteaverage); - tk->DefineStringToken("{posterpath}", (int)eScraperST::posterpath); - tk->DefineStringToken("{fanartpath}", (int)eScraperST::fanartpath); - tk->DefineStringToken("{moviecollectionName}", (int)eScraperST::moviecollectionName); - tk->DefineStringToken("{collectionposterpath}", (int)eScraperST::collectionposterpath); - tk->DefineStringToken("{collectionfanartpath}", (int)eScraperST::collectionfanartpath); - tk->DefineStringToken("{seriesname}", (int)eScraperST::seriesname); - tk->DefineStringToken("{seriesoverview}", (int)eScraperST::seriesoverview); - tk->DefineStringToken("{seriesfirstaired}", (int)eScraperST::seriesfirstaired); - tk->DefineStringToken("{seriesnetwork}", (int)eScraperST::seriesnetwork); - tk->DefineStringToken("{seriesgenre}", (int)eScraperST::seriesgenre); - tk->DefineStringToken("{seriesrating}", (int)eScraperST::seriesrating); - tk->DefineStringToken("{seriesstatus}", (int)eScraperST::seriesstatus); - tk->DefineStringToken("{episodetitle}", (int)eScraperST::episodetitle); - tk->DefineStringToken("{episodefirstaired}", (int)eScraperST::episodefirstaired); - tk->DefineStringToken("{episodegueststars}", (int)eScraperST::episodegueststars); - tk->DefineStringToken("{episodeoverview}", (int)eScraperST::episodeoverview); - tk->DefineStringToken("{episoderating}", (int)eScraperST::episoderating); - tk->DefineStringToken("{episodeimagepath}", (int)eScraperST::episodeimagepath); - tk->DefineStringToken("{seasonposterpath}", (int)eScraperST::seasonposterpath); - tk->DefineStringToken("{seriesposter1path}", (int)eScraperST::seriesposter1path); - tk->DefineStringToken("{seriesposter2path}", (int)eScraperST::seriesposter2path); - tk->DefineStringToken("{seriesposter3path}", (int)eScraperST::seriesposter3path); - tk->DefineStringToken("{seriesfanart1path}", (int)eScraperST::seriesfanart1path); - tk->DefineStringToken("{seriesfanart2path}", (int)eScraperST::seriesfanart2path); - tk->DefineStringToken("{seriesfanart3path}", (int)eScraperST::seriesfanart3path); - tk->DefineStringToken("{seriesbanner1path}", (int)eScraperST::seriesbanner1path); - tk->DefineStringToken("{seriesbanner2path}", (int)eScraperST::seriesbanner2path); - tk->DefineStringToken("{seriesbanner3path}", (int)eScraperST::seriesbanner3path); - tk->DefineIntToken("{daynumeric}", (int)eDetailedEpgIT::daynumeric); - tk->DefineIntToken("{month}", (int)eDetailedEpgIT::month); - tk->DefineIntToken("{year}", (int)eDetailedEpgIT::year); - tk->DefineIntToken("{running}", (int)eDetailedEpgIT::running); - tk->DefineIntToken("{elapsed}", (int)eDetailedEpgIT::elapsed); - tk->DefineIntToken("{duration}", (int)eDetailedEpgIT::duration); - tk->DefineIntToken("{durationhours}", (int)eDetailedEpgIT::durationhours); - tk->DefineIntToken("{channelnumber}", (int)eDetailedEpgIT::channelnumber); - tk->DefineIntToken("{channellogoexists}", (int)eDetailedEpgIT::channellogoexists); - tk->DefineIntToken("{hasreruns}", (int)eDetailedEpgIT::hasreruns); - tk->DefineIntToken("{epgpic1avaialble}", (int)eDetailedEpgIT::epgpic1avaialble); - tk->DefineIntToken("{epgpic2avaialble}", (int)eDetailedEpgIT::epgpic2avaialble); - tk->DefineIntToken("{epgpic3avaialble}", (int)eDetailedEpgIT::epgpic3avaialble); - tk->DefineIntToken("{ismovie}", (int)eScraperIT::ismovie); - tk->DefineIntToken("{moviebudget}", (int)eScraperIT::moviebudget); - tk->DefineIntToken("{movierevenue}", (int)eScraperIT::movierevenue); - tk->DefineIntToken("{movieadult}", (int)eScraperIT::movieadult); - tk->DefineIntToken("{movieruntime}", (int)eScraperIT::movieruntime); - tk->DefineIntToken("{isseries}", (int)eScraperIT::isseries); - tk->DefineIntToken("{posterwidth}", (int)eScraperIT::posterwidth); - tk->DefineIntToken("{posterheight}", (int)eScraperIT::posterheight); - tk->DefineIntToken("{fanartwidth}", (int)eScraperIT::fanartwidth); - tk->DefineIntToken("{fanartheight}", (int)eScraperIT::fanartheight); - tk->DefineIntToken("{movieiscollection}", (int)eScraperIT::movieiscollection); - tk->DefineIntToken("{collectionposterwidth}", (int)eScraperIT::collectionposterwidth); - tk->DefineIntToken("{collectionposterheight}", (int)eScraperIT::collectionposterheight); - tk->DefineIntToken("{collectionfanartwidth}", (int)eScraperIT::collectionfanartwidth); - tk->DefineIntToken("{collectionfanartheight}", (int)eScraperIT::collectionfanartheight); - tk->DefineIntToken("{epgpicavailable}", (int)eScraperIT::epgpicavailable); - tk->DefineIntToken("{episodenumber}", (int)eScraperIT::episodenumber); - tk->DefineIntToken("{episodeseason}", (int)eScraperIT::episodeseason); - tk->DefineIntToken("{episodeimagewidth}", (int)eScraperIT::episodeimagewidth); - tk->DefineIntToken("{episodeimageheight}", (int)eScraperIT::episodeimageheight); - tk->DefineIntToken("{seasonposterwidth}", (int)eScraperIT::seasonposterwidth); - tk->DefineIntToken("{seasonposterheight}", (int)eScraperIT::seasonposterheight); - tk->DefineIntToken("{seriesposter1width}", (int)eScraperIT::seriesposter1width); - tk->DefineIntToken("{seriesposter1height}", (int)eScraperIT::seriesposter1height); - tk->DefineIntToken("{seriesposter2width}", (int)eScraperIT::seriesposter2width); - tk->DefineIntToken("{seriesposter2height}", (int)eScraperIT::seriesposter2height); - tk->DefineIntToken("{seriesposter3width}", (int)eScraperIT::seriesposter3width); - tk->DefineIntToken("{seriesposter3height}", (int)eScraperIT::seriesposter3height); - tk->DefineIntToken("{seriesfanart1width}", (int)eScraperIT::seriesfanart1width); - tk->DefineIntToken("{seriesfanart1height}", (int)eScraperIT::seriesfanart1height); - tk->DefineIntToken("{seriesfanart2width}", (int)eScraperIT::seriesfanart2width); - tk->DefineIntToken("{seriesfanart2height}", (int)eScraperIT::seriesfanart2height); - tk->DefineIntToken("{seriesfanart3width}", (int)eScraperIT::seriesfanart3width); - tk->DefineIntToken("{seriesfanart3height}", (int)eScraperIT::seriesfanart3height); - tk->DefineIntToken("{seriesbanner1width}", (int)eScraperIT::seriesbanner1width); - tk->DefineIntToken("{seriesbanner1height}", (int)eScraperIT::seriesbanner1height); - tk->DefineIntToken("{seriesbanner2width}", (int)eScraperIT::seriesbanner2width); - tk->DefineIntToken("{seriesbanner2height}", (int)eScraperIT::seriesbanner2height); - tk->DefineIntToken("{seriesbanner3width}", (int)eScraperIT::seriesbanner3width); - tk->DefineIntToken("{seriesbanner3height}", (int)eScraperIT::seriesbanner3height); - tk->DefineLoopToken("{reruns[title]}", (int)eRerunsLT::title); - tk->DefineLoopToken("{reruns[shorttext]}", (int)eRerunsLT::shorttext); - tk->DefineLoopToken("{reruns[date]}", (int)eRerunsLT::date); - tk->DefineLoopToken("{reruns[day]}", (int)eRerunsLT::day); - tk->DefineLoopToken("{reruns[start]}", (int)eRerunsLT::start); - tk->DefineLoopToken("{reruns[stop]}", (int)eRerunsLT::stop); - tk->DefineLoopToken("{reruns[channelname]}", (int)eRerunsLT::channelname); - tk->DefineLoopToken("{reruns[channelnumber]}", (int)eRerunsLT::channelnumber); - tk->DefineLoopToken("{reruns[channelid]}", (int)eRerunsLT::channelid); - tk->DefineLoopToken("{reruns[channellogoexists]}", (int)eRerunsLT::channellogoexists); - tk->DefineLoopToken("{actors[name]}", (int)eScraperLT::name); - tk->DefineLoopToken("{actors[role]}", (int)eScraperLT::role); - tk->DefineLoopToken("{actors[thumb]}", (int)eScraperLT::thumb); - tk->DefineLoopToken("{actors[thumbwidth]}", (int)eScraperLT::thumbwidth); - tk->DefineLoopToken("{actors[thumbheight]}", (int)eScraperLT::thumbheight); -} -/******************************************************************** -* Private Functions -********************************************************************/ -void cDetailView::DrawBackground(void) { - back->Display(); -} - -void cDetailView::DrawHeader(void) { - if (!event) - return; - header->ClearTokens(); - static cPlugin *pScraper = GetScraperPlugin(); - if (pScraper) { - ScraperGetEventType getType; - getType.event = event; - if (!pScraper->Service("GetEventType", &getType)) { - if (getType.type == tMovie) { - cMovie movie; - movie.movieId = getType.movieId; - pScraper->Service("GetMovie", &movie); - header->AddIntToken((int)eScraperHeaderIT::banneravailable, true); - header->AddIntToken((int)eScraperHeaderIT::isseries, false); - header->AddIntToken((int)eScraperHeaderIT::posteravailable, true); - header->AddIntToken((int)eScraperHeaderIT::banneravailable, false); - header->AddStringToken((int)eScraperHeaderST::posterpath, movie.poster.path.c_str()); - header->AddIntToken((int)eScraperHeaderIT::posterwidth, movie.poster.width); - header->AddIntToken((int)eScraperHeaderIT::posterheight, movie.poster.height); - } else if (getType.type == tSeries) { - cSeries series; - series.seriesId = getType.seriesId; - series.episodeId = getType.episodeId; - pScraper->Service("GetSeries", &series); - header->AddIntToken((int)eScraperHeaderIT::ismovie, false); - header->AddIntToken((int)eScraperHeaderIT::isseries, true); - vector::iterator poster = series.posters.begin(); - if (poster != series.posters.end()) { - header->AddIntToken((int)eScraperHeaderIT::posterwidth, (*poster).width); - header->AddIntToken((int)eScraperHeaderIT::posterheight, (*poster).height); - header->AddStringToken((int)eScraperHeaderST::posterpath, (*poster).path.c_str()); - header->AddIntToken((int)eScraperHeaderIT::posteravailable, true); - } - vector::iterator banner = series.banners.begin(); - if (banner != series.banners.end()) { - header->AddIntToken((int)eScraperHeaderIT::bannerwidth, (*banner).width); - header->AddIntToken((int)eScraperHeaderIT::bannerheight, (*banner).height); - header->AddStringToken((int)eScraperHeaderST::bannerpath, (*banner).path.c_str()); - header->AddIntToken((int)eScraperHeaderIT::banneravailable, true); - } - } - } - } - - header->AddStringToken((int)eDetailedHeaderST::title, event->Title()); - header->AddStringToken((int)eDetailedHeaderST::shorttext, event->ShortText()); - header->AddStringToken((int)eDetailedHeaderST::start, *(event->GetTimeString())); - header->AddStringToken((int)eDetailedHeaderST::stop, *(event->GetEndTimeString())); - - time_t startTime = event->StartTime(); - header->AddStringToken((int)eDetailedHeaderST::day, *WeekDayName(startTime)); - header->AddStringToken((int)eDetailedHeaderST::date, *ShortDateString(startTime)); - struct tm * sStartTime = localtime(&startTime); - header->AddIntToken((int)eDetailedHeaderIT::year, sStartTime->tm_year + 1900); - header->AddIntToken((int)eDetailedHeaderIT::daynumeric, sStartTime->tm_mday); - header->AddIntToken((int)eDetailedHeaderIT::month, sStartTime->tm_mon+1); - - const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); - if (channel) { - header->AddStringToken((int)eDetailedHeaderST::channelname, channel->Name()); - header->AddIntToken((int)eDetailedHeaderIT::channelnumber, channel->Number()); - } else { - header->AddIntToken((int)eDetailedHeaderIT::channelnumber, 0); - } - cString channelID = channel->GetChannelID().ToString(); - header->AddStringToken((int)eDetailedHeaderST::channelid, *channelID); - header->AddIntToken((int)eDetailedHeaderIT::channellogoexists, header->ChannelLogoExists(*channelID)); - - bool isRunning = false; - time_t now = time(NULL); - if ((now >= event->StartTime()) && (now <= event->EndTime())) - isRunning = true; - header->AddIntToken((int)eDetailedHeaderIT::running, isRunning); - if (isRunning) { - header->AddIntToken((int)eDetailedHeaderIT::elapsed, (now - event->StartTime())/60); - } else { - header->AddIntToken((int)eDetailedHeaderIT::elapsed, 0); - } - header->AddIntToken((int)eDetailedHeaderIT::duration, event->Duration() / 60); - header->AddIntToken((int)eDetailedHeaderIT::durationhours, event->Duration() / 3600); - header->AddStringToken((int)eDetailedHeaderST::durationminutes, *cString::sprintf("%.2d", (event->Duration() / 60)%60)); - if (event->Vps()) - header->AddStringToken((int)eDetailedHeaderST::vps, *event->GetVpsString()); - - stringstream epgImageName; - epgImageName << event->EventID(); - string epgImagePath = header->GetEpgImagePath(); - - bool epgPicAvailable = FileExists(epgImagePath, epgImageName.str(), "jpg"); - if (epgPicAvailable) { - header->AddIntToken((int)eDetailedHeaderIT::epgpicavailable, true); - header->AddStringToken((int)eDetailedHeaderST::epgpicpath, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), epgImageName.str().c_str())); - } else { - epgImageName << "_0"; - epgPicAvailable = FileExists(epgImagePath, epgImageName.str(), "jpg"); - if (epgPicAvailable) { - header->AddIntToken((int)eDetailedHeaderIT::epgpicavailable, true); - header->AddStringToken((int)eDetailedHeaderST::epgpicpath, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), epgImageName.str().c_str())); - } - } - - header->Display(); -} - -void cDetailView::DrawFooter(void) { - string textGreen = ""; - string textYellow = ""; - string textRed = tr("Search & Record"); - string textBlue = tr("Switch"); - - int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 }; - - footer->Clear(); - footer->ClearTokens(); - - footer->AddStringToken((int)eFooterST::red, textRed.c_str()); - footer->AddStringToken((int)eFooterST::green, textGreen.c_str()); - footer->AddStringToken((int)eFooterST::yellow, textYellow.c_str()); - footer->AddStringToken((int)eFooterST::blue, textBlue.c_str()); - - for (int button = 0; button < 4; button++) { - bool isRed = false; - bool isGreen = false; - bool isYellow = false; - bool isBlue = false; - switch (colorKeys[button]) { - case 0: - isRed = true; - break; - case 1: - isGreen = true; - break; - case 2: - isYellow = true; - break; - case 3: - isBlue = true; - break; - default: - break; - } - footer->AddIntToken(0 + button, isRed); - footer->AddIntToken(4 + button, isGreen); - footer->AddIntToken(8 + button, isYellow); - footer->AddIntToken(12 + button, isBlue); - } - - footer->Display(); -} - -bool cDetailView::DrawTime(void) { - time_t t = time(0); // get time now - struct tm * now = localtime(&t); - int sec = now->tm_sec; - if (sec == lastSecond) - return false; - - int min = now->tm_min; - int hour = now->tm_hour; - int hourMinutes = hour%12 * 5 + min / 12; - - char monthname[20]; - char monthshort[10]; - strftime(monthshort, sizeof(monthshort), "%b", now); - strftime(monthname, sizeof(monthname), "%B", now); - - watch->Clear(); - watch->ClearTokens(); - watch->AddIntToken((int)eTimeIT::sec, sec); - watch->AddIntToken((int)eTimeIT::min, min); - watch->AddIntToken((int)eTimeIT::hour, hour); - watch->AddIntToken((int)eTimeIT::hmins, hourMinutes); - watch->AddIntToken((int)eTimeIT::year, now->tm_year + 1900); - watch->AddIntToken((int)eTimeIT::day, now->tm_mday); - watch->AddStringToken((int)eTimeST::time, *TimeString(t)); - watch->AddStringToken((int)eTimeST::monthname, monthname); - watch->AddStringToken((int)eTimeST::monthnameshort, monthshort); - watch->AddStringToken((int)eTimeST::month, *cString::sprintf("%02d", now->tm_mon + 1)); - watch->AddStringToken((int)eTimeST::dayleadingzero, *cString::sprintf("%02d", now->tm_mday)); - watch->AddStringToken((int)eTimeST::dayname, *WeekDayNameFull(now->tm_wday)); - watch->AddStringToken((int)eTimeST::daynameshort, *WeekDayName(now->tm_wday)); - watch->Display(); - - lastSecond = sec; - return true; -} - -void cDetailView::SetTabTokens(void) { - tabs->ClearTokens(); - tabs->AddStringToken((int)eDetailedEpgST::title, event->Title()); - tabs->AddStringToken((int)eDetailedEpgST::shorttext, event->ShortText()); - tabs->AddStringToken((int)eDetailedEpgST::description, event->Description()); - tabs->AddStringToken((int)eDetailedEpgST::start, *(event->GetTimeString())); - tabs->AddStringToken((int)eDetailedEpgST::stop, *(event->GetEndTimeString())); - time_t startTime = event->StartTime(); - tabs->AddStringToken((int)eDetailedEpgST::day, *WeekDayName(startTime)); - tabs->AddStringToken((int)eDetailedEpgST::date, *ShortDateString(startTime)); - struct tm * sStartTime = localtime(&startTime); - tabs->AddIntToken((int)eDetailedEpgIT::year, sStartTime->tm_year + 1900); - tabs->AddIntToken((int)eDetailedEpgIT::daynumeric, sStartTime->tm_mday); - tabs->AddIntToken((int)eDetailedEpgIT::month, sStartTime->tm_mon+1); - - cString channelID = event->ChannelID().ToString(); - tabs->AddStringToken((int)eDetailedEpgST::channelid, *channelID); - tabs->AddIntToken((int)eDetailedEpgIT::channellogoexists, tabs->ChannelLogoExists(*channelID)); - - bool isRunning = false; - time_t now = time(NULL); - if ((now >= event->StartTime()) && (now <= event->EndTime())) - isRunning = true; - tabs->AddIntToken((int)eDetailedEpgIT::running, isRunning); - if (isRunning) { - tabs->AddIntToken((int)eDetailedEpgIT::elapsed, (now - event->StartTime())/60); - } else { - tabs->AddIntToken((int)eDetailedEpgIT::elapsed, 0); - } - tabs->AddIntToken((int)eDetailedEpgIT::duration, event->Duration() / 60); - tabs->AddIntToken((int)eDetailedEpgIT::durationhours, event->Duration() / 3600); - tabs->AddStringToken((int)eDetailedEpgST::durationminutes, *cString::sprintf("%.2d", (event->Duration() / 60)%60)); - if (event->Vps()) - tabs->AddStringToken((int)eDetailedEpgST::vps, *event->GetVpsString()); - else - tabs->AddStringToken((int)eDetailedEpgST::vps, ""); - - - bool scrapInfoAvailable = LoadScrapInfo(event); - int numActors = NumActors(); - - cList *reruns = LoadReruns(); - int numReruns = NumReruns(reruns); - - vector loopInfo; - loopInfo.push_back(numReruns); - loopInfo.push_back(numActors); - tabs->SetLoop(loopInfo); - - if (numReruns > 0) { - tabs->AddIntToken((int)eDetailedEpgIT::hasreruns, 1); - SetReruns(reruns); - } - if (scrapInfoAvailable) { - SetScraperTokens(); - } - - SetEpgPictures(event->EventID()); -} - -cList *cDetailView::LoadReruns(void) { - cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch"); - if (!epgSearchPlugin) - return NULL; - - if (isempty(event->Title())) - return NULL; - - Epgsearch_searchresults_v1_0 data; - data.query = (char*)event->Title(); - data.mode = 0; - data.channelNr = 0; - data.useTitle = true; - data.useSubTitle = true; - data.useDescription = false; - - cList *result = NULL; - if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) - result = data.pResultList; - return result; -} - -int cDetailView::NumReruns(cList *reruns) { - if (!reruns || reruns->Count() < 2) - return 0; - - int maxNumReruns = config.rerunAmount; - int rerunDistance = config.rerunDistance * 3600; - int rerunMaxChannel = config.rerunMaxChannel; - - int i = 0; - for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = reruns->First(); r && i < maxNumReruns; r = reruns->Next(r)) { - time_t eventStart = event->StartTime(); - time_t rerunStart = r->event->StartTime(); - cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); - //check for identical event - if ((event->ChannelID() == r->event->ChannelID()) && (eventStart == rerunStart)) - continue; - //check for timely distance - if (rerunDistance > 0) - if (rerunStart - eventStart < rerunDistance) - continue; - //check for maxchannel - if (rerunMaxChannel > 0) - if (channel && channel->Number() > rerunMaxChannel) - continue; - i++; - } - return i; -} - -void cDetailView::SetReruns(cList *reruns) { - if (!reruns || reruns->Count() < 2) - return; - int rerunsIndex = tabs->GetLoopIndex("reruns"); - - int maxNumReruns = config.rerunAmount; - int rerunDistance = config.rerunDistance * 3600; - int rerunMaxChannel = config.rerunMaxChannel; - - int i = 0; - for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = reruns->First(); r && i < maxNumReruns; r = reruns->Next(r)) { - time_t eventStart = event->StartTime(); - time_t rerunStart = r->event->StartTime(); - cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); - //check for identical event - if ((event->ChannelID() == r->event->ChannelID()) && (eventStart == rerunStart)) - continue; - //check for timely distance - if (rerunDistance > 0) - if (rerunStart - eventStart < rerunDistance) - continue; - //check for maxchannel - if (rerunMaxChannel > 0) - if (channel && channel->Number() > rerunMaxChannel) - continue; - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::title, r->event->Title()); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::shorttext, r->event->ShortText()); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::start, *(r->event->GetTimeString())); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::stop, *(r->event->GetEndTimeString())); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::date, *ShortDateString(r->event->StartTime())); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::day, *WeekDayName(r->event->StartTime())); - cString channelID = r->event->ChannelID().ToString(); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelid, *channelID); - bool logoExists = tabs->ChannelLogoExists(*channelID); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channellogoexists, logoExists ? "1" : "0"); - if (channel) { - cString channelNumber = cString::sprintf("%d", channel->Number()); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, channel->ShortName(true)); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, *channelNumber); - } else { - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, ""); - tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, ""); - } - i++; - } -} - -bool cDetailView::LoadScrapInfo(const cEvent *event) { - static cPlugin *pScraper = GetScraperPlugin(); - if (!pScraper || !event) { - return false; - } - delete movie; - movie = NULL; - delete series; - series = NULL; - - ScraperGetEventType getType; - getType.event = event; - getType.recording = NULL; - if (!pScraper->Service("GetEventType", &getType)) { - return false; - } - if (getType.type == tMovie) { - movie = new cMovie(); - movie->movieId = getType.movieId; - pScraper->Service("GetMovie", movie); - return true; - } else if (getType.type == tSeries) { - series = new cSeries(); - series->seriesId = getType.seriesId; - series->episodeId = getType.episodeId; - pScraper->Service("GetSeries", series); - return true; - } - return false; -} - -int cDetailView::NumActors(void) { - if (series) { - return series->actors.size(); - } else if (movie) { - return movie->actors.size(); - } - return 0; -} - -void cDetailView::SetScraperTokens(void) { - if (movie) { - tabs->AddIntToken((int)eScraperIT::ismovie, true); - tabs->AddIntToken((int)eScraperIT::isseries, false); - - tabs->AddStringToken((int)eScraperST::movietitle, movie->title.c_str()); - tabs->AddStringToken((int)eScraperST::movieoriginalTitle, movie->originalTitle.c_str()); - tabs->AddStringToken((int)eScraperST::movietagline, movie->tagline.c_str()); - tabs->AddStringToken((int)eScraperST::movieoverview, movie->overview.c_str()); - tabs->AddStringToken((int)eScraperST::moviegenres, movie->genres.c_str()); - tabs->AddStringToken((int)eScraperST::moviehomepage, movie->homepage.c_str()); - tabs->AddStringToken((int)eScraperST::moviereleasedate, movie->releaseDate.c_str()); - stringstream pop; - pop << movie->popularity; - tabs->AddStringToken((int)eScraperST::moviepopularity, pop.str().c_str()); - stringstream vote; - vote << movie->voteAverage; - tabs->AddStringToken((int)eScraperST::movievoteaverage, pop.str().c_str()); - tabs->AddStringToken((int)eScraperST::posterpath, movie->poster.path.c_str()); - tabs->AddStringToken((int)eScraperST::fanartpath, movie->fanart.path.c_str()); - tabs->AddStringToken((int)eScraperST::collectionposterpath, movie->collectionPoster.path.c_str()); - tabs->AddStringToken((int)eScraperST::collectionfanartpath, movie->collectionFanart.path.c_str()); - - tabs->AddIntToken((int)eScraperIT::movieadult, movie->adult); - tabs->AddIntToken((int)eScraperIT::moviebudget, movie->budget); - tabs->AddIntToken((int)eScraperIT::movierevenue, movie->revenue); - tabs->AddIntToken((int)eScraperIT::movieruntime, movie->runtime); - tabs->AddIntToken((int)eScraperIT::posterwidth, movie->poster.width); - tabs->AddIntToken((int)eScraperIT::posterheight, movie->poster.height); - tabs->AddIntToken((int)eScraperIT::fanartwidth, movie->fanart.width); - tabs->AddIntToken((int)eScraperIT::fanartheight, movie->fanart.height); - tabs->AddIntToken((int)eScraperIT::collectionposterwidth, movie->collectionPoster.width); - tabs->AddIntToken((int)eScraperIT::collectionposterheight, movie->collectionPoster.height); - tabs->AddIntToken((int)eScraperIT::collectionfanartwidth, movie->collectionFanart.width); - tabs->AddIntToken((int)eScraperIT::collectionfanartheight, movie->collectionFanart.height); - - int actorsIndex = tabs->GetLoopIndex("actors"); - int i=0; - for (vector::iterator act = movie->actors.begin(); act != movie->actors.end(); act++) { - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::name, (*act).name.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::role, (*act).role.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumb, (*act).actorThumb.path.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbwidth, *cString::sprintf("%d", (*act).actorThumb.width)); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbheight, *cString::sprintf("%d", (*act).actorThumb.height)); - i++; - } - } else if (series) { - tabs->AddIntToken((int)eScraperIT::ismovie, false); - tabs->AddIntToken((int)eScraperIT::isseries, true); - //Series Basics - tabs->AddStringToken((int)eScraperST::seriesname, series->name.c_str()); - tabs->AddStringToken((int)eScraperST::seriesoverview, series->overview.c_str()); - tabs->AddStringToken((int)eScraperST::seriesfirstaired, series->firstAired.c_str()); - tabs->AddStringToken((int)eScraperST::seriesnetwork, series->network.c_str()); - tabs->AddStringToken((int)eScraperST::seriesgenre, series->genre.c_str()); - stringstream rating; - rating << series->rating; - tabs->AddStringToken((int)eScraperST::seriesrating, rating.str().c_str()); - tabs->AddStringToken((int)eScraperST::seriesstatus, series->status.c_str()); - //Episode Information - tabs->AddIntToken((int)eScraperIT::episodenumber, series->episode.number); - tabs->AddIntToken((int)eScraperIT::episodeseason, series->episode.season); - tabs->AddStringToken((int)eScraperST::episodetitle, series->episode.name.c_str()); - tabs->AddStringToken((int)eScraperST::episodefirstaired, series->episode.firstAired.c_str()); - tabs->AddStringToken((int)eScraperST::episodegueststars, series->episode.guestStars.c_str()); - tabs->AddStringToken((int)eScraperST::episodeoverview, series->episode.overview.c_str()); - stringstream eprating; - eprating << series->episode.rating; - tabs->AddStringToken((int)eScraperST::episoderating, eprating.str().c_str()); - tabs->AddIntToken((int)eScraperIT::episodeimagewidth, series->episode.episodeImage.width); - tabs->AddIntToken((int)eScraperIT::episodeimageheight, series->episode.episodeImage.height); - tabs->AddStringToken((int)eScraperST::episodeimagepath, series->episode.episodeImage.path.c_str()); - //Seasonposter - tabs->AddIntToken((int)eScraperIT::seasonposterwidth, series->seasonPoster.width); - tabs->AddIntToken((int)eScraperIT::seasonposterheight, series->seasonPoster.height); - tabs->AddStringToken((int)eScraperST::seasonposterpath, series->seasonPoster.path.c_str()); - - //Posters - int indexInt = (int)eScraperIT::seriesposter1width; - int indexStr = (int)eScraperST::seriesposter1path; - for(vector::iterator poster = series->posters.begin(); poster != series->posters.end(); poster++) { - tabs->AddIntToken(indexInt, (*poster).width); - tabs->AddIntToken(indexInt+1, (*poster).height); - tabs->AddStringToken(indexStr, (*poster).path.c_str()); - indexInt += 2; - indexStr++; - } - //Banners - indexInt = (int)eScraperIT::seriesbanner1width; - indexStr = (int)eScraperST::seriesbanner1path; - for(vector::iterator banner = series->banners.begin(); banner != series->banners.end(); banner++) { - tabs->AddIntToken(indexInt, (*banner).width); - tabs->AddIntToken(indexInt+1, (*banner).height); - tabs->AddStringToken(indexStr, (*banner).path.c_str()); - indexInt += 2; - indexStr++; - } - //Fanarts - indexInt = (int)eScraperIT::seriesfanart1width; - indexStr = (int)eScraperST::seriesfanart1path; - for(vector::iterator fanart = series->fanarts.begin(); fanart != series->fanarts.end(); fanart++) { - tabs->AddIntToken(indexInt, (*fanart).width); - tabs->AddIntToken(indexInt+1, (*fanart).height); - tabs->AddStringToken(indexStr, (*fanart).path.c_str()); - indexInt += 2; - indexStr++; - } - //Actors - int actorsIndex = tabs->GetLoopIndex("actors"); - int i=0; - for (vector::iterator act = series->actors.begin(); act != series->actors.end(); act++) { - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::name, (*act).name.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::role, (*act).role.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumb, (*act).actorThumb.path.c_str()); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbwidth, *cString::sprintf("%d", (*act).actorThumb.width)); - tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbheight, *cString::sprintf("%d", (*act).actorThumb.height)); - i++; - } - } else { - tabs->AddIntToken((int)eScraperIT::ismovie, false); - tabs->AddIntToken((int)eScraperIT::isseries, false); - } -} - -void cDetailView::SetEpgPictures(int eventId) { - string epgImagePath = tabs->GetEpgImagePath(); - for (int i=0; i<3; i++) { - stringstream picName; - picName << eventId << "_" << i; - bool epgPicAvailable = FileExists(epgImagePath, picName.str(), "jpg"); - if (epgPicAvailable) { - tabs->AddIntToken((int)eDetailedEpgIT::epgpic1avaialble + i, true); - tabs->AddStringToken((int)eDetailedEpgST::epgpic1path + i, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), picName.str().c_str())); - } else { - tabs->AddIntToken((int)eDetailedEpgIT::epgpic1avaialble + i, false); - tabs->AddStringToken((int)eDetailedEpgST::epgpic1path + i, ""); - } - } +#include "helpers.h" +#include "tvguidengosd.h" +#include "detailview.h" + +cDetailView::cDetailView(skindesignerapi::cOsdView *detailView, const cEvent *event) { + init = true; + lastSecond = -1; + this->detailView = detailView; + this->event = event; + back = detailView->GetViewElement((int)eViewElementsDetail::background); + header = detailView->GetViewElement((int)eViewElementsDetail::header); + footer = detailView->GetViewElement((int)eViewElementsDetail::footer); + watch = detailView->GetViewElement((int)eViewElementsDetail::time); + tabs = detailView->GetViewTabs(); + movie = NULL; + series = NULL; +} + +cDetailView::~cDetailView() { + delete back; + delete header; + delete footer; + delete watch; + delete tabs; + delete detailView; + delete movie; + delete series; +} + +void cDetailView::Draw(void) { + if (!event) { + return; + } + if (init) { + DrawBackground(); + DrawHeader(); + DrawFooter(); + Flush(); + SetTabTokens(); + tabs->Init(); + init = false; + } + tabs->Display(); +} + +void cDetailView::Left(void) { + tabs->Left(); + tabs->Display(); +} + +void cDetailView::Right(void) { + tabs->Right(); + tabs->Display(); +} + +void cDetailView::Up(void) { + tabs->Up(); + tabs->Display(); +} + +void cDetailView::Down(void) { + tabs->Down(); + tabs->Display(); +} + +void cDetailView::DefineTokens(eViewElementsDetail ve, skindesignerapi::cTokenContainer *tk) { + switch (ve) { + case eViewElementsDetail::header: + tk->DefineIntToken("{ismovie}", (int)eScraperHeaderIT::ismovie); + tk->DefineIntToken("{isseries}", (int)eScraperHeaderIT::isseries); + tk->DefineIntToken("{posteravailable}", (int)eScraperHeaderIT::posteravailable); + tk->DefineIntToken("{posterwidth}", (int)eScraperHeaderIT::posterwidth); + tk->DefineIntToken("{posterheight}", (int)eScraperHeaderIT::posterheight); + tk->DefineIntToken("{banneravailable}", (int)eScraperHeaderIT::banneravailable); + tk->DefineIntToken("{bannerwidth}", (int)eScraperHeaderIT::bannerwidth); + tk->DefineIntToken("{bannerheight}", (int)eScraperHeaderIT::bannerheight); + tk->DefineIntToken("{daynumeric}", (int)eDetailedHeaderIT::daynumeric); + tk->DefineIntToken("{month}", (int)eDetailedHeaderIT::month); + tk->DefineIntToken("{year}", (int)eDetailedHeaderIT::year); + tk->DefineIntToken("{running}", (int)eDetailedHeaderIT::running); + tk->DefineIntToken("{elapsed}", (int)eDetailedHeaderIT::elapsed); + tk->DefineIntToken("{duration}", (int)eDetailedHeaderIT::duration); + tk->DefineIntToken("{durationhours}", (int)eDetailedHeaderIT::durationhours); + tk->DefineIntToken("{channelnumber}", (int)eDetailedHeaderIT::channelnumber); + tk->DefineIntToken("{channellogoexists}", (int)eDetailedHeaderIT::channellogoexists); + tk->DefineIntToken("{epgpicavailable}", (int)eDetailedHeaderIT::epgpicavailable); + tk->DefineStringToken("{posterpath}", (int)eScraperHeaderST::posterpath); + tk->DefineStringToken("{bannerpath}", (int)eScraperHeaderST::bannerpath); + tk->DefineStringToken("{title}", (int)eDetailedHeaderST::title); + tk->DefineStringToken("{shorttext}", (int)eDetailedHeaderST::shorttext); + tk->DefineStringToken("{start}", (int)eDetailedHeaderST::start); + tk->DefineStringToken("{stop}", (int)eDetailedHeaderST::stop); + tk->DefineStringToken("{day}", (int)eDetailedHeaderST::day); + tk->DefineStringToken("{date}", (int)eDetailedHeaderST::date); + tk->DefineStringToken("{durationminutes}", (int)eDetailedHeaderST::durationminutes); + tk->DefineStringToken("{vps}", (int)eDetailedHeaderST::vps); + tk->DefineStringToken("{channelname}", (int)eDetailedHeaderST::channelname); + tk->DefineStringToken("{channelid}", (int)eDetailedHeaderST::channelid); + tk->DefineStringToken("{epgpicpath}", (int)eDetailedHeaderST::epgpicpath); + break; + case eViewElementsDetail::footer: + tk->DefineIntToken("{red1}", (int)eFooterIT::red1); + tk->DefineIntToken("{red2}", (int)eFooterIT::red2); + tk->DefineIntToken("{red3}", (int)eFooterIT::red3); + tk->DefineIntToken("{red4}", (int)eFooterIT::red4); + tk->DefineIntToken("{green1}", (int)eFooterIT::green1); + tk->DefineIntToken("{green2}", (int)eFooterIT::green2); + tk->DefineIntToken("{green3}", (int)eFooterIT::green3); + tk->DefineIntToken("{green4}", (int)eFooterIT::green4); + tk->DefineIntToken("{yellow1}", (int)eFooterIT::yellow1); + tk->DefineIntToken("{yellow2}", (int)eFooterIT::yellow2); + tk->DefineIntToken("{yellow3}", (int)eFooterIT::yellow3); + tk->DefineIntToken("{yellow4}", (int)eFooterIT::yellow4); + tk->DefineIntToken("{blue1}", (int)eFooterIT::blue1); + tk->DefineIntToken("{blue2}", (int)eFooterIT::blue2); + tk->DefineIntToken("{blue3}", (int)eFooterIT::blue3); + tk->DefineIntToken("{blue4}", (int)eFooterIT::blue4); + tk->DefineStringToken("{red}", (int)eFooterST::red); + tk->DefineStringToken("{green}", (int)eFooterST::green); + tk->DefineStringToken("{yellow}", (int)eFooterST::yellow); + tk->DefineStringToken("{blue}", (int)eFooterST::blue); + break; + default: + break; + } +} + +void cDetailView::DefineTabTokens(skindesignerapi::cTokenContainer *tk) { + tk->DefineStringToken("{title}", (int)eDetailedEpgST::title); + tk->DefineStringToken("{shorttext}", (int)eDetailedEpgST::shorttext); + tk->DefineStringToken("{description}", (int)eDetailedEpgST::description); + tk->DefineStringToken("{start}", (int)eDetailedEpgST::start); + tk->DefineStringToken("{stop}", (int)eDetailedEpgST::stop); + tk->DefineStringToken("{day}", (int)eDetailedEpgST::day); + tk->DefineStringToken("{date}", (int)eDetailedEpgST::date); + tk->DefineStringToken("{durationminutes}", (int)eDetailedEpgST::durationminutes); + tk->DefineStringToken("{vps}", (int)eDetailedEpgST::vps); + tk->DefineStringToken("{channelname}", (int)eDetailedEpgST::channelname); + tk->DefineStringToken("{channelid}", (int)eDetailedEpgST::channelid); + tk->DefineStringToken("{epgpic1path}", (int)eDetailedEpgST::epgpic1path); + tk->DefineStringToken("{epgpic2path}", (int)eDetailedEpgST::epgpic2path); + tk->DefineStringToken("{epgpic3path}", (int)eDetailedEpgST::epgpic3path); + tk->DefineStringToken("{movietitle}", (int)eScraperST::movietitle); + tk->DefineStringToken("{movieoriginalTitle}", (int)eScraperST::movieoriginalTitle); + tk->DefineStringToken("{movietagline}", (int)eScraperST::movietagline); + tk->DefineStringToken("{movieoverview}", (int)eScraperST::movieoverview); + tk->DefineStringToken("{moviegenres}", (int)eScraperST::moviegenres); + tk->DefineStringToken("{moviehomepage}", (int)eScraperST::moviehomepage); + tk->DefineStringToken("{moviereleasedate}", (int)eScraperST::moviereleasedate); + tk->DefineStringToken("{moviepopularity}", (int)eScraperST::moviepopularity); + tk->DefineStringToken("{movievoteaverage}", (int)eScraperST::movievoteaverage); + tk->DefineStringToken("{posterpath}", (int)eScraperST::posterpath); + tk->DefineStringToken("{fanartpath}", (int)eScraperST::fanartpath); + tk->DefineStringToken("{moviecollectionName}", (int)eScraperST::moviecollectionName); + tk->DefineStringToken("{collectionposterpath}", (int)eScraperST::collectionposterpath); + tk->DefineStringToken("{collectionfanartpath}", (int)eScraperST::collectionfanartpath); + tk->DefineStringToken("{seriesname}", (int)eScraperST::seriesname); + tk->DefineStringToken("{seriesoverview}", (int)eScraperST::seriesoverview); + tk->DefineStringToken("{seriesfirstaired}", (int)eScraperST::seriesfirstaired); + tk->DefineStringToken("{seriesnetwork}", (int)eScraperST::seriesnetwork); + tk->DefineStringToken("{seriesgenre}", (int)eScraperST::seriesgenre); + tk->DefineStringToken("{seriesrating}", (int)eScraperST::seriesrating); + tk->DefineStringToken("{seriesstatus}", (int)eScraperST::seriesstatus); + tk->DefineStringToken("{episodetitle}", (int)eScraperST::episodetitle); + tk->DefineStringToken("{episodefirstaired}", (int)eScraperST::episodefirstaired); + tk->DefineStringToken("{episodegueststars}", (int)eScraperST::episodegueststars); + tk->DefineStringToken("{episodeoverview}", (int)eScraperST::episodeoverview); + tk->DefineStringToken("{episoderating}", (int)eScraperST::episoderating); + tk->DefineStringToken("{episodeimagepath}", (int)eScraperST::episodeimagepath); + tk->DefineStringToken("{seasonposterpath}", (int)eScraperST::seasonposterpath); + tk->DefineStringToken("{seriesposter1path}", (int)eScraperST::seriesposter1path); + tk->DefineStringToken("{seriesposter2path}", (int)eScraperST::seriesposter2path); + tk->DefineStringToken("{seriesposter3path}", (int)eScraperST::seriesposter3path); + tk->DefineStringToken("{seriesfanart1path}", (int)eScraperST::seriesfanart1path); + tk->DefineStringToken("{seriesfanart2path}", (int)eScraperST::seriesfanart2path); + tk->DefineStringToken("{seriesfanart3path}", (int)eScraperST::seriesfanart3path); + tk->DefineStringToken("{seriesbanner1path}", (int)eScraperST::seriesbanner1path); + tk->DefineStringToken("{seriesbanner2path}", (int)eScraperST::seriesbanner2path); + tk->DefineStringToken("{seriesbanner3path}", (int)eScraperST::seriesbanner3path); + tk->DefineIntToken("{daynumeric}", (int)eDetailedEpgIT::daynumeric); + tk->DefineIntToken("{month}", (int)eDetailedEpgIT::month); + tk->DefineIntToken("{year}", (int)eDetailedEpgIT::year); + tk->DefineIntToken("{running}", (int)eDetailedEpgIT::running); + tk->DefineIntToken("{elapsed}", (int)eDetailedEpgIT::elapsed); + tk->DefineIntToken("{duration}", (int)eDetailedEpgIT::duration); + tk->DefineIntToken("{durationhours}", (int)eDetailedEpgIT::durationhours); + tk->DefineIntToken("{channelnumber}", (int)eDetailedEpgIT::channelnumber); + tk->DefineIntToken("{channellogoexists}", (int)eDetailedEpgIT::channellogoexists); + tk->DefineIntToken("{hasreruns}", (int)eDetailedEpgIT::hasreruns); + tk->DefineIntToken("{epgpic1avaialble}", (int)eDetailedEpgIT::epgpic1avaialble); + tk->DefineIntToken("{epgpic2avaialble}", (int)eDetailedEpgIT::epgpic2avaialble); + tk->DefineIntToken("{epgpic3avaialble}", (int)eDetailedEpgIT::epgpic3avaialble); + tk->DefineIntToken("{ismovie}", (int)eScraperIT::ismovie); + tk->DefineIntToken("{moviebudget}", (int)eScraperIT::moviebudget); + tk->DefineIntToken("{movierevenue}", (int)eScraperIT::movierevenue); + tk->DefineIntToken("{movieadult}", (int)eScraperIT::movieadult); + tk->DefineIntToken("{movieruntime}", (int)eScraperIT::movieruntime); + tk->DefineIntToken("{isseries}", (int)eScraperIT::isseries); + tk->DefineIntToken("{posterwidth}", (int)eScraperIT::posterwidth); + tk->DefineIntToken("{posterheight}", (int)eScraperIT::posterheight); + tk->DefineIntToken("{fanartwidth}", (int)eScraperIT::fanartwidth); + tk->DefineIntToken("{fanartheight}", (int)eScraperIT::fanartheight); + tk->DefineIntToken("{movieiscollection}", (int)eScraperIT::movieiscollection); + tk->DefineIntToken("{collectionposterwidth}", (int)eScraperIT::collectionposterwidth); + tk->DefineIntToken("{collectionposterheight}", (int)eScraperIT::collectionposterheight); + tk->DefineIntToken("{collectionfanartwidth}", (int)eScraperIT::collectionfanartwidth); + tk->DefineIntToken("{collectionfanartheight}", (int)eScraperIT::collectionfanartheight); + tk->DefineIntToken("{epgpicavailable}", (int)eScraperIT::epgpicavailable); + tk->DefineIntToken("{episodenumber}", (int)eScraperIT::episodenumber); + tk->DefineIntToken("{episodeseason}", (int)eScraperIT::episodeseason); + tk->DefineIntToken("{episodeimagewidth}", (int)eScraperIT::episodeimagewidth); + tk->DefineIntToken("{episodeimageheight}", (int)eScraperIT::episodeimageheight); + tk->DefineIntToken("{seasonposterwidth}", (int)eScraperIT::seasonposterwidth); + tk->DefineIntToken("{seasonposterheight}", (int)eScraperIT::seasonposterheight); + tk->DefineIntToken("{seriesposter1width}", (int)eScraperIT::seriesposter1width); + tk->DefineIntToken("{seriesposter1height}", (int)eScraperIT::seriesposter1height); + tk->DefineIntToken("{seriesposter2width}", (int)eScraperIT::seriesposter2width); + tk->DefineIntToken("{seriesposter2height}", (int)eScraperIT::seriesposter2height); + tk->DefineIntToken("{seriesposter3width}", (int)eScraperIT::seriesposter3width); + tk->DefineIntToken("{seriesposter3height}", (int)eScraperIT::seriesposter3height); + tk->DefineIntToken("{seriesfanart1width}", (int)eScraperIT::seriesfanart1width); + tk->DefineIntToken("{seriesfanart1height}", (int)eScraperIT::seriesfanart1height); + tk->DefineIntToken("{seriesfanart2width}", (int)eScraperIT::seriesfanart2width); + tk->DefineIntToken("{seriesfanart2height}", (int)eScraperIT::seriesfanart2height); + tk->DefineIntToken("{seriesfanart3width}", (int)eScraperIT::seriesfanart3width); + tk->DefineIntToken("{seriesfanart3height}", (int)eScraperIT::seriesfanart3height); + tk->DefineIntToken("{seriesbanner1width}", (int)eScraperIT::seriesbanner1width); + tk->DefineIntToken("{seriesbanner1height}", (int)eScraperIT::seriesbanner1height); + tk->DefineIntToken("{seriesbanner2width}", (int)eScraperIT::seriesbanner2width); + tk->DefineIntToken("{seriesbanner2height}", (int)eScraperIT::seriesbanner2height); + tk->DefineIntToken("{seriesbanner3width}", (int)eScraperIT::seriesbanner3width); + tk->DefineIntToken("{seriesbanner3height}", (int)eScraperIT::seriesbanner3height); + tk->DefineLoopToken("{reruns[title]}", (int)eRerunsLT::title); + tk->DefineLoopToken("{reruns[shorttext]}", (int)eRerunsLT::shorttext); + tk->DefineLoopToken("{reruns[date]}", (int)eRerunsLT::date); + tk->DefineLoopToken("{reruns[day]}", (int)eRerunsLT::day); + tk->DefineLoopToken("{reruns[start]}", (int)eRerunsLT::start); + tk->DefineLoopToken("{reruns[stop]}", (int)eRerunsLT::stop); + tk->DefineLoopToken("{reruns[channelname]}", (int)eRerunsLT::channelname); + tk->DefineLoopToken("{reruns[channelnumber]}", (int)eRerunsLT::channelnumber); + tk->DefineLoopToken("{reruns[channelid]}", (int)eRerunsLT::channelid); + tk->DefineLoopToken("{reruns[channellogoexists]}", (int)eRerunsLT::channellogoexists); + tk->DefineLoopToken("{actors[name]}", (int)eScraperLT::name); + tk->DefineLoopToken("{actors[role]}", (int)eScraperLT::role); + tk->DefineLoopToken("{actors[thumb]}", (int)eScraperLT::thumb); + tk->DefineLoopToken("{actors[thumbwidth]}", (int)eScraperLT::thumbwidth); + tk->DefineLoopToken("{actors[thumbheight]}", (int)eScraperLT::thumbheight); +} +/******************************************************************** +* Private Functions +********************************************************************/ +void cDetailView::DrawBackground(void) { + back->Display(); +} + +void cDetailView::DrawHeader(void) { + if (!event) + return; + header->ClearTokens(); + static cPlugin *pScraper = GetScraperPlugin(); + if (pScraper) { + ScraperGetEventType getType; + getType.event = event; + if (!pScraper->Service("GetEventType", &getType)) { + if (getType.type == tMovie) { + cMovie movie; + movie.movieId = getType.movieId; + pScraper->Service("GetMovie", &movie); + header->AddIntToken((int)eScraperHeaderIT::banneravailable, true); + header->AddIntToken((int)eScraperHeaderIT::isseries, false); + header->AddIntToken((int)eScraperHeaderIT::posteravailable, true); + header->AddIntToken((int)eScraperHeaderIT::banneravailable, false); + header->AddStringToken((int)eScraperHeaderST::posterpath, movie.poster.path.c_str()); + header->AddIntToken((int)eScraperHeaderIT::posterwidth, movie.poster.width); + header->AddIntToken((int)eScraperHeaderIT::posterheight, movie.poster.height); + } else if (getType.type == tSeries) { + cSeries series; + series.seriesId = getType.seriesId; + series.episodeId = getType.episodeId; + pScraper->Service("GetSeries", &series); + header->AddIntToken((int)eScraperHeaderIT::ismovie, false); + header->AddIntToken((int)eScraperHeaderIT::isseries, true); + vector::iterator poster = series.posters.begin(); + if (poster != series.posters.end()) { + header->AddIntToken((int)eScraperHeaderIT::posterwidth, (*poster).width); + header->AddIntToken((int)eScraperHeaderIT::posterheight, (*poster).height); + header->AddStringToken((int)eScraperHeaderST::posterpath, (*poster).path.c_str()); + header->AddIntToken((int)eScraperHeaderIT::posteravailable, true); + } + vector::iterator banner = series.banners.begin(); + if (banner != series.banners.end()) { + header->AddIntToken((int)eScraperHeaderIT::bannerwidth, (*banner).width); + header->AddIntToken((int)eScraperHeaderIT::bannerheight, (*banner).height); + header->AddStringToken((int)eScraperHeaderST::bannerpath, (*banner).path.c_str()); + header->AddIntToken((int)eScraperHeaderIT::banneravailable, true); + } + } + } + } + + header->AddStringToken((int)eDetailedHeaderST::title, event->Title()); + header->AddStringToken((int)eDetailedHeaderST::shorttext, event->ShortText()); + header->AddStringToken((int)eDetailedHeaderST::start, *(event->GetTimeString())); + header->AddStringToken((int)eDetailedHeaderST::stop, *(event->GetEndTimeString())); + + time_t startTime = event->StartTime(); + header->AddStringToken((int)eDetailedHeaderST::day, *WeekDayName(startTime)); + header->AddStringToken((int)eDetailedHeaderST::date, *ShortDateString(startTime)); + struct tm * sStartTime = localtime(&startTime); + header->AddIntToken((int)eDetailedHeaderIT::year, sStartTime->tm_year + 1900); + header->AddIntToken((int)eDetailedHeaderIT::daynumeric, sStartTime->tm_mday); + header->AddIntToken((int)eDetailedHeaderIT::month, sStartTime->tm_mon+1); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(event->ChannelID()); +#else + const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); +#endif + if (channel) { + header->AddStringToken((int)eDetailedHeaderST::channelname, channel->Name()); + header->AddIntToken((int)eDetailedHeaderIT::channelnumber, channel->Number()); + } else { + header->AddIntToken((int)eDetailedHeaderIT::channelnumber, 0); + } + cString channelID = channel->GetChannelID().ToString(); + header->AddStringToken((int)eDetailedHeaderST::channelid, *channelID); + header->AddIntToken((int)eDetailedHeaderIT::channellogoexists, header->ChannelLogoExists(*channelID)); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + header->AddIntToken((int)eDetailedHeaderIT::running, isRunning); + if (isRunning) { + header->AddIntToken((int)eDetailedHeaderIT::elapsed, (now - event->StartTime())/60); + } else { + header->AddIntToken((int)eDetailedHeaderIT::elapsed, 0); + } + header->AddIntToken((int)eDetailedHeaderIT::duration, event->Duration() / 60); + header->AddIntToken((int)eDetailedHeaderIT::durationhours, event->Duration() / 3600); + header->AddStringToken((int)eDetailedHeaderST::durationminutes, *cString::sprintf("%.2d", (event->Duration() / 60)%60)); + if (event->Vps()) + header->AddStringToken((int)eDetailedHeaderST::vps, *event->GetVpsString()); + + stringstream epgImageName; + epgImageName << event->EventID(); + string epgImagePath = header->GetEpgImagePath(); + + bool epgPicAvailable = FileExists(epgImagePath, epgImageName.str(), "jpg"); + if (epgPicAvailable) { + header->AddIntToken((int)eDetailedHeaderIT::epgpicavailable, true); + header->AddStringToken((int)eDetailedHeaderST::epgpicpath, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), epgImageName.str().c_str())); + } else { + epgImageName << "_0"; + epgPicAvailable = FileExists(epgImagePath, epgImageName.str(), "jpg"); + if (epgPicAvailable) { + header->AddIntToken((int)eDetailedHeaderIT::epgpicavailable, true); + header->AddStringToken((int)eDetailedHeaderST::epgpicpath, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), epgImageName.str().c_str())); + } + } + + header->Display(); +} + +void cDetailView::DrawFooter(void) { + string textGreen = ""; + string textYellow = ""; + string textRed = tr("Search & Record"); + string textBlue = tr("Switch"); + + int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 }; + + footer->Clear(); + footer->ClearTokens(); + + footer->AddStringToken((int)eFooterST::red, textRed.c_str()); + footer->AddStringToken((int)eFooterST::green, textGreen.c_str()); + footer->AddStringToken((int)eFooterST::yellow, textYellow.c_str()); + footer->AddStringToken((int)eFooterST::blue, textBlue.c_str()); + + for (int button = 0; button < 4; button++) { + bool isRed = false; + bool isGreen = false; + bool isYellow = false; + bool isBlue = false; + switch (colorKeys[button]) { + case 0: + isRed = true; + break; + case 1: + isGreen = true; + break; + case 2: + isYellow = true; + break; + case 3: + isBlue = true; + break; + default: + break; + } + footer->AddIntToken(0 + button, isRed); + footer->AddIntToken(4 + button, isGreen); + footer->AddIntToken(8 + button, isYellow); + footer->AddIntToken(12 + button, isBlue); + } + + footer->Display(); +} + +bool cDetailView::DrawTime(void) { + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + int sec = now->tm_sec; + if (sec == lastSecond) + return false; + + int min = now->tm_min; + int hour = now->tm_hour; + int hourMinutes = hour%12 * 5 + min / 12; + + char monthname[20]; + char monthshort[10]; + strftime(monthshort, sizeof(monthshort), "%b", now); + strftime(monthname, sizeof(monthname), "%B", now); + + watch->Clear(); + watch->ClearTokens(); + watch->AddIntToken((int)eTimeIT::sec, sec); + watch->AddIntToken((int)eTimeIT::min, min); + watch->AddIntToken((int)eTimeIT::hour, hour); + watch->AddIntToken((int)eTimeIT::hmins, hourMinutes); + watch->AddIntToken((int)eTimeIT::year, now->tm_year + 1900); + watch->AddIntToken((int)eTimeIT::day, now->tm_mday); + watch->AddStringToken((int)eTimeST::time, *TimeString(t)); + watch->AddStringToken((int)eTimeST::monthname, monthname); + watch->AddStringToken((int)eTimeST::monthnameshort, monthshort); + watch->AddStringToken((int)eTimeST::month, *cString::sprintf("%02d", now->tm_mon + 1)); + watch->AddStringToken((int)eTimeST::dayleadingzero, *cString::sprintf("%02d", now->tm_mday)); + watch->AddStringToken((int)eTimeST::dayname, *WeekDayNameFull(now->tm_wday)); + watch->AddStringToken((int)eTimeST::daynameshort, *WeekDayName(now->tm_wday)); + watch->Display(); + + lastSecond = sec; + return true; +} + +void cDetailView::SetTabTokens(void) { + tabs->ClearTokens(); + tabs->AddStringToken((int)eDetailedEpgST::title, event->Title()); + tabs->AddStringToken((int)eDetailedEpgST::shorttext, event->ShortText()); + tabs->AddStringToken((int)eDetailedEpgST::description, event->Description()); + tabs->AddStringToken((int)eDetailedEpgST::start, *(event->GetTimeString())); + tabs->AddStringToken((int)eDetailedEpgST::stop, *(event->GetEndTimeString())); + time_t startTime = event->StartTime(); + tabs->AddStringToken((int)eDetailedEpgST::day, *WeekDayName(startTime)); + tabs->AddStringToken((int)eDetailedEpgST::date, *ShortDateString(startTime)); + struct tm * sStartTime = localtime(&startTime); + tabs->AddIntToken((int)eDetailedEpgIT::year, sStartTime->tm_year + 1900); + tabs->AddIntToken((int)eDetailedEpgIT::daynumeric, sStartTime->tm_mday); + tabs->AddIntToken((int)eDetailedEpgIT::month, sStartTime->tm_mon+1); + + cString channelID = event->ChannelID().ToString(); + tabs->AddStringToken((int)eDetailedEpgST::channelid, *channelID); + tabs->AddIntToken((int)eDetailedEpgIT::channellogoexists, tabs->ChannelLogoExists(*channelID)); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + tabs->AddIntToken((int)eDetailedEpgIT::running, isRunning); + if (isRunning) { + tabs->AddIntToken((int)eDetailedEpgIT::elapsed, (now - event->StartTime())/60); + } else { + tabs->AddIntToken((int)eDetailedEpgIT::elapsed, 0); + } + tabs->AddIntToken((int)eDetailedEpgIT::duration, event->Duration() / 60); + tabs->AddIntToken((int)eDetailedEpgIT::durationhours, event->Duration() / 3600); + tabs->AddStringToken((int)eDetailedEpgST::durationminutes, *cString::sprintf("%.2d", (event->Duration() / 60)%60)); + if (event->Vps()) + tabs->AddStringToken((int)eDetailedEpgST::vps, *event->GetVpsString()); + else + tabs->AddStringToken((int)eDetailedEpgST::vps, ""); + + + bool scrapInfoAvailable = LoadScrapInfo(event); + int numActors = NumActors(); + + cList *reruns = LoadReruns(); + int numReruns = NumReruns(reruns); + + vector loopInfo; + loopInfo.push_back(numReruns); + loopInfo.push_back(numActors); + tabs->SetLoop(loopInfo); + + if (numReruns > 0) { + tabs->AddIntToken((int)eDetailedEpgIT::hasreruns, 1); + SetReruns(reruns); + } + if (scrapInfoAvailable) { + SetScraperTokens(); + } + + SetEpgPictures(event->EventID()); +} + +cList *cDetailView::LoadReruns(void) { + cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch"); + if (!epgSearchPlugin) + return NULL; + + if (isempty(event->Title())) + return NULL; + + Epgsearch_searchresults_v1_0 data; + data.query = (char*)event->Title(); + data.mode = 0; + data.channelNr = 0; + data.useTitle = true; + data.useSubTitle = true; + data.useDescription = false; + + cList *result = NULL; + if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) + result = data.pResultList; + return result; +} + +int cDetailView::NumReruns(cList *reruns) { + if (!reruns || reruns->Count() < 2) + return 0; + + int maxNumReruns = config.rerunAmount; + int rerunDistance = config.rerunDistance * 3600; + int rerunMaxChannel = config.rerunMaxChannel; + + int i = 0; + for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = reruns->First(); r && i < maxNumReruns; r = reruns->Next(r)) { + time_t eventStart = event->StartTime(); + time_t rerunStart = r->event->StartTime(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(r->event->ChannelID(), true, true); +#else + const cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); +#endif + //check for identical event + if ((event->ChannelID() == r->event->ChannelID()) && (eventStart == rerunStart)) + continue; + //check for timely distance + if (rerunDistance > 0) + if (rerunStart - eventStart < rerunDistance) + continue; + //check for maxchannel + if (rerunMaxChannel > 0) + if (channel && channel->Number() > rerunMaxChannel) + continue; + i++; + } + return i; +} + +void cDetailView::SetReruns(cList *reruns) { + if (!reruns || reruns->Count() < 2) + return; + int rerunsIndex = tabs->GetLoopIndex("reruns"); + + int maxNumReruns = config.rerunAmount; + int rerunDistance = config.rerunDistance * 3600; + int rerunMaxChannel = config.rerunMaxChannel; + + int i = 0; + for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = reruns->First(); r && i < maxNumReruns; r = reruns->Next(r)) { + time_t eventStart = event->StartTime(); + time_t rerunStart = r->event->StartTime(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(r->event->ChannelID(), true, true); +#else + const cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); +#endif + //check for identical event + if ((event->ChannelID() == r->event->ChannelID()) && (eventStart == rerunStart)) + continue; + //check for timely distance + if (rerunDistance > 0) + if (rerunStart - eventStart < rerunDistance) + continue; + //check for maxchannel + if (rerunMaxChannel > 0) + if (channel && channel->Number() > rerunMaxChannel) + continue; + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::title, r->event->Title()); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::shorttext, r->event->ShortText()); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::start, *(r->event->GetTimeString())); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::stop, *(r->event->GetEndTimeString())); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::date, *ShortDateString(r->event->StartTime())); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::day, *WeekDayName(r->event->StartTime())); + cString channelID = r->event->ChannelID().ToString(); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelid, *channelID); + bool logoExists = tabs->ChannelLogoExists(*channelID); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channellogoexists, logoExists ? "1" : "0"); + if (channel) { + cString channelNumber = cString::sprintf("%d", channel->Number()); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, channel->ShortName(true)); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, *channelNumber); + } else { + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, ""); + tabs->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, ""); + } + i++; + } +} + +bool cDetailView::LoadScrapInfo(const cEvent *event) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || !event) { + return false; + } + delete movie; + movie = NULL; + delete series; + series = NULL; + + ScraperGetEventType getType; + getType.event = event; + getType.recording = NULL; + if (!pScraper->Service("GetEventType", &getType)) { + return false; + } + if (getType.type == tMovie) { + movie = new cMovie(); + movie->movieId = getType.movieId; + pScraper->Service("GetMovie", movie); + return true; + } else if (getType.type == tSeries) { + series = new cSeries(); + series->seriesId = getType.seriesId; + series->episodeId = getType.episodeId; + pScraper->Service("GetSeries", series); + return true; + } + return false; +} + +int cDetailView::NumActors(void) { + if (series) { + return series->actors.size(); + } else if (movie) { + return movie->actors.size(); + } + return 0; +} + +void cDetailView::SetScraperTokens(void) { + if (movie) { + tabs->AddIntToken((int)eScraperIT::ismovie, true); + tabs->AddIntToken((int)eScraperIT::isseries, false); + + tabs->AddStringToken((int)eScraperST::movietitle, movie->title.c_str()); + tabs->AddStringToken((int)eScraperST::movieoriginalTitle, movie->originalTitle.c_str()); + tabs->AddStringToken((int)eScraperST::movietagline, movie->tagline.c_str()); + tabs->AddStringToken((int)eScraperST::movieoverview, movie->overview.c_str()); + tabs->AddStringToken((int)eScraperST::moviegenres, movie->genres.c_str()); + tabs->AddStringToken((int)eScraperST::moviehomepage, movie->homepage.c_str()); + tabs->AddStringToken((int)eScraperST::moviereleasedate, movie->releaseDate.c_str()); + stringstream pop; + pop << movie->popularity; + tabs->AddStringToken((int)eScraperST::moviepopularity, pop.str().c_str()); + stringstream vote; + vote << movie->voteAverage; + tabs->AddStringToken((int)eScraperST::movievoteaverage, pop.str().c_str()); + tabs->AddStringToken((int)eScraperST::posterpath, movie->poster.path.c_str()); + tabs->AddStringToken((int)eScraperST::fanartpath, movie->fanart.path.c_str()); + tabs->AddStringToken((int)eScraperST::collectionposterpath, movie->collectionPoster.path.c_str()); + tabs->AddStringToken((int)eScraperST::collectionfanartpath, movie->collectionFanart.path.c_str()); + + tabs->AddIntToken((int)eScraperIT::movieadult, movie->adult); + tabs->AddIntToken((int)eScraperIT::moviebudget, movie->budget); + tabs->AddIntToken((int)eScraperIT::movierevenue, movie->revenue); + tabs->AddIntToken((int)eScraperIT::movieruntime, movie->runtime); + tabs->AddIntToken((int)eScraperIT::posterwidth, movie->poster.width); + tabs->AddIntToken((int)eScraperIT::posterheight, movie->poster.height); + tabs->AddIntToken((int)eScraperIT::fanartwidth, movie->fanart.width); + tabs->AddIntToken((int)eScraperIT::fanartheight, movie->fanart.height); + tabs->AddIntToken((int)eScraperIT::collectionposterwidth, movie->collectionPoster.width); + tabs->AddIntToken((int)eScraperIT::collectionposterheight, movie->collectionPoster.height); + tabs->AddIntToken((int)eScraperIT::collectionfanartwidth, movie->collectionFanart.width); + tabs->AddIntToken((int)eScraperIT::collectionfanartheight, movie->collectionFanart.height); + + int actorsIndex = tabs->GetLoopIndex("actors"); + int i=0; + for (vector::iterator act = movie->actors.begin(); act != movie->actors.end(); act++) { + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::name, (*act).name.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::role, (*act).role.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumb, (*act).actorThumb.path.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbwidth, *cString::sprintf("%d", (*act).actorThumb.width)); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbheight, *cString::sprintf("%d", (*act).actorThumb.height)); + i++; + } + } else if (series) { + tabs->AddIntToken((int)eScraperIT::ismovie, false); + tabs->AddIntToken((int)eScraperIT::isseries, true); + //Series Basics + tabs->AddStringToken((int)eScraperST::seriesname, series->name.c_str()); + tabs->AddStringToken((int)eScraperST::seriesoverview, series->overview.c_str()); + tabs->AddStringToken((int)eScraperST::seriesfirstaired, series->firstAired.c_str()); + tabs->AddStringToken((int)eScraperST::seriesnetwork, series->network.c_str()); + tabs->AddStringToken((int)eScraperST::seriesgenre, series->genre.c_str()); + stringstream rating; + rating << series->rating; + tabs->AddStringToken((int)eScraperST::seriesrating, rating.str().c_str()); + tabs->AddStringToken((int)eScraperST::seriesstatus, series->status.c_str()); + //Episode Information + tabs->AddIntToken((int)eScraperIT::episodenumber, series->episode.number); + tabs->AddIntToken((int)eScraperIT::episodeseason, series->episode.season); + tabs->AddStringToken((int)eScraperST::episodetitle, series->episode.name.c_str()); + tabs->AddStringToken((int)eScraperST::episodefirstaired, series->episode.firstAired.c_str()); + tabs->AddStringToken((int)eScraperST::episodegueststars, series->episode.guestStars.c_str()); + tabs->AddStringToken((int)eScraperST::episodeoverview, series->episode.overview.c_str()); + stringstream eprating; + eprating << series->episode.rating; + tabs->AddStringToken((int)eScraperST::episoderating, eprating.str().c_str()); + tabs->AddIntToken((int)eScraperIT::episodeimagewidth, series->episode.episodeImage.width); + tabs->AddIntToken((int)eScraperIT::episodeimageheight, series->episode.episodeImage.height); + tabs->AddStringToken((int)eScraperST::episodeimagepath, series->episode.episodeImage.path.c_str()); + //Seasonposter + tabs->AddIntToken((int)eScraperIT::seasonposterwidth, series->seasonPoster.width); + tabs->AddIntToken((int)eScraperIT::seasonposterheight, series->seasonPoster.height); + tabs->AddStringToken((int)eScraperST::seasonposterpath, series->seasonPoster.path.c_str()); + + //Posters + int indexInt = (int)eScraperIT::seriesposter1width; + int indexStr = (int)eScraperST::seriesposter1path; + for(vector::iterator poster = series->posters.begin(); poster != series->posters.end(); poster++) { + tabs->AddIntToken(indexInt, (*poster).width); + tabs->AddIntToken(indexInt+1, (*poster).height); + tabs->AddStringToken(indexStr, (*poster).path.c_str()); + indexInt += 2; + indexStr++; + } + //Banners + indexInt = (int)eScraperIT::seriesbanner1width; + indexStr = (int)eScraperST::seriesbanner1path; + for(vector::iterator banner = series->banners.begin(); banner != series->banners.end(); banner++) { + tabs->AddIntToken(indexInt, (*banner).width); + tabs->AddIntToken(indexInt+1, (*banner).height); + tabs->AddStringToken(indexStr, (*banner).path.c_str()); + indexInt += 2; + indexStr++; + } + //Fanarts + indexInt = (int)eScraperIT::seriesfanart1width; + indexStr = (int)eScraperST::seriesfanart1path; + for(vector::iterator fanart = series->fanarts.begin(); fanart != series->fanarts.end(); fanart++) { + tabs->AddIntToken(indexInt, (*fanart).width); + tabs->AddIntToken(indexInt+1, (*fanart).height); + tabs->AddStringToken(indexStr, (*fanart).path.c_str()); + indexInt += 2; + indexStr++; + } + //Actors + int actorsIndex = tabs->GetLoopIndex("actors"); + int i=0; + for (vector::iterator act = series->actors.begin(); act != series->actors.end(); act++) { + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::name, (*act).name.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::role, (*act).role.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumb, (*act).actorThumb.path.c_str()); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbwidth, *cString::sprintf("%d", (*act).actorThumb.width)); + tabs->AddLoopToken(actorsIndex, i, (int)eScraperLT::thumbheight, *cString::sprintf("%d", (*act).actorThumb.height)); + i++; + } + } else { + tabs->AddIntToken((int)eScraperIT::ismovie, false); + tabs->AddIntToken((int)eScraperIT::isseries, false); + } +} + +void cDetailView::SetEpgPictures(int eventId) { + string epgImagePath = tabs->GetEpgImagePath(); + for (int i=0; i<3; i++) { + stringstream picName; + picName << eventId << "_" << i; + bool epgPicAvailable = FileExists(epgImagePath, picName.str(), "jpg"); + if (epgPicAvailable) { + tabs->AddIntToken((int)eDetailedEpgIT::epgpic1avaialble + i, true); + tabs->AddStringToken((int)eDetailedEpgST::epgpic1path + i, *cString::sprintf("%s%s.jpg", epgImagePath.c_str(), picName.str().c_str())); + } else { + tabs->AddIntToken((int)eDetailedEpgIT::epgpic1avaialble + i, false); + tabs->AddStringToken((int)eDetailedEpgST::epgpic1path + i, ""); + } + } } \ No newline at end of file diff --git a/detailview.h b/detailview.h index 517ec9c..d5174d0 100644 --- a/detailview.h +++ b/detailview.h @@ -1,49 +1,49 @@ -#ifndef __TVGUIDE_DETAILVIEW_H -#define __TVGUIDE_DETAILVIEW_H - -#include "services/scraper2vdr.h" -#include "services/epgsearch.h" -#include "config.h" -#include - -class cDetailView { -private: - bool init; - int lastSecond; - skindesignerapi::cOsdView *detailView; - const cEvent *event; - cMovie *movie; - cSeries *series; - skindesignerapi::cViewElement *back; - skindesignerapi::cViewElement *header; - skindesignerapi::cViewElement *footer; - skindesignerapi::cViewElement *watch; - skindesignerapi::cViewTab *tabs; - void DrawBackground(void); - void DrawHeader(void); - void DrawFooter(void); - void SetTabTokens(void); - bool LoadScrapInfo(const cEvent *event); - int NumActors(void); - void SetScraperTokens(void); - cList *LoadReruns(void); - int NumReruns(cList *reruns); - void SetReruns(cList *reruns); - void SetEpgPictures(int eventId); -public: - cDetailView(skindesignerapi::cOsdView *detailView, const cEvent *event); - virtual ~cDetailView(void); - void Activate(void) { detailView->Activate(); }; - void Draw(void); - void Left(void); - void Right(void); - void Up(void); - void Down(void); - bool DrawTime(void); - void Flush(void) { detailView->Display(); }; - const cEvent *GetEvent(void) { return event; }; - static void DefineTokens(eViewElementsDetail ve, skindesignerapi::cTokenContainer *tk); - static void DefineTabTokens(skindesignerapi::cTokenContainer *tk); -}; - -#endif //__TVGUIDE_DETAILVIEW_H +#ifndef __TVGUIDE_DETAILVIEW_H +#define __TVGUIDE_DETAILVIEW_H + +#include "services/scraper2vdr.h" +#include "services/epgsearch.h" +#include "config.h" +#include + +class cDetailView { +private: + bool init; + int lastSecond; + skindesignerapi::cOsdView *detailView; + const cEvent *event; + cMovie *movie; + cSeries *series; + skindesignerapi::cViewElement *back; + skindesignerapi::cViewElement *header; + skindesignerapi::cViewElement *footer; + skindesignerapi::cViewElement *watch; + skindesignerapi::cViewTab *tabs; + void DrawBackground(void); + void DrawHeader(void); + void DrawFooter(void); + void SetTabTokens(void); + bool LoadScrapInfo(const cEvent *event); + int NumActors(void); + void SetScraperTokens(void); + cList *LoadReruns(void); + int NumReruns(cList *reruns); + void SetReruns(cList *reruns); + void SetEpgPictures(int eventId); +public: + cDetailView(skindesignerapi::cOsdView *detailView, const cEvent *event); + virtual ~cDetailView(void); + void Activate(void) { detailView->Activate(); }; + void Draw(void); + void Left(void); + void Right(void); + void Up(void); + void Down(void); + bool DrawTime(void); + void Flush(void) { detailView->Display(); }; + const cEvent *GetEvent(void) { return event; }; + static void DefineTokens(eViewElementsDetail ve, skindesignerapi::cTokenContainer *tk); + static void DefineTabTokens(skindesignerapi::cTokenContainer *tk); +}; + +#endif //__TVGUIDE_DETAILVIEW_H diff --git a/epgelement.c b/epgelement.c index 1ef5542..2e1d077 100644 --- a/epgelement.c +++ b/epgelement.c @@ -1,52 +1,52 @@ -#include "switchtimer.h" -#include "services/remotetimers.h" -#include "epgelement.h" - -cEpgElement::cEpgElement(const cEvent *event, cChannelEpg *owner) : cGridElement(owner) { - this->event = event; - hasTimer = false; - SetTimer(); - hasSwitchTimer = false; - SetSwitchTimer(); - dummy = false; -} - -cEpgElement::~cEpgElement(void) { -} - -void cEpgElement::SetTimer() { - if (config.useRemoteTimers && pRemoteTimers) { - RemoteTimers_Event_v1_0 rt; - rt.event = event; - if (pRemoteTimers->Service("RemoteTimers::GetTimerByEvent-v1.0", &rt)) - hasTimer = true; - else - hasTimer = false; - } else if (owner->HasTimer()) { - hasTimer = event->HasTimer(); - } else { - hasTimer = false; - } -} - -void cEpgElement::SetSwitchTimer() { - if (owner->HasSwitchTimer()) { - hasSwitchTimer = SwitchTimers.EventInSwitchList(event); - } else { - hasSwitchTimer = false; - } -} - -const char *cEpgElement::Title(void) { - return event->Title(); -} - -const char *cEpgElement::ShortText(void) { - if (event->ShortText()) - return event->ShortText(); - return ""; -} - -void cEpgElement::Debug() { - esyslog("tvguideng: epgelement %ld: \"%s\" %s - %s, channel %s, timer: %d", id, event->Title(), *(event->GetTimeString()), *(event->GetEndTimeString()), Channel()->Name(), hasTimer); -} +#include "switchtimer.h" +#include "services/remotetimers.h" +#include "epgelement.h" + +cEpgElement::cEpgElement(const cEvent *event, cChannelEpg *owner) : cGridElement(owner) { + this->event = event; + hasTimer = false; + SetTimer(); + hasSwitchTimer = false; + SetSwitchTimer(); + dummy = false; +} + +cEpgElement::~cEpgElement(void) { +} + +void cEpgElement::SetTimer() { + if (config.useRemoteTimers && pRemoteTimers) { + RemoteTimers_Event_v1_0 rt; + rt.event = event; + if (pRemoteTimers->Service("RemoteTimers::GetTimerByEvent-v1.0", &rt)) + hasTimer = true; + else + hasTimer = false; + } else if (owner->HasTimer()) { + hasTimer = event->HasTimer(); + } else { + hasTimer = false; + } +} + +void cEpgElement::SetSwitchTimer() { + if (owner->HasSwitchTimer()) { + hasSwitchTimer = SwitchTimers.EventInSwitchList(event); + } else { + hasSwitchTimer = false; + } +} + +const char *cEpgElement::Title(void) { + return event->Title(); +} + +const char *cEpgElement::ShortText(void) { + if (event->ShortText()) + return event->ShortText(); + return ""; +} + +void cEpgElement::Debug() { + esyslog("tvguideng: epgelement %ld: \"%s\" %s - %s, channel %s, timer: %d", id, event->Title(), *(event->GetTimeString()), *(event->GetEndTimeString()), Channel()->Name(), hasTimer); +} diff --git a/epgelement.h b/epgelement.h index 3a7b48d..a503914 100644 --- a/epgelement.h +++ b/epgelement.h @@ -1,28 +1,28 @@ -#ifndef __TVGUIDE_EPGGRID_H -#define __TVGUIDE_EPGGRID_H - -#include -#include "gridelement.h" -#include "channelepg.h" - -// --- cEpgGrid ------------------------------------------------------------- - -class cEpgElement : public cGridElement { -private: - const cEvent *event; - time_t Duration(void) { return event->Duration(); }; -public: - cEpgElement(const cEvent *event, cChannelEpg *owner); - virtual ~cEpgElement(void); - const cEvent *GetEvent(void) {return event;}; - time_t StartTime(void) { return event->StartTime(); }; - time_t EndTime(void) { return event->EndTime(); }; - void SetTimer(void); - void SetSwitchTimer(void); - const char *Title(void); - const char *ShortText(void); - const cEvent *Event(void) { return event; }; - void Debug(void); -}; - +#ifndef __TVGUIDE_EPGGRID_H +#define __TVGUIDE_EPGGRID_H + +#include +#include "gridelement.h" +#include "channelepg.h" + +// --- cEpgGrid ------------------------------------------------------------- + +class cEpgElement : public cGridElement { +private: + const cEvent *event; + time_t Duration(void) { return event->Duration(); }; +public: + cEpgElement(const cEvent *event, cChannelEpg *owner); + virtual ~cEpgElement(void); + const cEvent *GetEvent(void) {return event;}; + time_t StartTime(void) { return event->StartTime(); }; + time_t EndTime(void) { return event->EndTime(); }; + void SetTimer(void); + void SetSwitchTimer(void); + const char *Title(void); + const char *ShortText(void); + const cEvent *Event(void) { return event; }; + void Debug(void); +}; + #endif //__TVGUIDE_EPGGRID_H \ No newline at end of file diff --git a/epggrid.c b/epggrid.c index f2ec973..a25437e 100644 --- a/epggrid.c +++ b/epggrid.c @@ -57,7 +57,14 @@ void cEpgGrid::Init(const cChannel *startChannel) { int numBack = channelsPerPage / 2; int offset = 0; const cChannel *newStartChannel = startChannel; - for (; newStartChannel ; newStartChannel = Channels.Prev(newStartChannel)) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + + for (; newStartChannel ; newStartChannel = channels->Prev(newStartChannel)) { if (newStartChannel && !newStartChannel->GroupSep()) { offset++; } @@ -65,7 +72,7 @@ void cEpgGrid::Init(const cChannel *startChannel) { break; } if (!newStartChannel) - newStartChannel = Channels.First(); + newStartChannel = channels->First(); offset--; if (offset < 0) offset = 0; @@ -79,7 +86,15 @@ void cEpgGrid::CreateChannels(const cChannel *startChannel, int activeChannel) { channels.Clear(); if (!startChannel) return; - for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) { + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + cChannels* chls = &Channels; +#endif + + for (const cChannel *channel = startChannel; channel; channel = chls->Next(channel)) { if (config.hideLastChannelGroup && channelGroups->IsInLastGroup(channel)) { break; } @@ -110,7 +125,7 @@ void cEpgGrid::CreateChannels(const cChannel *startChannel, int activeChannel) { int newChannelNumber = 1; if (first) newChannelNumber = first->GetChannelNumber() - numBack; - const cChannel *newStart = Channels.GetByNumber(newChannelNumber); + const cChannel *newStart = chls->GetByNumber(newChannelNumber); CreateChannels(newStart, pos+1); } } @@ -253,7 +268,15 @@ bool cEpgGrid::ChannelForward(void) { return false; //insert new channels at end int numInserted = 0; - for (const cChannel *channel = (const cChannel*)currentChannel->Next(); channel ; channel = Channels.Next(channel)) { + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + const cChannels* chls = &Channels; +#endif + + for (const cChannel *channel = (const cChannel*)currentChannel->Next(); channel ; channel = chls->Next(channel)) { if (channel->GroupSep()) { continue; } @@ -312,7 +335,13 @@ bool cEpgGrid::ChannelBack(void) { return false; //insert new channels at start int numInserted = 0; - for (const cChannel *channel = (const cChannel*)currentChannel->Prev(); channel ; channel = Channels.Prev(channel)) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + const cChannels* chls = &Channels; +#endif + for (const cChannel *channel = (const cChannel*)currentChannel->Prev(); channel ; channel = chls->Prev(channel)) { if (channel->GroupSep()) { continue; } @@ -352,39 +381,67 @@ bool cEpgGrid::ChannelBack(void) { const cChannel *cEpgGrid::GetNextChannelNumJump(void) { const cChannel *newFirst = SeekChannelForward(channelsPerPage); if (!newFirst) - newFirst = Channels.Last(); + { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + newFirst = Channels->Last(); +#else + newFirst = Channels.Last(); +#endif + } + return newFirst; } const cChannel *cEpgGrid::GetPrevChannelNumJump(void) { const cChannel *newFirst = SeekChannelBack(channelsPerPage); if (!newFirst) - newFirst = Channels.First(); + { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + newFirst = Channels->First(); +#else + newFirst = Channels.First(); +#endif + } return newFirst; } const cChannel *cEpgGrid::GetNextChannelGroupJump(void) { - if (!active) { - return Channels.Last(); - } +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + cChannels* chls = &Channels; +#endif + + if (!active) + return chls->Last(); + int currentGroup = channelGroups->GetGroup(active->Channel()); int nextChannelNumber = channelGroups->GetNextGroupFirstChannel(currentGroup); - const cChannel *next = Channels.GetByNumber(nextChannelNumber); + const cChannel *next = chls->GetByNumber(nextChannelNumber); if (next) return next; - return Channels.Last(); + return chls->Last(); } const cChannel *cEpgGrid::GetPrevChannelGroupJump(void) { - if (!active) { - return Channels.First(); - } +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + cChannels* chls = &Channels; +#endif + if (!active) + return chls->First(); + int currentGroup = channelGroups->GetGroup(active->Channel()); int prevChannelNumber = channelGroups->GetPrevGroupFirstChannel(currentGroup); - const cChannel *prev = Channels.GetByNumber(prevChannelNumber); + const cChannel *prev = chls->GetByNumber(prevChannelNumber); if (prev) return prev; - return Channels.First(); + return chls->First(); } bool cEpgGrid::IsFirstGroup(void) { @@ -715,15 +772,22 @@ const cChannel *cEpgGrid::SeekChannelForward(int num) { return NULL; const cChannel *currentChannel = active->Channel(); const cChannel *destChannel; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + const cChannels* chls = &Channels; +#endif + int found = 0; - for (destChannel = currentChannel; destChannel ; destChannel = Channels.Next(destChannel)) { + for (destChannel = currentChannel; destChannel ; destChannel = chls->Next(destChannel)) { if (destChannel->GroupSep()) { continue; } if (config.hideLastChannelGroup && channelGroups->IsInLastGroup(destChannel)) { - destChannel = Channels.Prev(destChannel); + destChannel = chls->Prev(destChannel); while (destChannel && destChannel->GroupSep()) { - destChannel = Channels.Prev(destChannel); + destChannel = chls->Prev(destChannel); } break; } @@ -732,9 +796,9 @@ const cChannel *cEpgGrid::SeekChannelForward(int num) { found++; } if (!destChannel) - destChannel = Channels.Last(); + destChannel = chls->Last(); while (destChannel && destChannel->GroupSep()) { - destChannel = Channels.Prev(destChannel); + destChannel = chls->Prev(destChannel); } return destChannel; } @@ -745,7 +809,13 @@ const cChannel *cEpgGrid::SeekChannelBack(int num) { const cChannel *currentChannel = active->Channel(); const cChannel *destChannel; int found = 0; - for (destChannel = currentChannel; destChannel ; destChannel = Channels.Prev(destChannel)) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* chls = Channels; +#else + const cChannels* chls = &Channels; +#endif + for (destChannel = currentChannel; destChannel ; destChannel = chls->Prev(destChannel)) { if (destChannel->GroupSep()) { continue; } @@ -754,9 +824,9 @@ const cChannel *cEpgGrid::SeekChannelBack(int num) { found++; } if (!destChannel) - destChannel = Channels.First(); + destChannel = chls->First(); while (destChannel && destChannel->GroupSep()) { - destChannel = Channels.Next(destChannel); + destChannel = chls->Next(destChannel); } return destChannel; } @@ -774,4 +844,4 @@ void cEpgGrid::Debug(void) { esyslog("tvguideng: No Active Grid Element"); } esyslog("tvguideng: -----------------------------------------------"); -} \ No newline at end of file +} diff --git a/gridelement.c b/gridelement.c index fe36128..af18fcd 100644 --- a/gridelement.c +++ b/gridelement.c @@ -1,56 +1,56 @@ -#include "gridelement.h" -#include "channelepg.h" - -long cGridElement::idCounter; - -cGridElement::cGridElement(cChannelEpg *owner) { - id = idCounter; - idCounter++; - init = true; - active = false; - hasTimer = false; - hasSwitchTimer = false; - this->owner = owner; -} - -cGridElement::~cGridElement(void) { -} - -bool cGridElement::Match(time_t t) { - if ((StartTime() < t) && (EndTime() > t)) - return true; - else - return false; -} - -bool cGridElement::IsFirst(void) { - return owner->IsFirst(this); -} - -int cGridElement::CalcOverlap(cGridElement *neighbor) { - int overlap = 0; - if (Intersects(neighbor)) { - if ((StartTime() <= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) { - overlap = EndTime() - neighbor->StartTime(); - } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) { - overlap = neighbor->EndTime() - StartTime(); - } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) { - overlap = Duration(); - } else if ((StartTime() <= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) { - overlap = neighbor->EndTime() - neighbor->StartTime(); - } - } - return overlap; -} - -bool cGridElement::Intersects(cGridElement *neighbor) { - return ! ( (neighbor->EndTime() <= StartTime()) || (neighbor->StartTime() >= EndTime()) ); -} - -const cChannel *cGridElement::Channel(void) { - return owner->Channel(); -} - -cChannelEpg *cGridElement::Owner(void) { - return owner; -} +#include "gridelement.h" +#include "channelepg.h" + +long cGridElement::idCounter; + +cGridElement::cGridElement(cChannelEpg *owner) { + id = idCounter; + idCounter++; + init = true; + active = false; + hasTimer = false; + hasSwitchTimer = false; + this->owner = owner; +} + +cGridElement::~cGridElement(void) { +} + +bool cGridElement::Match(time_t t) { + if ((StartTime() < t) && (EndTime() > t)) + return true; + else + return false; +} + +bool cGridElement::IsFirst(void) { + return owner->IsFirst(this); +} + +int cGridElement::CalcOverlap(cGridElement *neighbor) { + int overlap = 0; + if (Intersects(neighbor)) { + if ((StartTime() <= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) { + overlap = EndTime() - neighbor->StartTime(); + } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) { + overlap = neighbor->EndTime() - StartTime(); + } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) { + overlap = Duration(); + } else if ((StartTime() <= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) { + overlap = neighbor->EndTime() - neighbor->StartTime(); + } + } + return overlap; +} + +bool cGridElement::Intersects(cGridElement *neighbor) { + return ! ( (neighbor->EndTime() <= StartTime()) || (neighbor->StartTime() >= EndTime()) ); +} + +const cChannel *cGridElement::Channel(void) { + return owner->Channel(); +} + +cChannelEpg *cGridElement::Owner(void) { + return owner; +} diff --git a/gridelement.h b/gridelement.h index 4bd6d08..aa7ccc3 100644 --- a/gridelement.h +++ b/gridelement.h @@ -1,51 +1,51 @@ -#ifndef __TVGUIDE_GRID_H -#define __TVGUIDE_GRID_H - -#include -#include - -class cChannelEpg; - -class cGridElement : public cListObject { -protected: - static long idCounter; - long id; - bool init; - bool active; - bool hasTimer; - bool hasSwitchTimer; - cChannelEpg *owner; - bool Intersects(cGridElement *neighbor); - virtual time_t Duration(void) { return 0; }; - bool dummy; -public: - cGridElement(cChannelEpg *owner); - virtual ~cGridElement(void); - bool IsNew(void) { return init; }; - void Dirty(void) { init = true; }; - void InitFinished(void) { init = false; }; - void SetActive(void) {active = true;}; - void SetInActive(void) {active = false;}; - bool Match(time_t t); - virtual time_t StartTime(void) { return 0; }; - virtual time_t EndTime(void) { return 0; }; - virtual void SetStartTime(time_t start) {}; - virtual void SetEndTime(time_t end) {}; - int CalcOverlap(cGridElement *neighbor); - virtual void SetTimer(void) {}; - virtual void SetSwitchTimer(void) {}; - long Id(void) { return id; }; - bool Active(void) { return active; }; - bool HasTimer(void) {return hasTimer;}; - bool HasSwitchTimer(void) {return hasSwitchTimer;}; - bool IsFirst(void); - bool IsDummy(void) { return dummy; }; - const cChannel *Channel(void); - virtual const char *Title(void) { return ""; }; - virtual const char *ShortText(void) { return ""; }; - virtual const cEvent *Event(void) { return NULL; }; - cChannelEpg *Owner(void); - virtual void Debug(void) {}; -}; - +#ifndef __TVGUIDE_GRID_H +#define __TVGUIDE_GRID_H + +#include +#include + +class cChannelEpg; + +class cGridElement : public cListObject { +protected: + static long idCounter; + long id; + bool init; + bool active; + bool hasTimer; + bool hasSwitchTimer; + cChannelEpg *owner; + bool Intersects(cGridElement *neighbor); + virtual time_t Duration(void) { return 0; }; + bool dummy; +public: + cGridElement(cChannelEpg *owner); + virtual ~cGridElement(void); + bool IsNew(void) { return init; }; + void Dirty(void) { init = true; }; + void InitFinished(void) { init = false; }; + void SetActive(void) {active = true;}; + void SetInActive(void) {active = false;}; + bool Match(time_t t); + virtual time_t StartTime(void) { return 0; }; + virtual time_t EndTime(void) { return 0; }; + virtual void SetStartTime(time_t start) {}; + virtual void SetEndTime(time_t end) {}; + int CalcOverlap(cGridElement *neighbor); + virtual void SetTimer(void) {}; + virtual void SetSwitchTimer(void) {}; + long Id(void) { return id; }; + bool Active(void) { return active; }; + bool HasTimer(void) {return hasTimer;}; + bool HasSwitchTimer(void) {return hasSwitchTimer;}; + bool IsFirst(void); + bool IsDummy(void) { return dummy; }; + const cChannel *Channel(void); + virtual const char *Title(void) { return ""; }; + virtual const char *ShortText(void) { return ""; }; + virtual const cEvent *Event(void) { return NULL; }; + cChannelEpg *Owner(void); + virtual void Debug(void) {}; +}; + #endif //__TVGUIDE_GRID_H \ No newline at end of file diff --git a/recmanager.c b/recmanager.c index fbbf890..047ca18 100644 --- a/recmanager.c +++ b/recmanager.c @@ -6,6 +6,7 @@ #include #include +#include #include "recmanager.h" static int CompareRecording(const void *p1, const void *p2) { @@ -51,15 +52,23 @@ bool cRecManager::CheckEventForTimer(const cEvent *event) { return hasTimer; } -cTimer *cRecManager::GetTimerForEvent(const cEvent *event) { - cTimer *timer = NULL; +const cTimer *cRecManager::GetTimerForEvent(const cEvent *event) { + const cTimer *timer = NULL; if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_GetMatch_v1_0 rtMatch; rtMatch.event = event; pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); timer = rtMatch.timer; - } else - timer = Timers.GetMatch(event); + return timer; + } + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + timer = Timers->GetMatch(event); +#else + timer = Timers.GetMatch(event); +#endif + return timer; } @@ -74,20 +83,32 @@ cTimer *cRecManager::createTimer(const cEvent *event, std::string path) { } cTimer *cRecManager::createLocalTimer(const cEvent *event, std::string path) { - cTimer *timer = new cTimer(event); - cTimer *t = Timers.GetTimer(timer); + cTimer *timer = new cTimer(event); + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + cTimers* timers = Timers; +#else + cTimers* timers = &Timers; +#endif + + cTimer* t = timers->GetTimer(timer); + if (t) { t->OnOff(); - t->SetEventFromSchedule(); + + // #TODO ist das richtig? + t->SetEvent(event); // t->SetEventFromSchedule(); + delete timer; timer = t; isyslog("timer %s reactivated", *t->ToDescr()); } else { - Timers.Add(timer); + timers->Add(timer); isyslog("timer %s added (active)", *timer->ToDescr()); } SetTimerPath(timer, event, path); - Timers.SetModified(); + timers->SetModified(); return timer; } @@ -144,7 +165,13 @@ void cRecManager::SetTimerPath(cTimer *timer, const cEvent *event, std::string p } void cRecManager::DeleteTimer(int timerID) { - cTimer *t = Timers.Get(timerID); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimer *t = Timers->Get(timerID); +#else + const cTimer *t = Timers.Get(timerID); +#endif + if (!t) return; DeleteTimer(t); @@ -161,21 +188,40 @@ void cRecManager::DeleteTimer(const cEvent *event) { } void cRecManager::DeleteLocalTimer(const cEvent *event) { - cTimer *t = Timers.GetMatch(event); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimer *t = Timers->GetMatch(event); +#else + const cTimer *t = Timers.GetMatch(event); +#endif + if (!t) return; DeleteTimer(t); } -void cRecManager::DeleteTimer(cTimer *timer) { - if (timer->Recording()) { - timer->Skip(); - cRecordControls::Process(time(NULL)); - } +void cRecManager::DeleteTimer(const cTimer *timer) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + cTimers* timers = Timers; +#else + cTimers* timers = &Timers; +#endif + + cTimer* t = timers->GetTimer((cTimer*)timer); // #TODO dirty cast + + if (t->Recording()) { + t->Skip(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + cRecordControls::Process(timers, time(NULL)); +#else + cRecordControls::Process(time(NULL)); +#endif + } isyslog("timer %s deleted", *timer->ToDescr()); - Timers.Del(timer, true); - Timers.SetModified(); + timers->Del(t, true); + timers->SetModified(); } void cRecManager::DeleteRemoteTimer(const cEvent *event) { @@ -184,7 +230,7 @@ void cRecManager::DeleteRemoteTimer(const cEvent *event) { pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); if (rtMatch.timer) { RemoteTimers_Timer_v1_0 rt; - rt.timer = rtMatch.timer; + rt.timer = (cTimer*)rtMatch.timer; // #TODO - dirty cast isyslog("remotetimer %s deleted", *rt.timer->ToDescr()); if (!pRemoteTimers->Service("RemoteTimers::DelTimer-v1.0", &rt)) isyslog("remotetimer error"); @@ -192,7 +238,7 @@ void cRecManager::DeleteRemoteTimer(const cEvent *event) { } } -void cRecManager::SaveTimer(cTimer *timer, cTimer newTimerSettings) { +void cRecManager::SaveTimer(const cTimer *timer, cTimer newTimerSettings) { if (!timer) return; @@ -204,33 +250,45 @@ void cRecManager::SaveTimer(cTimer *timer, cTimer newTimerSettings) { int stop = newTimerSettings.Stop(); std::string fileName = newTimerSettings.File(); - timer->SetDay(day); - timer->SetStart(start); - timer->SetStop(stop); - timer->SetPriority(prio); - timer->SetLifetime(lifetime); - timer->SetFile(fileName.c_str()); - + // #TODO - very dirty cast from const !! + ((cTimer*)timer)->SetDay(day); + ((cTimer*)timer)->SetStart(start); + ((cTimer*)timer)->SetStop(stop); + ((cTimer*)timer)->SetPriority(prio); + ((cTimer*)timer)->SetLifetime(lifetime); + ((cTimer*)timer)->SetFile(fileName.c_str()); + if (timer->HasFlags(tfActive) && !active) - timer->ClrFlags(tfActive); + ((cTimer*)timer)->ClrFlags(tfActive); else if (!timer->HasFlags(tfActive) && active) - timer->SetFlags(tfActive); + ((cTimer*)timer)->SetFlags(tfActive); - timer->SetEventFromSchedule(); +// #TODO to be implemented timer->SetEventFromSchedule(); if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_Timer_v1_0 rt; - rt.timer = timer; + rt.timer = (cTimer*)timer; // #TODO - dirty cast if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt)) rt.timer = NULL; RefreshRemoteTimers(); } else { - Timers.SetModified(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + Timers->SetModified(); +#else + Timers.SetModified(); +#endif } } bool cRecManager::IsRecorded(const cEvent *event) { - cTimer *timer = Timers.GetMatch(event); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + cTimers* timers = Timers; +#else + cTimers* timers = &Timers; +#endif + cTimer *timer = timers->GetMatch(event); if (!timer) return false; return timer->Recording(); @@ -256,7 +314,7 @@ cTVGuideTimerConflicts *cRecManager::CheckTimerConflict(void) { } void cRecManager::CreateSeriesTimer(cTimer *seriesTimer) { - seriesTimer->SetEventFromSchedule(); +// #TOSO seriesTimer->SetEventFromSchedule(); if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_Timer_v1_0 rt; rt.timer = seriesTimer; @@ -264,8 +322,15 @@ void cRecManager::CreateSeriesTimer(cTimer *seriesTimer) { isyslog("%s", *rt.errorMsg); RefreshRemoteTimers(); } else { - Timers.Add(seriesTimer); - Timers.SetModified(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + cTimers* timers = Timers; +#else + cTimers* timers = &Timers; +#endif + + timers->Add(seriesTimer); + timers->SetModified(); } } @@ -312,9 +377,15 @@ const cEvent **cRecManager::PerformSearchTimerSearch(std::string epgSearchString numResults = results.size(); if (numResults > 0) { searchResults = new const cEvent *[numResults]; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else cSchedulesLock schedulesLock; - const cSchedules *schedules; - schedules = cSchedules::Schedules(schedulesLock); + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + const cEvent *event = NULL; int index=0; for (std::list::iterator it=results.begin(); it != results.end(); ++it) { @@ -324,7 +395,15 @@ const cEvent **cRecManager::PerformSearchTimerSearch(std::string epgSearchString int eventID = atoi(flds[1].c_str()); std::string channelID = flds[7]; tChannelID chanID = tChannelID::FromString(channelID.c_str()); - cChannel *channel = Channels.GetByChannelID(chanID); + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + cChannels* channels = &Channels; +#endif + + const cChannel *channel = channels->GetByChannelID(chanID); if (channel) { const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); @@ -431,24 +510,30 @@ void cRecManager::DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTi return; int searchTimerID = searchTimer->GetID(); if (delTimers) { - cTimer *timer = Timers.First(); - while(timer) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_WRITE; + cTimers* timers = Timers; +#else + cTimers* timers = &Timers; +#endif + cTimer *timer = timers->First(); + while (timer) { if (!timer->Recording()) { char* searchID = GetAuxValue(timer, "s-id"); if (searchID) { if (searchTimerID == atoi(searchID)) { - cTimer* timerNext = Timers.Next(timer); + cTimer* timerNext = timers->Next(timer); DeleteTimer(timer); timer = timerNext; } else { - timer = Timers.Next(timer); + timer = timers->Next(timer); } free(searchID); } else { - timer = Timers.Next(timer); + timer = timers->Next(timer); } } else { - timer = Timers.Next(timer); + timer = timers->Next(timer); } } } @@ -501,13 +586,20 @@ void cRecManager::DeleteSwitchTimer(const cEvent *event) { } } -cRecording **cRecManager::SearchForRecordings(std::string searchString, int &numResults) { +const cRecording **cRecManager::SearchForRecordings(std::string searchString, int &numResults) { - cRecording **matchingRecordings = NULL; + const cRecording **matchingRecordings = NULL; int num = 0; numResults = 0; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_RECORDINGS_READ; + const cRecordings* recordings = Recordings; +#else + const cRecordings* recordings = &Recordings; +#endif - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { + for (const cRecording *recording = recordings->First(); recording; recording = recordings->Next(recording)) { std::string s1 = recording->Name(); std::string s2 = searchString; if (s1.empty() || s2.empty()) continue; @@ -538,7 +630,7 @@ cRecording **cRecManager::SearchForRecordings(std::string searchString, int &num } if (match) { - matchingRecordings = (cRecording **)realloc(matchingRecordings, (num + 1) * sizeof(cRecording *)); + matchingRecordings = (const cRecording **)realloc(matchingRecordings, (num + 1) * sizeof(cRecording *)); matchingRecordings[num++] = recording; } } @@ -615,17 +707,31 @@ void cRecManager::GetFavorites(std::vector *favorites) { const cEvent **cRecManager::WhatsOnNow(bool nowOrNext, int &numResults) { std::vector tmpResults; + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + cChannels* channels = &Channels; +#endif + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else cSchedulesLock schedulesLock; - const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + const cChannel *startChannel = NULL, *stopChannel = NULL; if (config.favLimitChannels) { - startChannel = Channels.GetByNumber(config.favStartChannel); - stopChannel = Channels.GetByNumber(config.favStopChannel); + startChannel = channels->GetByNumber(config.favStartChannel); + stopChannel = channels->GetByNumber(config.favStopChannel); } if (!startChannel) - startChannel = Channels.First(); + startChannel = channels->First(); - for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) { + for (const cChannel *channel = startChannel; channel; channel = channels->Next(channel)) { if (channel->GroupSep()) continue; const cSchedule *Schedule = schedules->GetSchedule(channel); if (!Schedule) continue; @@ -675,17 +781,30 @@ const cEvent **cRecManager::UserDefinedTime(int userTime, int &numResults) { if (searchTime < now) searchTime += 24*60*60; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + cChannels* channels = &Channels; +#endif + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_SCHEDULES_READ; + const cSchedules* schedules = Schedules; +#else cSchedulesLock schedulesLock; - const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock); +#endif + const cChannel *startChannel = NULL, *stopChannel = NULL; if (config.favLimitChannels) { - startChannel = Channels.GetByNumber(config.favStartChannel); - stopChannel = Channels.GetByNumber(config.favStopChannel); + startChannel = channels->GetByNumber(config.favStartChannel); + stopChannel = channels->GetByNumber(config.favStopChannel); } if (!startChannel) - startChannel = Channels.First(); + startChannel = channels->First(); - for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) { + for (const cChannel *channel = startChannel; channel; channel = channels->Next(channel)) { if (channel->GroupSep()) continue; const cSchedule *Schedule = schedules->GetSchedule(channel); if (!Schedule) continue; diff --git a/recmanager.h b/recmanager.h index cff14fd..a901049 100644 --- a/recmanager.h +++ b/recmanager.h @@ -29,17 +29,17 @@ public: bool EpgSearchAvailable(void) {return epgSearchAvailable;}; bool RefreshRemoteTimers(void); bool CheckEventForTimer(const cEvent *event); - cTimer *GetTimerForEvent(const cEvent *event); + const cTimer *GetTimerForEvent(const cEvent *event); cTimer *createTimer(const cEvent *event, std::string path = ""); cTimer *createLocalTimer(const cEvent *event, std::string path); cTimer *createRemoteTimer(const cEvent *event, std::string path); void SetTimerPath(cTimer *timer, const cEvent *event, std::string path); - void DeleteTimer(cTimer *timer); + void DeleteTimer(const cTimer *timer); void DeleteTimer(int timerID); void DeleteTimer(const cEvent *event); void DeleteLocalTimer(const cEvent *event); void DeleteRemoteTimer(const cEvent *event); - void SaveTimer(cTimer *timer, cTimer newTimerSettings); + void SaveTimer(const cTimer *timer, cTimer newTimerSettings); bool IsRecorded(const cEvent *event); cTVGuideTimerConflicts *CheckTimerConflict(void); void CreateSeriesTimer(cTimer *seriesTimer); @@ -53,7 +53,7 @@ public: void UpdateSearchTimers(void); bool CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer); void DeleteSwitchTimer(const cEvent *event); - cRecording **SearchForRecordings(std::string searchString, int &numResults); + const cRecording **SearchForRecordings(std::string searchString, int &numResults); const cEvent **LoadReruns(const cEvent *event, int &numResults); void GetFavorites(std::vector *favorites); const cEvent **WhatsOnNow(bool nowOrNext, int &numResults); @@ -61,4 +61,4 @@ public: virtual ~cRecManager (void); }; -#endif //__TVGUIDE_RECMMANAGER_H \ No newline at end of file +#endif //__TVGUIDE_RECMMANAGER_H diff --git a/recmenu.c b/recmenu.c index 3e55b00..8f23bc9 100644 --- a/recmenu.c +++ b/recmenu.c @@ -1,623 +1,623 @@ -#include "recmenu.h" -#include "tvguidengosd.h" - -// --- cRecMenu ------------------------------------------------------------- - -cRecMenu::cRecMenu() { - hidden = false; - menuWidth = 50; - menuHeight = 0; - maxMenuHeight = 98; - recMenuGrid = NULL; - osdView = NULL; - scrollBar = NULL; - back = NULL; - start = NULL; - stop = NULL; - itemCount = 0; - active = NULL; - header = NULL; - footer = NULL; - scrolling = false; -} - -cRecMenu::~cRecMenu(void) { - menuItems.Clear(); - if (scrollBar) { - scrollBar->Clear(); - delete scrollBar; - scrollBar = NULL; - } - if (back) { - back->Clear(); - delete back; - back = NULL; - } - if (recMenuGrid) { - recMenuGrid->Clear(); - delete recMenuGrid; - } - if (hidden) - osdView->Activate(); -} - -/******************************************************************** -* Public Functions -********************************************************************/ - -void cRecMenu::Init(skindesignerapi::cOsdView *osdView) { - this->osdView = osdView; - recMenuGrid = osdView->GetViewGrid((int)eViewGridsRecMenu::menu); - scrollBar = osdView->GetViewElement((int)eViewElementsRecMenu::scrollbar); - back = osdView->GetViewElement((int)eViewElementsRecMenu::background); - InitMenuItems(); -} - -void cRecMenu::Draw(void) { - DrawHeader(); - double width = (double)menuWidth / (double)100; - double x = (double)(100 - menuWidth)/(double)200; - int totalHeight = GetHeight(); - int yPerc = (100 - totalHeight) / 2; - if (header) - yPerc += header->GetHeight(); - double y = (double)yPerc/(double)100; - - for (cRecMenuItem *current = start; current; current = menuItems.Next(current)) { - - double itemHeight = (double)(current->GetHeight())/(double)100; - if (current->IsNew()) { - current->SetTokens(recMenuGrid); - recMenuGrid->SetGrid(current->Id(), x, y, width, itemHeight); - } else { - recMenuGrid->MoveGrid(current->Id(), x, y, width, itemHeight); - } - if (current->Active()) { - recMenuGrid->SetCurrent(current->Id(), true); - } - y += itemHeight; - if (current == stop) - break; - } - DrawFooter(); - recMenuGrid->Display(); -} - -eRecMenuState cRecMenu::ProcessKey(eKeys Key) { - eRecMenuState state = rmsContinue; - if (!active) - return state; - - state = active->ProcessKey(Key); - if (state == rmsRefresh) { - //Refresh current - active->SetTokens(recMenuGrid); - active->SetNew(); - Draw(); - } else if (state == rmsNotConsumed) { - switch (Key & ~k_Repeat) { - case kUp: - if (!ScrollUp(false)) - SetLast(); - Draw(); - state = rmsConsumed; - break; - case kDown: - if (!ScrollDown(false)) - SetFirst(); - Draw(); - state = rmsConsumed; - break; - case kLeft: - if (PageUp()) - Draw(); - state = rmsConsumed; - break; - case kRight: - if (PageDown()) - Draw(); - state = rmsConsumed; - break; - case kBack: - state = rmsClose; - break; - default: - break; - } - } - return state; -} - -void cRecMenu::DefineTokens(eViewElementsRecMenu ve, skindesignerapi::cTokenContainer *tk) { - switch (ve) { - case eViewElementsRecMenu::background: - tk->DefineIntToken("{menuwidth}", (int)eBackgroundRecMenuIT::menuwidth); - tk->DefineIntToken("{menuheight}", (int)eBackgroundRecMenuIT::menuheight); - tk->DefineIntToken("{hasscrollbar}", (int)eBackgroundRecMenuIT::hasscrollbar); - break; - case eViewElementsRecMenu::scrollbar: - tk->DefineIntToken("{menuwidth}", (int)eScrollbarRecMenuIT::menuwidth); - tk->DefineIntToken("{posy}", (int)eScrollbarRecMenuIT::posy); - tk->DefineIntToken("{totalheight}", (int)eScrollbarRecMenuIT::totalheight); - tk->DefineIntToken("{height}", (int)eScrollbarRecMenuIT::height); - tk->DefineIntToken("{offset}", (int)eScrollbarRecMenuIT::offset); - break; - default: - break; - } -} - -void cRecMenu::DefineTokens(eViewGridsRecMenu vg, skindesignerapi::cTokenContainer *tk) { - tk->DefineIntToken("{info}", (int)eRecMenuIT::info); - tk->DefineIntToken("{lines}", (int)eRecMenuIT::lines); - tk->DefineIntToken("{button}", (int)eRecMenuIT::button); - tk->DefineIntToken("{buttonyesno}", (int)eRecMenuIT::buttonyesno); - tk->DefineIntToken("{yes}", (int)eRecMenuIT::yes); - tk->DefineIntToken("{intselector}", (int)eRecMenuIT::intselector); - tk->DefineIntToken("{intvalue}", (int)eRecMenuIT::value); - tk->DefineIntToken("{boolselector}", (int)eRecMenuIT::boolselector); - tk->DefineIntToken("{stringselector}", (int)eRecMenuIT::stringselector); - tk->DefineIntToken("{textinput}", (int)eRecMenuIT::textinput); - tk->DefineIntToken("{editmode}", (int)eRecMenuIT::editmode); - tk->DefineIntToken("{timeselector}", (int)eRecMenuIT::timeselector); - tk->DefineIntToken("{dayselector}", (int)eRecMenuIT::dayselector); - tk->DefineIntToken("{channelselector}", (int)eRecMenuIT::channelselector); - tk->DefineIntToken("{channelnumber}", (int)eRecMenuIT::channelnumber); - tk->DefineIntToken("{channellogoexisis}", (int)eRecMenuIT::channellogoexisis); - tk->DefineIntToken("{weekdayselector}", (int)eRecMenuIT::weekdayselector); - tk->DefineIntToken("{dayselected}", (int)eRecMenuIT::dayselected); - tk->DefineIntToken("{day0set}", (int)eRecMenuIT::day0set); - tk->DefineIntToken("{day1set}", (int)eRecMenuIT::day1set); - tk->DefineIntToken("{day2set}", (int)eRecMenuIT::day2set); - tk->DefineIntToken("{day3set}", (int)eRecMenuIT::day3set); - tk->DefineIntToken("{day4set}", (int)eRecMenuIT::day4set); - tk->DefineIntToken("{day5set}", (int)eRecMenuIT::day5set); - tk->DefineIntToken("{day6set}", (int)eRecMenuIT::day6set); - tk->DefineIntToken("{directoryselector}", (int)eRecMenuIT::directoryselector); - tk->DefineIntToken("{timerconflictheader}", (int)eRecMenuIT::timerconflictheader); - tk->DefineIntToken("{overlapstartpercent}", (int)eRecMenuIT::overlapstartpercent); - tk->DefineIntToken("{overlapwidthpercent}", (int)eRecMenuIT::overlapwidthpercent); - tk->DefineIntToken("{timerconflict}", (int)eRecMenuIT::timerconflict); - tk->DefineIntToken("{infoactive}", (int)eRecMenuIT::infoactive); - tk->DefineIntToken("{deleteactive}", (int)eRecMenuIT::deleteactive); - tk->DefineIntToken("{editactive}", (int)eRecMenuIT::editactive); - tk->DefineIntToken("{searchactive}", (int)eRecMenuIT::searchactive); - tk->DefineIntToken("{timerstartpercent}", (int)eRecMenuIT::timerstartpercent); - tk->DefineIntToken("{timerwidthpercent}", (int)eRecMenuIT::timerwidthpercent); - tk->DefineIntToken("{event}", (int)eRecMenuIT::event); - tk->DefineIntToken("{hastimer}", (int)eRecMenuIT::hastimer); - tk->DefineIntToken("{recording}", (int)eRecMenuIT::recording); - tk->DefineIntToken("{recduration}", (int)eRecMenuIT::recduration); - tk->DefineIntToken("{searchtimer}", (int)eRecMenuIT::searchtimer); - tk->DefineIntToken("{timeractive}", (int)eRecMenuIT::timeractive); - tk->DefineIntToken("{activetimers}", (int)eRecMenuIT::activetimers); - tk->DefineIntToken("{recordingsdone}", (int)eRecMenuIT::recordingsdone); - tk->DefineIntToken("{timelineheader}", (int)eRecMenuIT::timelineheader); - tk->DefineIntToken("{timerset}", (int)eRecMenuIT::timerset); - tk->DefineIntToken("{channeltransponder}", (int)eRecMenuIT::channeltransponder); - tk->DefineIntToken("{timelinetimer}", (int)eRecMenuIT::timelinetimer); - tk->DefineIntToken("{timerstart}", (int)eRecMenuIT::timerstart); - tk->DefineIntToken("{timerwidth}", (int)eRecMenuIT::timerwidth); - tk->DefineIntToken("{favorite}", (int)eRecMenuIT::favorite); - tk->DefineStringToken("{line1}", (int)eRecMenuST::line1); - tk->DefineStringToken("{line2}", (int)eRecMenuST::line2); - tk->DefineStringToken("{line3}", (int)eRecMenuST::line3); - tk->DefineStringToken("{line4}", (int)eRecMenuST::line4); - tk->DefineStringToken("{stringvalue}", (int)eRecMenuST::value); - tk->DefineStringToken("{buttontext}", (int)eRecMenuST::buttontext); - tk->DefineStringToken("{textyes}", (int)eRecMenuST::textyes); - tk->DefineStringToken("{textno}", (int)eRecMenuST::textno); - tk->DefineStringToken("{text}", (int)eRecMenuST::text); - tk->DefineStringToken("{channelname}", (int)eRecMenuST::channelname); - tk->DefineStringToken("{channelid}", (int)eRecMenuST::channelid); - tk->DefineStringToken("{transponder}", (int)eRecMenuST::transponder); - tk->DefineStringToken("{day0abbr}", (int)eRecMenuST::day0abbr); - tk->DefineStringToken("{day1abbr}", (int)eRecMenuST::day1abbr); - tk->DefineStringToken("{day2abbr}", (int)eRecMenuST::day2abbr); - tk->DefineStringToken("{day3abbr}", (int)eRecMenuST::day3abbr); - tk->DefineStringToken("{day4abbr}", (int)eRecMenuST::day4abbr); - tk->DefineStringToken("{day5abbr}", (int)eRecMenuST::day5abbr); - tk->DefineStringToken("{day6abbr}", (int)eRecMenuST::day6abbr); - tk->DefineStringToken("{folder}", (int)eRecMenuST::folder); - tk->DefineStringToken("{conflictstart}", (int)eRecMenuST::conflictstart); - tk->DefineStringToken("{conflictstop}", (int)eRecMenuST::conflictstop); - tk->DefineStringToken("{overlapstart}", (int)eRecMenuST::overlapstart); - tk->DefineStringToken("{overlapstop}", (int)eRecMenuST::overlapstop); - tk->DefineStringToken("{timertitle}", (int)eRecMenuST::timertitle); - tk->DefineStringToken("{starttime}", (int)eRecMenuST::starttime); - tk->DefineStringToken("{stoptime}", (int)eRecMenuST::stoptime); - tk->DefineStringToken("{date}", (int)eRecMenuST::date); - tk->DefineStringToken("{weekday}", (int)eRecMenuST::weekday); - tk->DefineStringToken("{title}", (int)eRecMenuST::title); - tk->DefineStringToken("{shorttext}", (int)eRecMenuST::shorttext); - tk->DefineStringToken("{recname}", (int)eRecMenuST::recname); - tk->DefineStringToken("{recstarttime}", (int)eRecMenuST::recstarttime); - tk->DefineStringToken("{recdate}", (int)eRecMenuST::recdate); - tk->DefineStringToken("{searchstring}", (int)eRecMenuST::searchstring); - tk->DefineStringToken("{timerstart}", (int)eRecMenuST::timerstart); - tk->DefineStringToken("{timerstop}", (int)eRecMenuST::timerstop); - tk->DefineStringToken("{eventtitle}", (int)eRecMenuST::eventtitle); - tk->DefineStringToken("{eventshorttext}", (int)eRecMenuST::eventshorttext); - tk->DefineStringToken("{eventstart}", (int)eRecMenuST::eventstart); - tk->DefineStringToken("{eventstop}", (int)eRecMenuST::eventstop); - tk->DefineStringToken("{favdesc}", (int)eRecMenuST::favdesc); -} - -/******************************************************************** -* Protected Functions -********************************************************************/ -void cRecMenu::AddMenuItem(cRecMenuItem *item, bool inFront) { - if (!inFront) - menuItems.Add(item); - else - menuItems.Ins(item); -} - -void cRecMenu::AddHeader(cRecMenuItem *header) { - this->header = header; - maxMenuHeight -= header->GetHeight(); -} - -void cRecMenu::AddFooter(cRecMenuItem *footer) { - this->footer = footer; - maxMenuHeight -= footer->GetHeight(); -} - -int cRecMenu::GetNumActive(void) { - int num = 0; - for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { - if (current == active) { - return num; - } - num++; - } - return 0; -} - -bool cRecMenu::ScrollUp(bool retry) { - if (active == start) { - bool scrolled = SeekBack(false); - if (scrolled && scrolling) DrawScrollbar(); - } - if (footer && active == footer) { - recMenuGrid->SetCurrent(footer->Id(), false); - footer->SetInactive(); - active = stop; - active->SetActive(); - return true; - } - cRecMenuItem *prev = (cRecMenuItem*)active->Prev(); - while (prev && !prev->Selectable()) { - prev = (cRecMenuItem*)prev->Prev(); - } - if (prev) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = prev; - active->SetActive(); - return true; - } else { - SeekBack(false); - if (!retry) - ScrollUp(true); - } - return false; -} - -bool cRecMenu::ScrollDown(bool retry) { - if (active == stop || retry) { - bool scrolled = SeekForward(false); - if (scrolled && scrolling) DrawScrollbar(); - } - cRecMenuItem *next = (cRecMenuItem*)active->Next(); - while (next && !next->Selectable()) { - if (next == stop) { - return ScrollDown(true); - } - next = (cRecMenuItem*)next->Next(); - } - if (next) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = next; - active->SetActive(); - return true; - } else { - SeekForward(false); - if (!retry) - return ScrollDown(true); - } - if (footer && active != footer) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = footer; - active->SetActive(); - return true; - } - return false; -} - -bool cRecMenu::PageUp(void) { - bool scrolled = SeekBack(true); - if (scrolled && scrolling) DrawScrollbar(); - if (!scrolled) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = start; - active->SetActive(); - return true; - } - if (!active) { - active = stop; - active->SetActive(); - } - return scrolled; -} - -bool cRecMenu::PageDown(void) { - bool scrolled = SeekForward(true); - if (scrolled && scrolling) DrawScrollbar(); - if (!scrolled) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = stop; - active->SetActive(); - return true; - } - if (!active) { - active = start; - active->SetActive(); - } - return scrolled; -} - -void cRecMenu::ClearMenuItems(bool deleteItems) { - if (deleteItems) { - menuItems.Clear(); - active = NULL; - } else { - for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { - current->SetNew(); - } - } - itemCount = 0; - back->Clear(); - scrollBar->Clear(); - recMenuGrid->Clear(); - if (header) - header->SetNew(); - if (footer) - footer->SetNew(); - if (active) - active->SetInactive(); - active = NULL; -} - -void cRecMenu::InitMenuItems(void) { - if (menuItems.Count() == 0) - return; - scrolling = false; - menuHeight = 0; - start = menuItems.First(); - cRecMenuItem *current = start; - while (current) { - int itemHeight = current->GetHeight(); - if (menuHeight + itemHeight > maxMenuHeight) { - scrolling = true; - break; - } - if (current->Active()) - active = current; - itemCount++; - stop = current; - menuHeight += itemHeight; - current = menuItems.Next(current); - } - DrawBackground(); - Flush(); - if (scrolling) { - DrawScrollbar(); - Flush(); - } -} - -void cRecMenu::InitMenuItemsLast(void) { - if (menuItems.Count() == 0) - return; - scrolling = false; - menuHeight = 0; - stop = menuItems.Last(); - active = stop; - active->SetActive(); - cRecMenuItem *current = stop; - while (current) { - int itemHeight = current->GetHeight(); - if (menuHeight + itemHeight > maxMenuHeight) { - scrolling = true; - break; - } - itemCount++; - start = current; - menuHeight += itemHeight; - current = menuItems.Prev(current); - } - DrawBackground(); - Flush(); - if (scrolling) { - DrawScrollbar(); - Flush(); - } -} - -int cRecMenu::GetHeight(void) { - int totalHeight = menuHeight; - if (header) - totalHeight += header->GetHeight(); - if (footer) - totalHeight += footer->GetHeight(); - return totalHeight; -} - -/******************************************************************** -* Private Functions -********************************************************************/ - -bool cRecMenu::SeekForward(bool page) { - int jumpStep = 0; - if (page) - jumpStep = itemCount; - else - jumpStep = itemCount/2; - int jump = 0; - cRecMenuItem *next = (cRecMenuItem*)stop->Next(); - while (next && jump < jumpStep) { - stop = next; - menuHeight += next->GetHeight(); - next = (cRecMenuItem*)next->Next(); - jump++; - } - while (start && menuHeight > maxMenuHeight) { - if (active == start) { - active = NULL; - start->SetInactive(); - } - menuHeight -= start->GetHeight(); - recMenuGrid->Delete(start->Id()); - start->SetNew(); - start = (cRecMenuItem*)start->Next(); - } - if (jump > 0) - return true; - return false; -} - -bool cRecMenu::SeekBack(bool page) { - int jumpStep = 0; - if (page) - jumpStep = itemCount; - else - jumpStep = itemCount/2; - int jump = 0; - cRecMenuItem *prev = (cRecMenuItem*)start->Prev(); - while (prev && jump < jumpStep) { - start = prev; - menuHeight += prev->GetHeight(); - prev = (cRecMenuItem*)prev->Prev(); - jump++; - } - while (stop && menuHeight > maxMenuHeight) { - if (active == stop) { - active = NULL; - stop->SetInactive(); - } - menuHeight -= stop->GetHeight(); - recMenuGrid->Delete(stop->Id()); - stop->SetNew(); - stop = (cRecMenuItem*)stop->Prev(); - } - if (jump > 0) - return true; - return false; -} - -void cRecMenu::SetFirst(void) { - if (!scrolling) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - active = start; - active->SetActive(); - return; - } - ClearMenuItems(false); - menuItems.First()->SetActive(); - InitMenuItems(); -} - -void cRecMenu::SetLast(void) { - if (!scrolling) { - recMenuGrid->SetCurrent(active->Id(), false); - active->SetInactive(); - if (footer) { - active = footer; - } else { - active = stop; - } - active->SetActive(); - return; - } - ClearMenuItems(false); - InitMenuItemsLast(); -} - -void cRecMenu::DrawBackground(void) { - back->Clear(); - back->ClearTokens(); - back->AddIntToken((int)eBackgroundRecMenuIT::menuwidth, menuWidth + 2); - back->AddIntToken((int)eBackgroundRecMenuIT::menuheight, GetHeight() + 2); - back->AddIntToken((int)eBackgroundRecMenuIT::hasscrollbar, scrolling); - back->Display(); -} - -void cRecMenu::DrawScrollbar(void) { - if (menuItems.Count() == 0) - return; - int scrollBarHeight = (double)itemCount / (double)menuItems.Count() * 1000; - int startPos = 0; - for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { - if (start == current) - break; - startPos++; - } - int offset = (double)startPos / (double)menuItems.Count() * 1000; - scrollBar->Clear(); - scrollBar->ClearTokens(); - scrollBar->AddIntToken((int)eScrollbarRecMenuIT::menuwidth, menuWidth + 2); - int y = (100 - GetHeight())/2; - if (header) - y += header->GetHeight(); - - scrollBar->AddIntToken((int)eScrollbarRecMenuIT::posy, y); - scrollBar->AddIntToken((int)eScrollbarRecMenuIT::totalheight, menuHeight); - scrollBar->AddIntToken((int)eScrollbarRecMenuIT::height, scrollBarHeight); - scrollBar->AddIntToken((int)eScrollbarRecMenuIT::offset, offset); - scrollBar->Display(); -} - -void cRecMenu::DrawHeader(void) { - if (!header) - return; - double width = (double)menuWidth / (double)100; - double x = (double)(100 - menuWidth)/(double)200; - int totalHeight = GetHeight(); - double y = (double)((100 - totalHeight) / 2) / (double)100; - - if (header->IsNew()) { - recMenuGrid->ClearTokens(); - header->SetTokens(recMenuGrid); - recMenuGrid->SetGrid(header->Id(), x, y, width, (double)header->GetHeight()/(double)100); - } -} - -void cRecMenu::DrawFooter(void) { - if (!footer) - return; - double width = (double)menuWidth / (double)100; - double x = (double)(100 - menuWidth)/(double)200; - int totalHeight = GetHeight(); - int totalMenuHeight = menuHeight; - if (header) - totalMenuHeight += header->GetHeight(); - double y = (double)((100 - totalHeight) / 2 + totalMenuHeight) / (double)100; - - if (footer->IsNew()) { - recMenuGrid->ClearTokens(); - footer->SetTokens(recMenuGrid); - recMenuGrid->SetGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); - } else { - recMenuGrid->MoveGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); - } - if (footer->Active()) { - active = footer; - recMenuGrid->SetCurrent(footer->Id(), true); - } +#include "recmenu.h" +#include "tvguidengosd.h" + +// --- cRecMenu ------------------------------------------------------------- + +cRecMenu::cRecMenu() { + hidden = false; + menuWidth = 50; + menuHeight = 0; + maxMenuHeight = 98; + recMenuGrid = NULL; + osdView = NULL; + scrollBar = NULL; + back = NULL; + start = NULL; + stop = NULL; + itemCount = 0; + active = NULL; + header = NULL; + footer = NULL; + scrolling = false; +} + +cRecMenu::~cRecMenu(void) { + menuItems.Clear(); + if (scrollBar) { + scrollBar->Clear(); + delete scrollBar; + scrollBar = NULL; + } + if (back) { + back->Clear(); + delete back; + back = NULL; + } + if (recMenuGrid) { + recMenuGrid->Clear(); + delete recMenuGrid; + } + if (hidden) + osdView->Activate(); +} + +/******************************************************************** +* Public Functions +********************************************************************/ + +void cRecMenu::Init(skindesignerapi::cOsdView *osdView) { + this->osdView = osdView; + recMenuGrid = osdView->GetViewGrid((int)eViewGridsRecMenu::menu); + scrollBar = osdView->GetViewElement((int)eViewElementsRecMenu::scrollbar); + back = osdView->GetViewElement((int)eViewElementsRecMenu::background); + InitMenuItems(); +} + +void cRecMenu::Draw(void) { + DrawHeader(); + double width = (double)menuWidth / (double)100; + double x = (double)(100 - menuWidth)/(double)200; + int totalHeight = GetHeight(); + int yPerc = (100 - totalHeight) / 2; + if (header) + yPerc += header->GetHeight(); + double y = (double)yPerc/(double)100; + + for (cRecMenuItem *current = start; current; current = menuItems.Next(current)) { + + double itemHeight = (double)(current->GetHeight())/(double)100; + if (current->IsNew()) { + current->SetTokens(recMenuGrid); + recMenuGrid->SetGrid(current->Id(), x, y, width, itemHeight); + } else { + recMenuGrid->MoveGrid(current->Id(), x, y, width, itemHeight); + } + if (current->Active()) { + recMenuGrid->SetCurrent(current->Id(), true); + } + y += itemHeight; + if (current == stop) + break; + } + DrawFooter(); + recMenuGrid->Display(); +} + +eRecMenuState cRecMenu::ProcessKey(eKeys Key) { + eRecMenuState state = rmsContinue; + if (!active) + return state; + + state = active->ProcessKey(Key); + if (state == rmsRefresh) { + //Refresh current + active->SetTokens(recMenuGrid); + active->SetNew(); + Draw(); + } else if (state == rmsNotConsumed) { + switch (Key & ~k_Repeat) { + case kUp: + if (!ScrollUp(false)) + SetLast(); + Draw(); + state = rmsConsumed; + break; + case kDown: + if (!ScrollDown(false)) + SetFirst(); + Draw(); + state = rmsConsumed; + break; + case kLeft: + if (PageUp()) + Draw(); + state = rmsConsumed; + break; + case kRight: + if (PageDown()) + Draw(); + state = rmsConsumed; + break; + case kBack: + state = rmsClose; + break; + default: + break; + } + } + return state; +} + +void cRecMenu::DefineTokens(eViewElementsRecMenu ve, skindesignerapi::cTokenContainer *tk) { + switch (ve) { + case eViewElementsRecMenu::background: + tk->DefineIntToken("{menuwidth}", (int)eBackgroundRecMenuIT::menuwidth); + tk->DefineIntToken("{menuheight}", (int)eBackgroundRecMenuIT::menuheight); + tk->DefineIntToken("{hasscrollbar}", (int)eBackgroundRecMenuIT::hasscrollbar); + break; + case eViewElementsRecMenu::scrollbar: + tk->DefineIntToken("{menuwidth}", (int)eScrollbarRecMenuIT::menuwidth); + tk->DefineIntToken("{posy}", (int)eScrollbarRecMenuIT::posy); + tk->DefineIntToken("{totalheight}", (int)eScrollbarRecMenuIT::totalheight); + tk->DefineIntToken("{height}", (int)eScrollbarRecMenuIT::height); + tk->DefineIntToken("{offset}", (int)eScrollbarRecMenuIT::offset); + break; + default: + break; + } +} + +void cRecMenu::DefineTokens(eViewGridsRecMenu vg, skindesignerapi::cTokenContainer *tk) { + tk->DefineIntToken("{info}", (int)eRecMenuIT::info); + tk->DefineIntToken("{lines}", (int)eRecMenuIT::lines); + tk->DefineIntToken("{button}", (int)eRecMenuIT::button); + tk->DefineIntToken("{buttonyesno}", (int)eRecMenuIT::buttonyesno); + tk->DefineIntToken("{yes}", (int)eRecMenuIT::yes); + tk->DefineIntToken("{intselector}", (int)eRecMenuIT::intselector); + tk->DefineIntToken("{intvalue}", (int)eRecMenuIT::value); + tk->DefineIntToken("{boolselector}", (int)eRecMenuIT::boolselector); + tk->DefineIntToken("{stringselector}", (int)eRecMenuIT::stringselector); + tk->DefineIntToken("{textinput}", (int)eRecMenuIT::textinput); + tk->DefineIntToken("{editmode}", (int)eRecMenuIT::editmode); + tk->DefineIntToken("{timeselector}", (int)eRecMenuIT::timeselector); + tk->DefineIntToken("{dayselector}", (int)eRecMenuIT::dayselector); + tk->DefineIntToken("{channelselector}", (int)eRecMenuIT::channelselector); + tk->DefineIntToken("{channelnumber}", (int)eRecMenuIT::channelnumber); + tk->DefineIntToken("{channellogoexisis}", (int)eRecMenuIT::channellogoexisis); + tk->DefineIntToken("{weekdayselector}", (int)eRecMenuIT::weekdayselector); + tk->DefineIntToken("{dayselected}", (int)eRecMenuIT::dayselected); + tk->DefineIntToken("{day0set}", (int)eRecMenuIT::day0set); + tk->DefineIntToken("{day1set}", (int)eRecMenuIT::day1set); + tk->DefineIntToken("{day2set}", (int)eRecMenuIT::day2set); + tk->DefineIntToken("{day3set}", (int)eRecMenuIT::day3set); + tk->DefineIntToken("{day4set}", (int)eRecMenuIT::day4set); + tk->DefineIntToken("{day5set}", (int)eRecMenuIT::day5set); + tk->DefineIntToken("{day6set}", (int)eRecMenuIT::day6set); + tk->DefineIntToken("{directoryselector}", (int)eRecMenuIT::directoryselector); + tk->DefineIntToken("{timerconflictheader}", (int)eRecMenuIT::timerconflictheader); + tk->DefineIntToken("{overlapstartpercent}", (int)eRecMenuIT::overlapstartpercent); + tk->DefineIntToken("{overlapwidthpercent}", (int)eRecMenuIT::overlapwidthpercent); + tk->DefineIntToken("{timerconflict}", (int)eRecMenuIT::timerconflict); + tk->DefineIntToken("{infoactive}", (int)eRecMenuIT::infoactive); + tk->DefineIntToken("{deleteactive}", (int)eRecMenuIT::deleteactive); + tk->DefineIntToken("{editactive}", (int)eRecMenuIT::editactive); + tk->DefineIntToken("{searchactive}", (int)eRecMenuIT::searchactive); + tk->DefineIntToken("{timerstartpercent}", (int)eRecMenuIT::timerstartpercent); + tk->DefineIntToken("{timerwidthpercent}", (int)eRecMenuIT::timerwidthpercent); + tk->DefineIntToken("{event}", (int)eRecMenuIT::event); + tk->DefineIntToken("{hastimer}", (int)eRecMenuIT::hastimer); + tk->DefineIntToken("{recording}", (int)eRecMenuIT::recording); + tk->DefineIntToken("{recduration}", (int)eRecMenuIT::recduration); + tk->DefineIntToken("{searchtimer}", (int)eRecMenuIT::searchtimer); + tk->DefineIntToken("{timeractive}", (int)eRecMenuIT::timeractive); + tk->DefineIntToken("{activetimers}", (int)eRecMenuIT::activetimers); + tk->DefineIntToken("{recordingsdone}", (int)eRecMenuIT::recordingsdone); + tk->DefineIntToken("{timelineheader}", (int)eRecMenuIT::timelineheader); + tk->DefineIntToken("{timerset}", (int)eRecMenuIT::timerset); + tk->DefineIntToken("{channeltransponder}", (int)eRecMenuIT::channeltransponder); + tk->DefineIntToken("{timelinetimer}", (int)eRecMenuIT::timelinetimer); + tk->DefineIntToken("{timerstart}", (int)eRecMenuIT::timerstart); + tk->DefineIntToken("{timerwidth}", (int)eRecMenuIT::timerwidth); + tk->DefineIntToken("{favorite}", (int)eRecMenuIT::favorite); + tk->DefineStringToken("{line1}", (int)eRecMenuST::line1); + tk->DefineStringToken("{line2}", (int)eRecMenuST::line2); + tk->DefineStringToken("{line3}", (int)eRecMenuST::line3); + tk->DefineStringToken("{line4}", (int)eRecMenuST::line4); + tk->DefineStringToken("{stringvalue}", (int)eRecMenuST::value); + tk->DefineStringToken("{buttontext}", (int)eRecMenuST::buttontext); + tk->DefineStringToken("{textyes}", (int)eRecMenuST::textyes); + tk->DefineStringToken("{textno}", (int)eRecMenuST::textno); + tk->DefineStringToken("{text}", (int)eRecMenuST::text); + tk->DefineStringToken("{channelname}", (int)eRecMenuST::channelname); + tk->DefineStringToken("{channelid}", (int)eRecMenuST::channelid); + tk->DefineStringToken("{transponder}", (int)eRecMenuST::transponder); + tk->DefineStringToken("{day0abbr}", (int)eRecMenuST::day0abbr); + tk->DefineStringToken("{day1abbr}", (int)eRecMenuST::day1abbr); + tk->DefineStringToken("{day2abbr}", (int)eRecMenuST::day2abbr); + tk->DefineStringToken("{day3abbr}", (int)eRecMenuST::day3abbr); + tk->DefineStringToken("{day4abbr}", (int)eRecMenuST::day4abbr); + tk->DefineStringToken("{day5abbr}", (int)eRecMenuST::day5abbr); + tk->DefineStringToken("{day6abbr}", (int)eRecMenuST::day6abbr); + tk->DefineStringToken("{folder}", (int)eRecMenuST::folder); + tk->DefineStringToken("{conflictstart}", (int)eRecMenuST::conflictstart); + tk->DefineStringToken("{conflictstop}", (int)eRecMenuST::conflictstop); + tk->DefineStringToken("{overlapstart}", (int)eRecMenuST::overlapstart); + tk->DefineStringToken("{overlapstop}", (int)eRecMenuST::overlapstop); + tk->DefineStringToken("{timertitle}", (int)eRecMenuST::timertitle); + tk->DefineStringToken("{starttime}", (int)eRecMenuST::starttime); + tk->DefineStringToken("{stoptime}", (int)eRecMenuST::stoptime); + tk->DefineStringToken("{date}", (int)eRecMenuST::date); + tk->DefineStringToken("{weekday}", (int)eRecMenuST::weekday); + tk->DefineStringToken("{title}", (int)eRecMenuST::title); + tk->DefineStringToken("{shorttext}", (int)eRecMenuST::shorttext); + tk->DefineStringToken("{recname}", (int)eRecMenuST::recname); + tk->DefineStringToken("{recstarttime}", (int)eRecMenuST::recstarttime); + tk->DefineStringToken("{recdate}", (int)eRecMenuST::recdate); + tk->DefineStringToken("{searchstring}", (int)eRecMenuST::searchstring); + tk->DefineStringToken("{timerstart}", (int)eRecMenuST::timerstart); + tk->DefineStringToken("{timerstop}", (int)eRecMenuST::timerstop); + tk->DefineStringToken("{eventtitle}", (int)eRecMenuST::eventtitle); + tk->DefineStringToken("{eventshorttext}", (int)eRecMenuST::eventshorttext); + tk->DefineStringToken("{eventstart}", (int)eRecMenuST::eventstart); + tk->DefineStringToken("{eventstop}", (int)eRecMenuST::eventstop); + tk->DefineStringToken("{favdesc}", (int)eRecMenuST::favdesc); +} + +/******************************************************************** +* Protected Functions +********************************************************************/ +void cRecMenu::AddMenuItem(cRecMenuItem *item, bool inFront) { + if (!inFront) + menuItems.Add(item); + else + menuItems.Ins(item); +} + +void cRecMenu::AddHeader(cRecMenuItem *header) { + this->header = header; + maxMenuHeight -= header->GetHeight(); +} + +void cRecMenu::AddFooter(cRecMenuItem *footer) { + this->footer = footer; + maxMenuHeight -= footer->GetHeight(); +} + +int cRecMenu::GetNumActive(void) { + int num = 0; + for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { + if (current == active) { + return num; + } + num++; + } + return 0; +} + +bool cRecMenu::ScrollUp(bool retry) { + if (active == start) { + bool scrolled = SeekBack(false); + if (scrolled && scrolling) DrawScrollbar(); + } + if (footer && active == footer) { + recMenuGrid->SetCurrent(footer->Id(), false); + footer->SetInactive(); + active = stop; + active->SetActive(); + return true; + } + cRecMenuItem *prev = (cRecMenuItem*)active->Prev(); + while (prev && !prev->Selectable()) { + prev = (cRecMenuItem*)prev->Prev(); + } + if (prev) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = prev; + active->SetActive(); + return true; + } else { + SeekBack(false); + if (!retry) + ScrollUp(true); + } + return false; +} + +bool cRecMenu::ScrollDown(bool retry) { + if (active == stop || retry) { + bool scrolled = SeekForward(false); + if (scrolled && scrolling) DrawScrollbar(); + } + cRecMenuItem *next = (cRecMenuItem*)active->Next(); + while (next && !next->Selectable()) { + if (next == stop) { + return ScrollDown(true); + } + next = (cRecMenuItem*)next->Next(); + } + if (next) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = next; + active->SetActive(); + return true; + } else { + SeekForward(false); + if (!retry) + return ScrollDown(true); + } + if (footer && active != footer) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = footer; + active->SetActive(); + return true; + } + return false; +} + +bool cRecMenu::PageUp(void) { + bool scrolled = SeekBack(true); + if (scrolled && scrolling) DrawScrollbar(); + if (!scrolled) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = start; + active->SetActive(); + return true; + } + if (!active) { + active = stop; + active->SetActive(); + } + return scrolled; +} + +bool cRecMenu::PageDown(void) { + bool scrolled = SeekForward(true); + if (scrolled && scrolling) DrawScrollbar(); + if (!scrolled) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = stop; + active->SetActive(); + return true; + } + if (!active) { + active = start; + active->SetActive(); + } + return scrolled; +} + +void cRecMenu::ClearMenuItems(bool deleteItems) { + if (deleteItems) { + menuItems.Clear(); + active = NULL; + } else { + for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { + current->SetNew(); + } + } + itemCount = 0; + back->Clear(); + scrollBar->Clear(); + recMenuGrid->Clear(); + if (header) + header->SetNew(); + if (footer) + footer->SetNew(); + if (active) + active->SetInactive(); + active = NULL; +} + +void cRecMenu::InitMenuItems(void) { + if (menuItems.Count() == 0) + return; + scrolling = false; + menuHeight = 0; + start = menuItems.First(); + cRecMenuItem *current = start; + while (current) { + int itemHeight = current->GetHeight(); + if (menuHeight + itemHeight > maxMenuHeight) { + scrolling = true; + break; + } + if (current->Active()) + active = current; + itemCount++; + stop = current; + menuHeight += itemHeight; + current = menuItems.Next(current); + } + DrawBackground(); + Flush(); + if (scrolling) { + DrawScrollbar(); + Flush(); + } +} + +void cRecMenu::InitMenuItemsLast(void) { + if (menuItems.Count() == 0) + return; + scrolling = false; + menuHeight = 0; + stop = menuItems.Last(); + active = stop; + active->SetActive(); + cRecMenuItem *current = stop; + while (current) { + int itemHeight = current->GetHeight(); + if (menuHeight + itemHeight > maxMenuHeight) { + scrolling = true; + break; + } + itemCount++; + start = current; + menuHeight += itemHeight; + current = menuItems.Prev(current); + } + DrawBackground(); + Flush(); + if (scrolling) { + DrawScrollbar(); + Flush(); + } +} + +int cRecMenu::GetHeight(void) { + int totalHeight = menuHeight; + if (header) + totalHeight += header->GetHeight(); + if (footer) + totalHeight += footer->GetHeight(); + return totalHeight; +} + +/******************************************************************** +* Private Functions +********************************************************************/ + +bool cRecMenu::SeekForward(bool page) { + int jumpStep = 0; + if (page) + jumpStep = itemCount; + else + jumpStep = itemCount/2; + int jump = 0; + cRecMenuItem *next = (cRecMenuItem*)stop->Next(); + while (next && jump < jumpStep) { + stop = next; + menuHeight += next->GetHeight(); + next = (cRecMenuItem*)next->Next(); + jump++; + } + while (start && menuHeight > maxMenuHeight) { + if (active == start) { + active = NULL; + start->SetInactive(); + } + menuHeight -= start->GetHeight(); + recMenuGrid->Delete(start->Id()); + start->SetNew(); + start = (cRecMenuItem*)start->Next(); + } + if (jump > 0) + return true; + return false; +} + +bool cRecMenu::SeekBack(bool page) { + int jumpStep = 0; + if (page) + jumpStep = itemCount; + else + jumpStep = itemCount/2; + int jump = 0; + cRecMenuItem *prev = (cRecMenuItem*)start->Prev(); + while (prev && jump < jumpStep) { + start = prev; + menuHeight += prev->GetHeight(); + prev = (cRecMenuItem*)prev->Prev(); + jump++; + } + while (stop && menuHeight > maxMenuHeight) { + if (active == stop) { + active = NULL; + stop->SetInactive(); + } + menuHeight -= stop->GetHeight(); + recMenuGrid->Delete(stop->Id()); + stop->SetNew(); + stop = (cRecMenuItem*)stop->Prev(); + } + if (jump > 0) + return true; + return false; +} + +void cRecMenu::SetFirst(void) { + if (!scrolling) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + active = start; + active->SetActive(); + return; + } + ClearMenuItems(false); + menuItems.First()->SetActive(); + InitMenuItems(); +} + +void cRecMenu::SetLast(void) { + if (!scrolling) { + recMenuGrid->SetCurrent(active->Id(), false); + active->SetInactive(); + if (footer) { + active = footer; + } else { + active = stop; + } + active->SetActive(); + return; + } + ClearMenuItems(false); + InitMenuItemsLast(); +} + +void cRecMenu::DrawBackground(void) { + back->Clear(); + back->ClearTokens(); + back->AddIntToken((int)eBackgroundRecMenuIT::menuwidth, menuWidth + 2); + back->AddIntToken((int)eBackgroundRecMenuIT::menuheight, GetHeight() + 2); + back->AddIntToken((int)eBackgroundRecMenuIT::hasscrollbar, scrolling); + back->Display(); +} + +void cRecMenu::DrawScrollbar(void) { + if (menuItems.Count() == 0) + return; + int scrollBarHeight = (double)itemCount / (double)menuItems.Count() * 1000; + int startPos = 0; + for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { + if (start == current) + break; + startPos++; + } + int offset = (double)startPos / (double)menuItems.Count() * 1000; + scrollBar->Clear(); + scrollBar->ClearTokens(); + scrollBar->AddIntToken((int)eScrollbarRecMenuIT::menuwidth, menuWidth + 2); + int y = (100 - GetHeight())/2; + if (header) + y += header->GetHeight(); + + scrollBar->AddIntToken((int)eScrollbarRecMenuIT::posy, y); + scrollBar->AddIntToken((int)eScrollbarRecMenuIT::totalheight, menuHeight); + scrollBar->AddIntToken((int)eScrollbarRecMenuIT::height, scrollBarHeight); + scrollBar->AddIntToken((int)eScrollbarRecMenuIT::offset, offset); + scrollBar->Display(); +} + +void cRecMenu::DrawHeader(void) { + if (!header) + return; + double width = (double)menuWidth / (double)100; + double x = (double)(100 - menuWidth)/(double)200; + int totalHeight = GetHeight(); + double y = (double)((100 - totalHeight) / 2) / (double)100; + + if (header->IsNew()) { + recMenuGrid->ClearTokens(); + header->SetTokens(recMenuGrid); + recMenuGrid->SetGrid(header->Id(), x, y, width, (double)header->GetHeight()/(double)100); + } +} + +void cRecMenu::DrawFooter(void) { + if (!footer) + return; + double width = (double)menuWidth / (double)100; + double x = (double)(100 - menuWidth)/(double)200; + int totalHeight = GetHeight(); + int totalMenuHeight = menuHeight; + if (header) + totalMenuHeight += header->GetHeight(); + double y = (double)((100 - totalHeight) / 2 + totalMenuHeight) / (double)100; + + if (footer->IsNew()) { + recMenuGrid->ClearTokens(); + footer->SetTokens(recMenuGrid); + recMenuGrid->SetGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); + } else { + recMenuGrid->MoveGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); + } + if (footer->Active()) { + active = footer; + recMenuGrid->SetCurrent(footer->Id(), true); + } } \ No newline at end of file diff --git a/recmenu.h b/recmenu.h index 64b35be..c5f1a87 100644 --- a/recmenu.h +++ b/recmenu.h @@ -1,66 +1,66 @@ -#ifndef __TVGUIDE_RECMENU_H -#define __TVGUIDE_RECMENU_H - -#include -#include -#include "definitions.h" -#include "recmenuitem.h" - -// --- cRecMenu ------------------------------------------------------------- - -class cRecMenu { -private: - bool hidden; - int menuWidth; - int menuHeight; - int maxMenuHeight; - skindesignerapi::cOsdView *osdView; - skindesignerapi::cViewElement *back; - skindesignerapi::cViewElement *scrollBar; - skindesignerapi::cViewGrid *recMenuGrid; - cList menuItems; - cRecMenuItem *start; - cRecMenuItem *stop; - int itemCount; - cRecMenuItem *active; - cRecMenuItem *header; - cRecMenuItem *footer; - bool scrolling; - bool SeekForward(bool page); - bool SeekBack(bool page); - void SetFirst(void); - void SetLast(void); - void DrawScrollbar(void); - void DrawHeader(void); - void DrawFooter(void); -protected: - void SetMenuWidth(int width) { menuWidth = width; }; - void AddMenuItem(cRecMenuItem *item, bool inFront = false); - void AddHeader(cRecMenuItem *header); - void AddFooter(cRecMenuItem *footer); - int GetNumActive(void); - cRecMenuItem *GetActive(void) { return active; }; - bool ScrollUp(bool retry); - bool ScrollDown(bool retry); - bool PageUp(void); - bool PageDown(void); - void ClearMenuItems(bool deleteItems); - void InitMenuItems(void); - void InitMenuItemsLast(void); - int GetWidth(void) { return menuWidth; }; - int GetHeight(void); -public: - cRecMenu(void); - virtual ~cRecMenu(void); - void Init(skindesignerapi::cOsdView *osdView); - void Activate(void) { osdView->Activate(); }; - void DrawBackground(void); - void Draw(void); - void Hide(void) { hidden = true; osdView->Deactivate(true); }; - void Show(void) { hidden = false; osdView->Activate(); }; - void Flush(void) { osdView->Display(); }; - virtual eRecMenuState ProcessKey(eKeys Key); - static void DefineTokens(eViewElementsRecMenu ve, skindesignerapi::cTokenContainer *tk); - static void DefineTokens(eViewGridsRecMenu vg, skindesignerapi::cTokenContainer *tk); -}; +#ifndef __TVGUIDE_RECMENU_H +#define __TVGUIDE_RECMENU_H + +#include +#include +#include "definitions.h" +#include "recmenuitem.h" + +// --- cRecMenu ------------------------------------------------------------- + +class cRecMenu { +private: + bool hidden; + int menuWidth; + int menuHeight; + int maxMenuHeight; + skindesignerapi::cOsdView *osdView; + skindesignerapi::cViewElement *back; + skindesignerapi::cViewElement *scrollBar; + skindesignerapi::cViewGrid *recMenuGrid; + cList menuItems; + cRecMenuItem *start; + cRecMenuItem *stop; + int itemCount; + cRecMenuItem *active; + cRecMenuItem *header; + cRecMenuItem *footer; + bool scrolling; + bool SeekForward(bool page); + bool SeekBack(bool page); + void SetFirst(void); + void SetLast(void); + void DrawScrollbar(void); + void DrawHeader(void); + void DrawFooter(void); +protected: + void SetMenuWidth(int width) { menuWidth = width; }; + void AddMenuItem(cRecMenuItem *item, bool inFront = false); + void AddHeader(cRecMenuItem *header); + void AddFooter(cRecMenuItem *footer); + int GetNumActive(void); + cRecMenuItem *GetActive(void) { return active; }; + bool ScrollUp(bool retry); + bool ScrollDown(bool retry); + bool PageUp(void); + bool PageDown(void); + void ClearMenuItems(bool deleteItems); + void InitMenuItems(void); + void InitMenuItemsLast(void); + int GetWidth(void) { return menuWidth; }; + int GetHeight(void); +public: + cRecMenu(void); + virtual ~cRecMenu(void); + void Init(skindesignerapi::cOsdView *osdView); + void Activate(void) { osdView->Activate(); }; + void DrawBackground(void); + void Draw(void); + void Hide(void) { hidden = true; osdView->Deactivate(true); }; + void Show(void) { hidden = false; osdView->Activate(); }; + void Flush(void) { osdView->Display(); }; + virtual eRecMenuState ProcessKey(eKeys Key); + static void DefineTokens(eViewElementsRecMenu ve, skindesignerapi::cTokenContainer *tk); + static void DefineTokens(eViewGridsRecMenu vg, skindesignerapi::cTokenContainer *tk); +}; #endif //__TVGUIDE_RECMENU_H \ No newline at end of file diff --git a/recmenuitem.c b/recmenuitem.c index 81fa2ed..a0dde60 100644 --- a/recmenuitem.c +++ b/recmenuitem.c @@ -1,1566 +1,1593 @@ -#include "recmenuitem.h" -#include "recmenus.h" -#include "config.h" -#include "helpers.h" -#include -#include -#include - -long cRecMenuItem::idCounter; - -// --- cRecMenuItem ------------------------------------------------------------- - -cRecMenuItem::cRecMenuItem(void) { - id = idCounter; - idCounter++; - init = true; - active = false; - selectable = true; - action = rmsNotConsumed; - height = 0; - text = ""; -} - -cRecMenuItem::~cRecMenuItem(void) { -} - -bool cRecMenuItem::IsNew(void) { - if (init) { - init = false; - return true; - } - return false; -} - -// --- cRecMenuItemInfo ------------------------------------------------------- - -cRecMenuItemInfo::cRecMenuItemInfo(string line1, int numLines, string line2, string line3, string line4) { - selectable = false; - this->numLines = numLines; - this->line1 = line1; - this->line2 = line2; - this->line3 = line3; - this->line4 = line4; - if (numLines == 1) - height = 12; - else if (numLines == 2) - height = 16; - else if (numLines == 3) - height = 20; - else if (numLines == 4) - height = 24; - this->active = false; -} - -cRecMenuItemInfo::~cRecMenuItemInfo(void) { -} - -void cRecMenuItemInfo::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::info, 1); - menu->AddIntToken((int)eRecMenuIT::lines, numLines); - menu->AddStringToken((int)eRecMenuST::line1, line1.c_str()); - menu->AddStringToken((int)eRecMenuST::line2, line2.c_str()); - menu->AddStringToken((int)eRecMenuST::line3, line3.c_str()); - menu->AddStringToken((int)eRecMenuST::line4, line4.c_str()); -} - -// --- cRecMenuItemButton ------------------------------------------------------- - -cRecMenuItemButton::cRecMenuItemButton(string text, eRecMenuState action, bool active) { - selectable = true; - height = 8; - this->text = text; - this->action = action; - this->active = active; -} - -cRecMenuItemButton::~cRecMenuItemButton(void) { -} - -void cRecMenuItemButton::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::button, 1); - menu->AddStringToken((int)eRecMenuST::buttontext, text.c_str()); -} - -eRecMenuState cRecMenuItemButton::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kOk: - return action; - break; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemButtonYesNo ------------------------------------------------------- -cRecMenuItemButtonYesNo::cRecMenuItemButtonYesNo(string textYes, - string textNo, - eRecMenuState actionYes, - eRecMenuState actionNo, - bool active) { - height = 8; - selectable = true; - this->textYes = textYes; - this->textNo = textNo; - this->action = actionYes; - this->actionNo = actionNo; - this->active = active; - yesActive = true; -} - -cRecMenuItemButtonYesNo::~cRecMenuItemButtonYesNo(void) { -} - -void cRecMenuItemButtonYesNo::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::buttonyesno, 1); - menu->AddIntToken((int)eRecMenuIT::yes, yesActive); - menu->AddStringToken((int)eRecMenuST::textyes, textYes.c_str()); - menu->AddStringToken((int)eRecMenuST::textno, textNo.c_str()); -} - -eRecMenuState cRecMenuItemButtonYesNo::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - if (!yesActive) { - yesActive = true; - return rmsRefresh; - } else - return rmsNotConsumed; - break; - case kRight: - if (yesActive) { - yesActive = false; - return rmsRefresh; - } else - return rmsNotConsumed; - break; - case kOk: - if (yesActive) - return action; - return actionNo; - break; - default: - break; - } - return rmsNotConsumed; -} - - -// --- cRecMenuItemInt ------------------------------------------------------- -cRecMenuItemInt::cRecMenuItemInt(string text, - int initialVal, - int minVal, - int maxVal, - bool active, - int *callback, - eRecMenuState action) { - - height = 8; - selectable = true; - this->text = text; - this->currentVal = initialVal; - this->minVal = minVal; - this->maxVal = maxVal; - this->active = active; - this->callback = callback; - this->action = action; - fresh = true; -} - -cRecMenuItemInt::~cRecMenuItemInt(void) { -} - -void cRecMenuItemInt::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::intselector, 1); - menu->AddIntToken((int)eRecMenuIT::value, currentVal); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); -} - -eRecMenuState cRecMenuItemInt::ProcessKey(eKeys Key) { - int oldValue = currentVal; - switch (Key & ~k_Repeat) { - case kLeft: - fresh = true; - if (currentVal > minVal) { - currentVal--; - if (callback) - *callback = currentVal; - } - return rmsRefresh; - break; - case kRight: - fresh = true; - if (currentVal < maxVal) { - currentVal++; - if (callback) - *callback = currentVal; - } - return rmsRefresh; - break; - case k0 ... k9: - if (fresh) { - currentVal = 0; - fresh = false; - } - currentVal = currentVal * 10 + (Key - k0); - if (!((currentVal >= minVal) && (currentVal <= maxVal))) - currentVal = oldValue; - if (callback) - *callback = currentVal; - return rmsRefresh; - break; - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemBool ------------------------------------------------------- -cRecMenuItemBool::cRecMenuItemBool(string text, - bool initialVal, - bool active, - bool *callback, - eRecMenuState action) { - height = 8; - selectable = true; - this->text = text; - this->yes = initialVal; - this->active = active; - this->callback = callback; - this->action = action; -} - -cRecMenuItemBool::~cRecMenuItemBool(void) { -} - -void cRecMenuItemBool::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::boolselector, 1); - menu->AddIntToken((int)eRecMenuIT::value, yes); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); -} - -eRecMenuState cRecMenuItemBool::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - case kRight: - yes = !yes; - if (callback) - *callback = yes; - return rmsRefresh; - break; - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemSelect ------------------------------------------------------- -cRecMenuItemSelect::cRecMenuItemSelect(string text, - vector strings, - int initialVal, - bool active, - int *callback, - eRecMenuState action) { - height = 8; - selectable = true; - this->text = text; - this->strings = strings; - numValues = strings.size(); - if ((initialVal < 0) || (initialVal > numValues-1)) - this->currentVal = 0; - else - this->currentVal = initialVal; - this->active = active; - this->callback = callback; - this->action = action; -} - -cRecMenuItemSelect::~cRecMenuItemSelect(void) { -} - -void cRecMenuItemSelect::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::stringselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - menu->AddStringToken((int)eRecMenuST::value, strings[currentVal].c_str()); -} - -eRecMenuState cRecMenuItemSelect::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - currentVal--; - if (currentVal<0) - currentVal = numValues - 1; - if (callback) - *callback = currentVal; - return rmsRefresh; - break; - case kRight: - currentVal = (currentVal+1)%numValues; - if (callback) - *callback = currentVal; - return rmsRefresh; - break; - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemText ------------------------------------------------------- -cRecMenuItemText::cRecMenuItemText(string text, - char *initialVal, - int length, - bool active, - char *callback) { - - height = 16; - selectable = true; - this->text = text; - value = initialVal; - this->active = active; - this->callback = callback; - this->length = length; - allowed = trVDR(FileNameChars); - pos = -1; - offset = 0; - insert = uppercase = false; - newchar = true; - lengthUtf8 = 0; - valueUtf8 = NULL; - allowedUtf8 = NULL; - charMapUtf8 = NULL; - currentCharUtf8 = NULL; - lastKey = kNone; - buffer = ""; -} - -cRecMenuItemText::~cRecMenuItemText(void) { - delete[] valueUtf8; - delete[] allowedUtf8; - delete[] charMapUtf8; -} - -void cRecMenuItemText::EnterEditMode(void) { - if (!valueUtf8) { - valueUtf8 = new uint[length]; - lengthUtf8 = Utf8ToArray(value, valueUtf8, length); - int l = strlen(allowed) + 1; - allowedUtf8 = new uint[l]; - Utf8ToArray(allowed, allowedUtf8, l); - const char *charMap = trVDR("CharMap$ 0\t-.,1#~\\^$[]|()*+?{}/:%@&\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9"); - l = strlen(charMap) + 1; - charMapUtf8 = new uint[l]; - Utf8ToArray(charMap, charMapUtf8, l); - currentCharUtf8 = charMapUtf8; - AdvancePos(); - } -} - -void cRecMenuItemText::LeaveEditMode(bool SaveValue) { - if (valueUtf8) { - if (SaveValue) { - Utf8FromArray(valueUtf8, value, length); - stripspace(value); - if (callback) { - strncpy(callback, value, TEXTINPUTLENGTH); - } - } - lengthUtf8 = 0; - delete[] valueUtf8; - valueUtf8 = NULL; - delete[] allowedUtf8; - allowedUtf8 = NULL; - delete[] charMapUtf8; - charMapUtf8 = NULL; - pos = -1; - offset = 0; - newchar = true; - } -} - -void cRecMenuItemText::AdvancePos(void) { - if (pos < length - 2 && pos < lengthUtf8) { - if (++pos >= lengthUtf8) { - if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ') - pos--; // allow only two blanks at the end - else { - valueUtf8[pos] = ' '; - valueUtf8[pos + 1] = 0; - lengthUtf8++; - } - } - } - newchar = true; - if (!insert && Utf8is(alpha, valueUtf8[pos])) - uppercase = Utf8is(upper, valueUtf8[pos]); -} - -uint cRecMenuItemText::Inc(uint c, bool Up) { - uint *p = IsAllowed(c); - if (!p) - p = allowedUtf8; - if (Up) { - if (!*++p) - p = allowedUtf8; - } else if (--p < allowedUtf8) { - p = allowedUtf8; - while (*p && *(p + 1)) - p++; - } - return *p; -} - -void cRecMenuItemText::Type(uint c) { - if (insert && lengthUtf8 < length - 1) - Insert(); - valueUtf8[pos] = c; - if (pos < length - 2) - pos++; - if (pos >= lengthUtf8) { - valueUtf8[pos] = ' '; - valueUtf8[pos + 1] = 0; - lengthUtf8 = pos + 1; - } -} - -void cRecMenuItemText::Insert(void) { - memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8)); - lengthUtf8++; - valueUtf8[pos] = ' '; -} - -void cRecMenuItemText::Delete(void) { - memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8)); - lengthUtf8--; -} - -uint *cRecMenuItemText::IsAllowed(uint c) { - if (allowedUtf8) { - for (uint *a = allowedUtf8; *a; a++) { - if (c == *a) - return a; - } - } - return NULL; -} - -void cRecMenuItemText::SetText(void) { - if (InEditMode()) { - int textAreaWidth = 800; - if (pos < offset) - offset = pos; - int WidthFromOffset = 0; - int EndPos = lengthUtf8; - for (int i = offset; i < lengthUtf8; i++) { - WidthFromOffset += 20; - if (WidthFromOffset > textAreaWidth) { - if (pos >= i) { - do { - WidthFromOffset -= 20; - offset++; - } while (WidthFromOffset > textAreaWidth && offset < pos); - EndPos = pos + 1; - } else { - EndPos = i; - break; - } - } - } - char buf[1000]; - char *p = buf; - if (offset) - *p++ = '<'; - p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset); - *p++ = '['; - if (insert && newchar) - *p++ = ']'; - p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1); - if (!(insert && newchar)) - *p++ = ']'; - p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1); - if (EndPos != lengthUtf8) - *p++ = '>'; - *p = 0; - buffer = buf; - } else { - buffer = ""; - } -} - -void cRecMenuItemText::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::textinput, 1); - menu->AddIntToken((int)eRecMenuIT::editmode, InEditMode()); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - if (buffer.size() > 0) { - menu->AddStringToken((int)eRecMenuST::value, buffer.c_str()); - } else { - menu->AddStringToken((int)eRecMenuST::value, value); - } -} - -eRecMenuState cRecMenuItemText::ProcessKey(eKeys Key) { - bool consumed = false; - bool SameKey = NORMALKEY(Key) == lastKey; - - if (Key != kNone) { - lastKey = NORMALKEY(Key); - } else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) { - AdvancePos(); - newchar = true; - currentCharUtf8 = NULL; - SetText(); - return rmsRefresh; - } - - switch ((int)Key) { - case kRed: // Switch between upper- and lowercase characters - if (InEditMode()) { - if (!insert || !newchar) { - uppercase = !uppercase; - valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]); - } - consumed = true; - } - break; - case kGreen: // Toggle insert/overwrite modes - if (InEditMode()) { - insert = !insert; - newchar = true; - consumed = true; - } - break; - case kYellow|k_Repeat: - case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor - if (InEditMode()) { - if (lengthUtf8 > 1) { - if (!insert || pos < lengthUtf8 - 1) - Delete(); - else if (insert && pos == lengthUtf8 - 1) - valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position - // reduce position, if we removed the last character - if (pos == lengthUtf8) - pos--; - } else if (lengthUtf8 == 1) - valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank - if (Utf8is(alpha, valueUtf8[pos])) - uppercase = Utf8is(upper, valueUtf8[pos]); - newchar = true; - consumed = true; - } - break; - case kLeft|k_Repeat: - case kLeft: - - if (pos > 0) { - if (!insert || newchar) - pos--; - newchar = true; - if (!insert && Utf8is(alpha, valueUtf8[pos])) - uppercase = Utf8is(upper, valueUtf8[pos]); - } - consumed = true; - break; - case kRight|k_Repeat: - case kRight: - if (InEditMode()) { - AdvancePos(); - } else { - EnterEditMode(); - } - consumed = true; - break; - case kUp|k_Repeat: - case kUp: - case kDown|k_Repeat: - case kDown: - if (InEditMode()) { - if (insert && newchar) { - // create a new character in insert mode - if (lengthUtf8 < length - 1) - Insert(); - } - if (uppercase) - valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp)); - else - valueUtf8[pos] = Inc( valueUtf8[pos], NORMALKEY(Key) == kUp); - newchar = false; - consumed = true; - } - break; - case k0|k_Repeat ... k9|k_Repeat: - case k0 ... k9: { - if (InEditMode()) { - if (Setup.NumberKeysForChars) { - if (!SameKey) { - if (!newchar) - AdvancePos(); - currentCharUtf8 = NULL; - } - if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') { - // find the beginning of the character map entry for Key - int n = NORMALKEY(Key) - k0; - currentCharUtf8 = charMapUtf8; - while (n > 0 && *currentCharUtf8) { - if (*currentCharUtf8++ == '\t') - n--; - } - // find first allowed character - while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) - currentCharUtf8++; - } - if (*currentCharUtf8 && *currentCharUtf8 != '\t') { - if (insert && newchar) { - // create a new character in insert mode - if (lengthUtf8 < length - 1) - Insert(); - } - valueUtf8[pos] = *currentCharUtf8; - if (uppercase) - valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]); - // find next allowed character - do { - currentCharUtf8++; - } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)); - newchar = false; - autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT); - } - } else { - Type('0' + NORMALKEY(Key) - k0); - } - consumed = true; - } - break; } - case kBack: - case kOk: - if (InEditMode()) { - LeaveEditMode(Key == kOk); - } else { - EnterEditMode(); - } - consumed = true; - break; - default: - if (InEditMode() && BASICKEY(Key) == kKbd) { - int c = KEYKBD(Key); - if (c <= 0xFF) { - if (IsAllowed(Utf8to(lower, c))) - Type(c); - else { - switch (c) { - case 0x7F: // backspace - if (pos > 0) { - pos--; - ProcessKey(kYellow); - } - break; - default: ; - } - } - } else { - switch (c) { - case kfHome: pos = 0; break; - case kfEnd: pos = lengthUtf8 - 1; break; - case kfIns: ProcessKey(kGreen); - case kfDel: ProcessKey(kYellow); - default: ; - } - } - consumed = true; - } - break; - } - SetText(); - if (consumed) - return rmsRefresh; - return rmsNotConsumed; -} - -// --- cRecMenuItemTime ------------------------------------------------------- -cRecMenuItemTime::cRecMenuItemTime(string text, - int initialVal, - bool active, - int *callback, - eRecMenuState action) { - height = 8; - selectable = true; - this->text = text; - this->value = initialVal; - hh = value / 100; - mm = value % 100; - pos = 0; - fresh = true; - this->active = active; - this->callback = callback; - this->action = action; -} - -cRecMenuItemTime::~cRecMenuItemTime(void) { -} - -void cRecMenuItemTime::SetTokens(skindesignerapi::cViewGrid *menu) { - char buf[10]; - switch (pos) { - case 1: snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break; - case 2: snprintf(buf, sizeof(buf), "%02d:--", hh); break; - case 3: snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break; - default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); - } - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::timeselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - menu->AddStringToken((int)eRecMenuST::value, buf); -} - -eRecMenuState cRecMenuItemTime::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft|k_Repeat: - case kLeft: { - if (--mm < 0) { - mm = 59; - if (--hh < 0) - hh = 23; - } - fresh = true; - value = hh * 100 + mm; - if (callback) - *callback = value; - return rmsRefresh; - break; } - case kRight|k_Repeat: - case kRight: { - if (++mm > 59) { - mm = 0; - if (++hh > 23) - hh = 0; - } - fresh = true; - value = hh * 100 + mm; - if (callback) - *callback = value; - return rmsRefresh; - break; } - case k0|k_Repeat ... k9|k_Repeat: - case k0 ... k9: { - if (fresh || pos > 3) { - pos = 0; - fresh = false; - } - int n = Key - k0; - switch (pos) { - case 0: - if (n <= 2) { - hh = n * 10; - mm = 0; - pos++; - } - break; - case 1: - if (hh + n <= 23) { - hh += n; - pos++; - } - break; - case 2: - if (n <= 5) { - mm += n * 10; - pos++; - } - break; - case 3: - if (mm + n <= 59) { - mm += n; - pos++; - } - break; - default: ; - } - value = hh * 100 + mm; - if (callback) - *callback = value; - return rmsRefresh; - break; } - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemDay ------------------------------------------------------- -cRecMenuItemDay::cRecMenuItemDay(string text, - time_t initialVal, - bool active, - time_t *callback, - eRecMenuState action) { - - height = 8; - selectable = true; - this->text = text; - this->currentVal = cTimer::SetTime(initialVal, 0); - this->active = active; - this->callback = callback; - this->action = action; -} - -cRecMenuItemDay::~cRecMenuItemDay(void) { -} - -void cRecMenuItemDay::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::dayselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - menu->AddStringToken((int)eRecMenuST::value, *DateString(currentVal)); -} - -eRecMenuState cRecMenuItemDay::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - currentVal -= 60*60*24; - if (callback) - *callback = currentVal; - return rmsRefresh; - break; - case kRight: - currentVal += 60*60*24; - if (callback) - *callback = currentVal; - return rmsRefresh; - break; - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemChannelChooser ------------------------------------------------------- -cRecMenuItemChannelChooser::cRecMenuItemChannelChooser(string text, - cChannel *initialChannel, - bool active, - int *callback, - eRecMenuState action) { - - height = 8; - selectable = true; - this->text = text; - this->channel = initialChannel; - if (initialChannel) - initialChannelSet = true; - else - initialChannelSet = false; - channelNumber = 0; - fresh = true; - this->active = active; - this->callback = callback; - this->action = action; -} - -cRecMenuItemChannelChooser::~cRecMenuItemChannelChooser(void) { -} - -void cRecMenuItemChannelChooser::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::channelselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - if (channel) { - menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); - menu->AddStringToken((int)eRecMenuST::channelname, channel->Name()); - cString channelId = channel->GetChannelID().ToString(); - menu->AddStringToken((int)eRecMenuST::channelid, *channelId); - menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); - } else { - menu->AddIntToken((int)eRecMenuIT::channelnumber, 0); - menu->AddStringToken((int)eRecMenuST::channelname, tr("all Channels")); - menu->AddStringToken((int)eRecMenuST::channelid, ""); - menu->AddIntToken((int)eRecMenuIT::channellogoexisis, false); - } -} - -eRecMenuState cRecMenuItemChannelChooser::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: { - fresh = true; - if (!channel) - return rmsConsumed; - cChannel *prev = channel; - cChannel *firstChannel = Channels.First(); - if(firstChannel->GroupSep()) - firstChannel = Channels.Next(firstChannel); - if (prev == firstChannel) { - if (!initialChannelSet) - channel = NULL; - } else { - while (prev = Channels.Prev(prev)) { - if(!prev->GroupSep()) { - channel = prev; - break; - } - } - } - if (callback) { - if (channel) - *callback = channel->Number(); - else - *callback = 0; - } - return rmsRefresh; - break; } - case kRight: { - fresh = true; - if (!channel) { - channel = Channels.First(); - if(channel->GroupSep()) - channel = Channels.Next(channel); - } else { - cChannel *next = channel; - while (next = Channels.Next(next)) { - if(!next->GroupSep()) { - channel = next; - break; - } - } - } - if (callback) { - if (channel) - *callback = channel->Number(); - else - *callback = 0; - } - return rmsRefresh; - break; } - case k0 ... k9: { - if (fresh) { - channelNumber = 0; - fresh = false; - } - channelNumber = channelNumber * 10 + (Key - k0); - cChannel *chanNew = Channels.GetByNumber(channelNumber); - if (chanNew) { - channel = chanNew; - if (callback) - *callback = channel->Number(); - } - return rmsRefresh; - break; } - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemDayChooser ------------------------------------------------------- -cRecMenuItemDayChooser::cRecMenuItemDayChooser(string text, - int weekdays, - bool active, - int *callback) { - height = 8; - selectable = true; - this->text = text; - if (weekdays < 1) - weekdays *= -1; - this->weekdays = weekdays; - this->active = active; - this->callback = callback; - selectedDay = 0; -} - -cRecMenuItemDayChooser::~cRecMenuItemDayChooser(void) { -} - -void cRecMenuItemDayChooser::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::weekdayselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - menu->AddIntToken((int)eRecMenuIT::dayselected, selectedDay); - - string days = trVDR("MTWTFSS"); - for (unsigned day=0; dayAddStringToken((int)eRecMenuST::day0abbr + day, *strDay); - menu->AddIntToken((int)eRecMenuIT::day0set + day, WeekDaySet(day)); - } -} - -bool cRecMenuItemDayChooser::WeekDaySet(unsigned day) { - return weekdays & (1 << day); -} - -void cRecMenuItemDayChooser::ToggleDay(void) { - bool dayActive = WeekDaySet(selectedDay); - int dayBit = pow(2, selectedDay); - if (dayActive) { - weekdays -= dayBit; - } else { - weekdays += dayBit; - } - if (callback) { - *callback = weekdays; - } -} - -eRecMenuState cRecMenuItemDayChooser::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: { - selectedDay--; - if (selectedDay<0) - selectedDay += 7; - return rmsRefresh; - break; } - case kRight: { - selectedDay = (selectedDay+1)%7; - return rmsRefresh; - break; } - case kOk: - ToggleDay(); - return rmsRefresh; - break; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemSelectDirectory ------------------------------------------------------- -cRecMenuItemSelectDirectory::cRecMenuItemSelectDirectory(string text, - string originalFolder, - bool active, - char *callback, - eRecMenuState action, - bool isSearchTimer) { - - height = 8; - selectable = true; - this->text = text; - this->originalFolder = originalFolder; - this->active = active; - this->callback = callback; - this->action = action; - folders.push_back(tr("root video folder")); - if (isSearchTimer && config.instRecFixedFolder.size() > 0) - folders.push_back(config.instRecFixedFolder); - ReadRecordingDirectories(&folders, NULL, ""); - numValues = folders.size(); - this->currentVal = GetInitial(); -} - -void cRecMenuItemSelectDirectory::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::directoryselector, 1); - menu->AddStringToken((int)eRecMenuST::text, text.c_str()); - menu->AddStringToken((int)eRecMenuST::folder, folders[currentVal].c_str()); -} - -eRecMenuState cRecMenuItemSelectDirectory::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - currentVal--; - if (currentVal<0) - currentVal = numValues - 1; - if (callback) { - SetCallback(); - } - return rmsRefresh; - break; - case kRight: { - currentVal = (currentVal+1)%numValues; - if (callback) { - SetCallback(); - } - return rmsRefresh; - break; } - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -void cRecMenuItemSelectDirectory::SetCallback(void) { - string newFolder = folders[currentVal]; - if (!newFolder.compare(tr("root video folder"))) - newFolder = ""; - strncpy(callback, newFolder.c_str(), TEXTINPUTLENGTH); -} - -int cRecMenuItemSelectDirectory::GetInitial(void) { - if (originalFolder.size() == 0) - return 0; - for (int i=0; i < numValues; i++) { - if (!folders[i].compare(originalFolder)) { - return i; - } - } - return 0; -} - -// --- cRecMenuItemTimerConflictHeader ------------------------------------------------------- -cRecMenuItemTimerConflictHeader::cRecMenuItemTimerConflictHeader(time_t conflictStart, - time_t conflictStop, - time_t overlapStart, - time_t overlapStop) { - height = 10; - selectable = false; - active = false; - this->conflictStart = conflictStart; - this->conflictStop = conflictStop; - this->overlapStart = overlapStart; - this->overlapStop = overlapStop; -} - -cRecMenuItemTimerConflictHeader::~cRecMenuItemTimerConflictHeader(void) { -} - -void cRecMenuItemTimerConflictHeader::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::timerconflictheader, 1); - menu->AddStringToken((int)eRecMenuST::text, tr("Timer Conflict")); - menu->AddStringToken((int)eRecMenuST::conflictstart, *TimeString(conflictStart)); - menu->AddStringToken((int)eRecMenuST::conflictstop, *TimeString(conflictStop)); - menu->AddStringToken((int)eRecMenuST::overlapstart, *TimeString(overlapStart)); - menu->AddStringToken((int)eRecMenuST::overlapstop, *TimeString(overlapStop)); - - int olStart = (double)(overlapStart - conflictStart) / (double)(conflictStop - conflictStart) * 100; - int olWidth = (double)(overlapStop - overlapStart) / (double)(conflictStop - conflictStart) * 100; - menu->AddIntToken((int)eRecMenuIT::overlapstartpercent, olStart); - menu->AddIntToken((int)eRecMenuIT::overlapwidthpercent, olWidth); -} - -// --- cRecMenuItemTimer ------------------------------------------------------- -cRecMenuItemTimer::cRecMenuItemTimer(const cTimer *timer, - eRecMenuState action1, - eRecMenuState action2, - eRecMenuState action3, - eRecMenuState action4, - time_t conflictStart, - time_t conflictStop, - time_t overlapStart, - time_t overlapStop, - bool active) { - height = 12; - selectable = true; - this->timer = timer; - this->action = action1; - this->action2 = action2; - this->action3 = action3; - this->action4 = action4; - iconActive = 0; - this->conflictStart = conflictStart; - this->conflictStop = conflictStop; - this->overlapStart = overlapStart; - this->overlapStop = overlapStop; - this->active = active; -} - -cRecMenuItemTimer::~cRecMenuItemTimer(void) { -} - -void cRecMenuItemTimer::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::timerconflict, 1); - - const cChannel *channel = timer->Channel(); - int channelTransponder = 0; - const char *channelName = NULL; - cString channelId = ""; - if (channel) { - channelTransponder = channel->Transponder(); - channelName = channel->Name() ? channel->Name() : ""; - channelId = channel->GetChannelID().ToString(); - } - menu->AddIntToken((int)eRecMenuIT::channeltransponder, channelTransponder); - menu->AddStringToken((int)eRecMenuST::channelname, channelName); - menu->AddStringToken((int)eRecMenuST::channelid, *channelId); - - const cEvent *event = timer->Event(); - string timerTitle = ""; - if (event && event->Title()) { - timerTitle = event->Title(); - } - menu->AddStringToken((int)eRecMenuST::timertitle, timerTitle.c_str()); - menu->AddStringToken((int)eRecMenuST::starttime, *TimeString(timer->StartTime())); - menu->AddStringToken((int)eRecMenuST::stoptime, *TimeString(timer->StopTime())); - menu->AddStringToken((int)eRecMenuST::date, *ShortDateString(timer->StartTime())); - menu->AddStringToken((int)eRecMenuST::weekday, *WeekDayName(timer->StartTime())); - - menu->AddIntToken((int)eRecMenuIT::infoactive, (iconActive==0)?true:false); - menu->AddIntToken((int)eRecMenuIT::deleteactive, (iconActive==1)?true:false); - menu->AddIntToken((int)eRecMenuIT::editactive, (iconActive==2)?true:false); - menu->AddIntToken((int)eRecMenuIT::searchactive, (iconActive==3)?true:false); - - - int conflictTime = conflictStop - conflictStart; - int timerStart = (double)(timer->StartTime() - conflictStart) / (double)conflictTime * 100; - int timerWidth = (double)(timer->StopTime() - timer->StartTime()) / (double)conflictTime * 100; - int olStart = (double)(overlapStart - conflictStart) / (double)(conflictStop - conflictStart) * 100; - int olWidth = (double)(overlapStop - overlapStart) / (double)(conflictStop - conflictStart) * 100; - menu->AddIntToken((int)eRecMenuIT::timerstartpercent, timerStart); - menu->AddIntToken((int)eRecMenuIT::timerwidthpercent, timerWidth); - menu->AddIntToken((int)eRecMenuIT::overlapstartpercent, olStart); - menu->AddIntToken((int)eRecMenuIT::overlapwidthpercent, olWidth); -} - -eRecMenuState cRecMenuItemTimer::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - if (iconActive > 0) { - iconActive--; - return rmsRefresh; - } else - return rmsNotConsumed; - break; - case kRight: - if (iconActive < 3) { - iconActive++; - return rmsRefresh; - } else - return rmsNotConsumed; - break; - case kOk: - if (iconActive == 0) - return action; - else if (iconActive == 1) - return action2; - else if (iconActive == 2) - return action3; - else if (iconActive == 3) - return action4; - break; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemEvent ------------------------------------------------------- -cRecMenuItemEvent::cRecMenuItemEvent(const cEvent *event, - eRecMenuState action1, - eRecMenuState action2, - bool active) { - height = 8; - selectable = true; - this->event = event; - this->action = action1; - this->action2 = action2; - iconActive = 0; - this->active = active; -} - -cRecMenuItemEvent::~cRecMenuItemEvent(void) { -} - -void cRecMenuItemEvent::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::event, 1); - - const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); - const char *channelName = NULL; - cString channelId = ""; - if (channel) { - channelName = channel->Name(); - channelId = channel->GetChannelID().ToString(); - menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); - } - - menu->AddStringToken((int)eRecMenuST::channelname, channelName); - menu->AddStringToken((int)eRecMenuST::channelid, *channelId); - menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); - menu->AddStringToken((int)eRecMenuST::title, event->Title()); - menu->AddStringToken((int)eRecMenuST::shorttext, event->ShortText()); - menu->AddStringToken((int)eRecMenuST::date, *ShortDateString(event->StartTime())); - menu->AddStringToken((int)eRecMenuST::weekday, *WeekDayName(event->StartTime())); - menu->AddStringToken((int)eRecMenuST::starttime, *TimeString(event->StartTime())); - menu->AddStringToken((int)eRecMenuST::stoptime, *TimeString(event->EndTime())); - menu->AddIntToken((int)eRecMenuIT::hastimer, event->HasTimer()); -} - -eRecMenuState cRecMenuItemEvent::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kOk: - return action; - break; - case kRed: - if (!event->HasTimer()) - return action2; - break; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemRecording ------------------------------------------------------- -cRecMenuItemRecording::cRecMenuItemRecording(cRecording *recording, bool active) { - height = 8; - selectable = true; - this->recording = recording; - this->active = active; -} - -void cRecMenuItemRecording::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::recording, 1); - if (!recording) - return; - const cRecordingInfo *recInfo = recording->Info(); - cChannel *channel = NULL; - if (recInfo) - channel = Channels.GetByChannelID(recInfo->ChannelID()); - string channelName = tr("unknown channel"); - string channelId = ""; - if (channel && channel->Name()) { - channelName = channel->Name(); - channelId = *(channel->GetChannelID().ToString()); - menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); - } - menu->AddStringToken((int)eRecMenuST::channelname, channelName.c_str()); - menu->AddStringToken((int)eRecMenuST::channelid, channelId.c_str()); - menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(channelId)); - - string recName = recording->Name() ? recording->Name() : ""; - string recDate = *ShortDateString(recording->Start()); - string recStartTime = *TimeString(recording->Start()); - int recDuration = recording->LengthInSeconds() / 60; - - menu->AddStringToken((int)eRecMenuST::recname, recName.c_str()); - menu->AddStringToken((int)eRecMenuST::recdate, recDate.c_str()); - menu->AddStringToken((int)eRecMenuST::recstarttime, recStartTime.c_str()); - menu->AddIntToken((int)eRecMenuIT::recduration, recDuration); -} - -// --- cRecMenuItemSearchTimer ------------------------------------------------------- -cRecMenuItemSearchTimer::cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, - eRecMenuState action1, - eRecMenuState action2, - eRecMenuState action3, - bool active) { - height = 8; - this->timer = timer; - this->action = action1; - this->action2 = action2; - this->action3 = action3; - selectable = true; - this->active = active; - iconActive = 0; -} - -cRecMenuItemSearchTimer::~cRecMenuItemSearchTimer(void) { -} - -void cRecMenuItemSearchTimer::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::searchtimer, 1); - menu->AddIntToken((int)eRecMenuIT::timeractive, timer.Active()); - menu->AddStringToken((int)eRecMenuST::searchstring, timer.SearchString().c_str()); - menu->AddIntToken((int)eRecMenuIT::activetimers, timer.GetNumTimers()); - menu->AddIntToken((int)eRecMenuIT::recordingsdone, timer.GetNumRecordings()); - menu->AddIntToken((int)eRecMenuIT::searchactive, (iconActive==0)?true:false); - menu->AddIntToken((int)eRecMenuIT::editactive, (iconActive==1)?true:false); - menu->AddIntToken((int)eRecMenuIT::deleteactive, (iconActive==2)?true:false); -} - -eRecMenuState cRecMenuItemSearchTimer::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kLeft: - if (iconActive > 0) { - iconActive--; - return rmsRefresh; - } - return rmsNotConsumed; - break; - case kRight: { - if (iconActive < 2) { - iconActive++; - return rmsRefresh; - } - return rmsNotConsumed; - break; } - case kOk: - if (iconActive == 0) - return action; - else if (iconActive == 1) - return action2; - else if (iconActive == 2) - return action3; - break; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemTimelineHeader ------------------------------------------------------- -cRecMenuItemTimelineHeader::cRecMenuItemTimelineHeader(time_t day) { - height = 15; - timer = NULL; - this->day = day; - selectable = false; - active = false; -} - -cRecMenuItemTimelineHeader::~cRecMenuItemTimelineHeader(void) { -} - -void cRecMenuItemTimelineHeader::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::timelineheader, 1); - string daydate = *DateString(day); - menu->AddStringToken((int)eRecMenuST::date, daydate.c_str()); - if (!timer) { - menu->AddIntToken((int)eRecMenuIT::timerset, false); - return; - } - menu->AddIntToken((int)eRecMenuIT::timerset, true); - - const cChannel *channel = timer->Channel(); - const char *channelName = NULL; - cString channelId = ""; - int channelNumber = 0; - int transponder = 0; - if (channel) { - channelName = channel->Name(); - channelId = channel->GetChannelID().ToString(); - channelNumber = channel->Number(); - transponder = channel->Transponder(); - } - menu->AddStringToken((int)eRecMenuST::channelname, channelName); - menu->AddStringToken((int)eRecMenuST::channelid, *channelId); - menu->AddIntToken((int)eRecMenuIT::channelnumber, channelNumber); - menu->AddIntToken((int)eRecMenuIT::channeltransponder, transponder); - menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); - - menu->AddStringToken((int)eRecMenuST::timerstart, *TimeString(timer->StartTime())); - menu->AddStringToken((int)eRecMenuST::timerstop, *TimeString(timer->StopTime())); - - const cEvent *event = timer->Event(); - const char *eventTitle = NULL; - const char *eventShortText = ""; - cString eventStart = ""; - cString eventStop = ""; - if (event) { - eventTitle = event->Title(); - eventShortText = event->ShortText(); - eventStart = event->GetTimeString(); - eventStop = event->GetEndTimeString(); - } - menu->AddStringToken((int)eRecMenuST::eventtitle, eventTitle); - menu->AddStringToken((int)eRecMenuST::eventshorttext, eventShortText); - menu->AddStringToken((int)eRecMenuST::eventstart, *eventStart); - menu->AddStringToken((int)eRecMenuST::eventstop, *eventStop); -} - -// --- cRecMenuItemTimelineTimer ------------------------------------------------------- -cRecMenuItemTimelineTimer::cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, bool active) { - height = 8; - this->timer = timer; - this->start = start; - this->stop = stop; - selectable = true; - this->active = active; -} - -cRecMenuItemTimelineTimer::~cRecMenuItemTimelineTimer(void) { -} - -void cRecMenuItemTimelineTimer::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::timelinetimer, 1); - - int secsPerDay = 24*60*60; - time_t timerStart = timer->StartTime() - start; - time_t timerStop = timer->StopTime() - start; - if (timerStart < 0) - timerStart = 0; - if (timerStop > secsPerDay) - timerStop = secsPerDay; - - int percentStart = ((double)timerStart / (double)secsPerDay) * 1000; - int percentWidth = ((double)(timerStop - timerStart) / (double)secsPerDay) * 1000; - menu->AddIntToken((int)eRecMenuIT::timerstart, percentStart); - menu->AddIntToken((int)eRecMenuIT::timerwidth, percentWidth); -} - -cTimer *cRecMenuItemTimelineTimer::GetTimer(void) { - return timer; -} - -eRecMenuState cRecMenuItemTimelineTimer::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kOk: - return rmsTimelineTimerEdit; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemFavorite ------------------------------------------------------- -cRecMenuItemFavorite::cRecMenuItemFavorite(cTVGuideSearchTimer favorite, - eRecMenuState action1, - bool active) { - height = 8; - this->favorite = favorite; - this->action = action1; - selectable = true; - this->active = active; -} - -void cRecMenuItemFavorite::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::favorite, 1); - menu->AddStringToken((int)eRecMenuST::favdesc, favorite.SearchString().c_str()); -} - -eRecMenuState cRecMenuItemFavorite::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - -// --- cRecMenuItemFavoriteStatic ------------------------------------------------------- -cRecMenuItemFavoriteStatic::cRecMenuItemFavoriteStatic(string text, eRecMenuState action, bool active) { - height = 8; - this->text = text; - this->action = action; - selectable = true; - this->active = active; -} - -void cRecMenuItemFavoriteStatic::SetTokens(skindesignerapi::cViewGrid *menu) { - menu->ClearTokens(); - menu->AddIntToken((int)eRecMenuIT::favorite, 1); - menu->AddStringToken((int)eRecMenuST::favdesc, text.c_str()); -} - -eRecMenuState cRecMenuItemFavoriteStatic::ProcessKey(eKeys Key) { - switch (Key & ~k_Repeat) { - case kOk: - return action; - default: - break; - } - return rmsNotConsumed; -} - +#include "recmenuitem.h" +#include "recmenus.h" +#include "config.h" +#include "helpers.h" +#include +#include +#include + +long cRecMenuItem::idCounter; + +// --- cRecMenuItem ------------------------------------------------------------- + +cRecMenuItem::cRecMenuItem(void) { + id = idCounter; + idCounter++; + init = true; + active = false; + selectable = true; + action = rmsNotConsumed; + height = 0; + text = ""; +} + +cRecMenuItem::~cRecMenuItem(void) { +} + +bool cRecMenuItem::IsNew(void) { + if (init) { + init = false; + return true; + } + return false; +} + +// --- cRecMenuItemInfo ------------------------------------------------------- + +cRecMenuItemInfo::cRecMenuItemInfo(string line1, int numLines, string line2, string line3, string line4) { + selectable = false; + this->numLines = numLines; + this->line1 = line1; + this->line2 = line2; + this->line3 = line3; + this->line4 = line4; + if (numLines == 1) + height = 12; + else if (numLines == 2) + height = 16; + else if (numLines == 3) + height = 20; + else if (numLines == 4) + height = 24; + this->active = false; +} + +cRecMenuItemInfo::~cRecMenuItemInfo(void) { +} + +void cRecMenuItemInfo::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::info, 1); + menu->AddIntToken((int)eRecMenuIT::lines, numLines); + menu->AddStringToken((int)eRecMenuST::line1, line1.c_str()); + menu->AddStringToken((int)eRecMenuST::line2, line2.c_str()); + menu->AddStringToken((int)eRecMenuST::line3, line3.c_str()); + menu->AddStringToken((int)eRecMenuST::line4, line4.c_str()); +} + +// --- cRecMenuItemButton ------------------------------------------------------- + +cRecMenuItemButton::cRecMenuItemButton(string text, eRecMenuState action, bool active) { + selectable = true; + height = 8; + this->text = text; + this->action = action; + this->active = active; +} + +cRecMenuItemButton::~cRecMenuItemButton(void) { +} + +void cRecMenuItemButton::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::button, 1); + menu->AddStringToken((int)eRecMenuST::buttontext, text.c_str()); +} + +eRecMenuState cRecMenuItemButton::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return action; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemButtonYesNo ------------------------------------------------------- +cRecMenuItemButtonYesNo::cRecMenuItemButtonYesNo(string textYes, + string textNo, + eRecMenuState actionYes, + eRecMenuState actionNo, + bool active) { + height = 8; + selectable = true; + this->textYes = textYes; + this->textNo = textNo; + this->action = actionYes; + this->actionNo = actionNo; + this->active = active; + yesActive = true; +} + +cRecMenuItemButtonYesNo::~cRecMenuItemButtonYesNo(void) { +} + +void cRecMenuItemButtonYesNo::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::buttonyesno, 1); + menu->AddIntToken((int)eRecMenuIT::yes, yesActive); + menu->AddStringToken((int)eRecMenuST::textyes, textYes.c_str()); + menu->AddStringToken((int)eRecMenuST::textno, textNo.c_str()); +} + +eRecMenuState cRecMenuItemButtonYesNo::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + if (!yesActive) { + yesActive = true; + return rmsRefresh; + } else + return rmsNotConsumed; + break; + case kRight: + if (yesActive) { + yesActive = false; + return rmsRefresh; + } else + return rmsNotConsumed; + break; + case kOk: + if (yesActive) + return action; + return actionNo; + break; + default: + break; + } + return rmsNotConsumed; +} + + +// --- cRecMenuItemInt ------------------------------------------------------- +cRecMenuItemInt::cRecMenuItemInt(string text, + int initialVal, + int minVal, + int maxVal, + bool active, + int *callback, + eRecMenuState action) { + + height = 8; + selectable = true; + this->text = text; + this->currentVal = initialVal; + this->minVal = minVal; + this->maxVal = maxVal; + this->active = active; + this->callback = callback; + this->action = action; + fresh = true; +} + +cRecMenuItemInt::~cRecMenuItemInt(void) { +} + +void cRecMenuItemInt::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::intselector, 1); + menu->AddIntToken((int)eRecMenuIT::value, currentVal); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); +} + +eRecMenuState cRecMenuItemInt::ProcessKey(eKeys Key) { + int oldValue = currentVal; + switch (Key & ~k_Repeat) { + case kLeft: + fresh = true; + if (currentVal > minVal) { + currentVal--; + if (callback) + *callback = currentVal; + } + return rmsRefresh; + break; + case kRight: + fresh = true; + if (currentVal < maxVal) { + currentVal++; + if (callback) + *callback = currentVal; + } + return rmsRefresh; + break; + case k0 ... k9: + if (fresh) { + currentVal = 0; + fresh = false; + } + currentVal = currentVal * 10 + (Key - k0); + if (!((currentVal >= minVal) && (currentVal <= maxVal))) + currentVal = oldValue; + if (callback) + *callback = currentVal; + return rmsRefresh; + break; + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemBool ------------------------------------------------------- +cRecMenuItemBool::cRecMenuItemBool(string text, + bool initialVal, + bool active, + bool *callback, + eRecMenuState action) { + height = 8; + selectable = true; + this->text = text; + this->yes = initialVal; + this->active = active; + this->callback = callback; + this->action = action; +} + +cRecMenuItemBool::~cRecMenuItemBool(void) { +} + +void cRecMenuItemBool::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::boolselector, 1); + menu->AddIntToken((int)eRecMenuIT::value, yes); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); +} + +eRecMenuState cRecMenuItemBool::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + case kRight: + yes = !yes; + if (callback) + *callback = yes; + return rmsRefresh; + break; + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemSelect ------------------------------------------------------- +cRecMenuItemSelect::cRecMenuItemSelect(string text, + vector strings, + int initialVal, + bool active, + int *callback, + eRecMenuState action) { + height = 8; + selectable = true; + this->text = text; + this->strings = strings; + numValues = strings.size(); + if ((initialVal < 0) || (initialVal > numValues-1)) + this->currentVal = 0; + else + this->currentVal = initialVal; + this->active = active; + this->callback = callback; + this->action = action; +} + +cRecMenuItemSelect::~cRecMenuItemSelect(void) { +} + +void cRecMenuItemSelect::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::stringselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + menu->AddStringToken((int)eRecMenuST::value, strings[currentVal].c_str()); +} + +eRecMenuState cRecMenuItemSelect::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + currentVal--; + if (currentVal<0) + currentVal = numValues - 1; + if (callback) + *callback = currentVal; + return rmsRefresh; + break; + case kRight: + currentVal = (currentVal+1)%numValues; + if (callback) + *callback = currentVal; + return rmsRefresh; + break; + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemText ------------------------------------------------------- +cRecMenuItemText::cRecMenuItemText(string text, + char *initialVal, + int length, + bool active, + char *callback) { + + height = 16; + selectable = true; + this->text = text; + value = initialVal; + this->active = active; + this->callback = callback; + this->length = length; + allowed = trVDR(FileNameChars); + pos = -1; + offset = 0; + insert = uppercase = false; + newchar = true; + lengthUtf8 = 0; + valueUtf8 = NULL; + allowedUtf8 = NULL; + charMapUtf8 = NULL; + currentCharUtf8 = NULL; + lastKey = kNone; + buffer = ""; +} + +cRecMenuItemText::~cRecMenuItemText(void) { + delete[] valueUtf8; + delete[] allowedUtf8; + delete[] charMapUtf8; +} + +void cRecMenuItemText::EnterEditMode(void) { + if (!valueUtf8) { + valueUtf8 = new uint[length]; + lengthUtf8 = Utf8ToArray(value, valueUtf8, length); + int l = strlen(allowed) + 1; + allowedUtf8 = new uint[l]; + Utf8ToArray(allowed, allowedUtf8, l); + const char *charMap = trVDR("CharMap$ 0\t-.,1#~\\^$[]|()*+?{}/:%@&\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9"); + l = strlen(charMap) + 1; + charMapUtf8 = new uint[l]; + Utf8ToArray(charMap, charMapUtf8, l); + currentCharUtf8 = charMapUtf8; + AdvancePos(); + } +} + +void cRecMenuItemText::LeaveEditMode(bool SaveValue) { + if (valueUtf8) { + if (SaveValue) { + Utf8FromArray(valueUtf8, value, length); + stripspace(value); + if (callback) { + strncpy(callback, value, TEXTINPUTLENGTH); + } + } + lengthUtf8 = 0; + delete[] valueUtf8; + valueUtf8 = NULL; + delete[] allowedUtf8; + allowedUtf8 = NULL; + delete[] charMapUtf8; + charMapUtf8 = NULL; + pos = -1; + offset = 0; + newchar = true; + } +} + +void cRecMenuItemText::AdvancePos(void) { + if (pos < length - 2 && pos < lengthUtf8) { + if (++pos >= lengthUtf8) { + if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ') + pos--; // allow only two blanks at the end + else { + valueUtf8[pos] = ' '; + valueUtf8[pos + 1] = 0; + lengthUtf8++; + } + } + } + newchar = true; + if (!insert && Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); +} + +uint cRecMenuItemText::Inc(uint c, bool Up) { + uint *p = IsAllowed(c); + if (!p) + p = allowedUtf8; + if (Up) { + if (!*++p) + p = allowedUtf8; + } else if (--p < allowedUtf8) { + p = allowedUtf8; + while (*p && *(p + 1)) + p++; + } + return *p; +} + +void cRecMenuItemText::Type(uint c) { + if (insert && lengthUtf8 < length - 1) + Insert(); + valueUtf8[pos] = c; + if (pos < length - 2) + pos++; + if (pos >= lengthUtf8) { + valueUtf8[pos] = ' '; + valueUtf8[pos + 1] = 0; + lengthUtf8 = pos + 1; + } +} + +void cRecMenuItemText::Insert(void) { + memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8)); + lengthUtf8++; + valueUtf8[pos] = ' '; +} + +void cRecMenuItemText::Delete(void) { + memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8)); + lengthUtf8--; +} + +uint *cRecMenuItemText::IsAllowed(uint c) { + if (allowedUtf8) { + for (uint *a = allowedUtf8; *a; a++) { + if (c == *a) + return a; + } + } + return NULL; +} + +void cRecMenuItemText::SetText(void) { + if (InEditMode()) { + int textAreaWidth = 800; + if (pos < offset) + offset = pos; + int WidthFromOffset = 0; + int EndPos = lengthUtf8; + for (int i = offset; i < lengthUtf8; i++) { + WidthFromOffset += 20; + if (WidthFromOffset > textAreaWidth) { + if (pos >= i) { + do { + WidthFromOffset -= 20; + offset++; + } while (WidthFromOffset > textAreaWidth && offset < pos); + EndPos = pos + 1; + } else { + EndPos = i; + break; + } + } + } + char buf[1000]; + char *p = buf; + if (offset) + *p++ = '<'; + p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset); + *p++ = '['; + if (insert && newchar) + *p++ = ']'; + p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1); + if (!(insert && newchar)) + *p++ = ']'; + p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1); + if (EndPos != lengthUtf8) + *p++ = '>'; + *p = 0; + buffer = buf; + } else { + buffer = ""; + } +} + +void cRecMenuItemText::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::textinput, 1); + menu->AddIntToken((int)eRecMenuIT::editmode, InEditMode()); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + if (buffer.size() > 0) { + menu->AddStringToken((int)eRecMenuST::value, buffer.c_str()); + } else { + menu->AddStringToken((int)eRecMenuST::value, value); + } +} + +eRecMenuState cRecMenuItemText::ProcessKey(eKeys Key) { + bool consumed = false; + bool SameKey = NORMALKEY(Key) == lastKey; + + if (Key != kNone) { + lastKey = NORMALKEY(Key); + } else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) { + AdvancePos(); + newchar = true; + currentCharUtf8 = NULL; + SetText(); + return rmsRefresh; + } + + switch ((int)Key) { + case kRed: // Switch between upper- and lowercase characters + if (InEditMode()) { + if (!insert || !newchar) { + uppercase = !uppercase; + valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]); + } + consumed = true; + } + break; + case kGreen: // Toggle insert/overwrite modes + if (InEditMode()) { + insert = !insert; + newchar = true; + consumed = true; + } + break; + case kYellow|k_Repeat: + case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor + if (InEditMode()) { + if (lengthUtf8 > 1) { + if (!insert || pos < lengthUtf8 - 1) + Delete(); + else if (insert && pos == lengthUtf8 - 1) + valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position + // reduce position, if we removed the last character + if (pos == lengthUtf8) + pos--; + } else if (lengthUtf8 == 1) + valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank + if (Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); + newchar = true; + consumed = true; + } + break; + case kLeft|k_Repeat: + case kLeft: + + if (pos > 0) { + if (!insert || newchar) + pos--; + newchar = true; + if (!insert && Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); + } + consumed = true; + break; + case kRight|k_Repeat: + case kRight: + if (InEditMode()) { + AdvancePos(); + } else { + EnterEditMode(); + } + consumed = true; + break; + case kUp|k_Repeat: + case kUp: + case kDown|k_Repeat: + case kDown: + if (InEditMode()) { + if (insert && newchar) { + // create a new character in insert mode + if (lengthUtf8 < length - 1) + Insert(); + } + if (uppercase) + valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp)); + else + valueUtf8[pos] = Inc( valueUtf8[pos], NORMALKEY(Key) == kUp); + newchar = false; + consumed = true; + } + break; + case k0|k_Repeat ... k9|k_Repeat: + case k0 ... k9: { + if (InEditMode()) { + if (Setup.NumberKeysForChars) { + if (!SameKey) { + if (!newchar) + AdvancePos(); + currentCharUtf8 = NULL; + } + if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') { + // find the beginning of the character map entry for Key + int n = NORMALKEY(Key) - k0; + currentCharUtf8 = charMapUtf8; + while (n > 0 && *currentCharUtf8) { + if (*currentCharUtf8++ == '\t') + n--; + } + // find first allowed character + while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) + currentCharUtf8++; + } + if (*currentCharUtf8 && *currentCharUtf8 != '\t') { + if (insert && newchar) { + // create a new character in insert mode + if (lengthUtf8 < length - 1) + Insert(); + } + valueUtf8[pos] = *currentCharUtf8; + if (uppercase) + valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]); + // find next allowed character + do { + currentCharUtf8++; + } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)); + newchar = false; + autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT); + } + } else { + Type('0' + NORMALKEY(Key) - k0); + } + consumed = true; + } + break; } + case kBack: + case kOk: + if (InEditMode()) { + LeaveEditMode(Key == kOk); + } else { + EnterEditMode(); + } + consumed = true; + break; + default: + if (InEditMode() && BASICKEY(Key) == kKbd) { + int c = KEYKBD(Key); + if (c <= 0xFF) { + if (IsAllowed(Utf8to(lower, c))) + Type(c); + else { + switch (c) { + case 0x7F: // backspace + if (pos > 0) { + pos--; + ProcessKey(kYellow); + } + break; + default: ; + } + } + } else { + switch (c) { + case kfHome: pos = 0; break; + case kfEnd: pos = lengthUtf8 - 1; break; + case kfIns: ProcessKey(kGreen); + case kfDel: ProcessKey(kYellow); + default: ; + } + } + consumed = true; + } + break; + } + SetText(); + if (consumed) + return rmsRefresh; + return rmsNotConsumed; +} + +// --- cRecMenuItemTime ------------------------------------------------------- +cRecMenuItemTime::cRecMenuItemTime(string text, + int initialVal, + bool active, + int *callback, + eRecMenuState action) { + height = 8; + selectable = true; + this->text = text; + this->value = initialVal; + hh = value / 100; + mm = value % 100; + pos = 0; + fresh = true; + this->active = active; + this->callback = callback; + this->action = action; +} + +cRecMenuItemTime::~cRecMenuItemTime(void) { +} + +void cRecMenuItemTime::SetTokens(skindesignerapi::cViewGrid *menu) { + char buf[10]; + switch (pos) { + case 1: snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break; + case 2: snprintf(buf, sizeof(buf), "%02d:--", hh); break; + case 3: snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break; + default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); + } + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::timeselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + menu->AddStringToken((int)eRecMenuST::value, buf); +} + +eRecMenuState cRecMenuItemTime::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft|k_Repeat: + case kLeft: { + if (--mm < 0) { + mm = 59; + if (--hh < 0) + hh = 23; + } + fresh = true; + value = hh * 100 + mm; + if (callback) + *callback = value; + return rmsRefresh; + break; } + case kRight|k_Repeat: + case kRight: { + if (++mm > 59) { + mm = 0; + if (++hh > 23) + hh = 0; + } + fresh = true; + value = hh * 100 + mm; + if (callback) + *callback = value; + return rmsRefresh; + break; } + case k0|k_Repeat ... k9|k_Repeat: + case k0 ... k9: { + if (fresh || pos > 3) { + pos = 0; + fresh = false; + } + int n = Key - k0; + switch (pos) { + case 0: + if (n <= 2) { + hh = n * 10; + mm = 0; + pos++; + } + break; + case 1: + if (hh + n <= 23) { + hh += n; + pos++; + } + break; + case 2: + if (n <= 5) { + mm += n * 10; + pos++; + } + break; + case 3: + if (mm + n <= 59) { + mm += n; + pos++; + } + break; + default: ; + } + value = hh * 100 + mm; + if (callback) + *callback = value; + return rmsRefresh; + break; } + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemDay ------------------------------------------------------- +cRecMenuItemDay::cRecMenuItemDay(string text, + time_t initialVal, + bool active, + time_t *callback, + eRecMenuState action) { + + height = 8; + selectable = true; + this->text = text; + this->currentVal = cTimer::SetTime(initialVal, 0); + this->active = active; + this->callback = callback; + this->action = action; +} + +cRecMenuItemDay::~cRecMenuItemDay(void) { +} + +void cRecMenuItemDay::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::dayselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + menu->AddStringToken((int)eRecMenuST::value, *DateString(currentVal)); +} + +eRecMenuState cRecMenuItemDay::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + currentVal -= 60*60*24; + if (callback) + *callback = currentVal; + return rmsRefresh; + break; + case kRight: + currentVal += 60*60*24; + if (callback) + *callback = currentVal; + return rmsRefresh; + break; + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemChannelChooser ------------------------------------------------------- +cRecMenuItemChannelChooser::cRecMenuItemChannelChooser(string text, + const cChannel *initialChannel, + bool active, + int *callback, + eRecMenuState action) { + + height = 8; + selectable = true; + this->text = text; + this->channel = initialChannel; + if (initialChannel) + initialChannelSet = true; + else + initialChannelSet = false; + channelNumber = 0; + fresh = true; + this->active = active; + this->callback = callback; + this->action = action; +} + +cRecMenuItemChannelChooser::~cRecMenuItemChannelChooser(void) { +} + +void cRecMenuItemChannelChooser::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::channelselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + if (channel) { + menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); + menu->AddStringToken((int)eRecMenuST::channelname, channel->Name()); + cString channelId = channel->GetChannelID().ToString(); + menu->AddStringToken((int)eRecMenuST::channelid, *channelId); + menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); + } else { + menu->AddIntToken((int)eRecMenuIT::channelnumber, 0); + menu->AddStringToken((int)eRecMenuST::channelname, tr("all Channels")); + menu->AddStringToken((int)eRecMenuST::channelid, ""); + menu->AddIntToken((int)eRecMenuIT::channellogoexisis, false); + } +} + +eRecMenuState cRecMenuItemChannelChooser::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: { + fresh = true; + if (!channel) + return rmsConsumed; + const cChannel *prev = channel; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + const cChannel *firstChannel = channels->First(); + if (firstChannel->GroupSep()) + firstChannel = channels->Next(firstChannel); + if (prev == firstChannel) { + if (!initialChannelSet) + channel = NULL; + } else { + while (prev = channels->Prev(prev)) { + if(!prev->GroupSep()) { + channel = prev; + break; + } + } + } + if (callback) { + if (channel) + *callback = channel->Number(); + else + *callback = 0; + } + return rmsRefresh; + break; } + case kRight: { + fresh = true; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + const cChannels* channels = &Channels; +#endif + if (!channel) { + channel = channels->First(); + if(channel->GroupSep()) + channel = channels->Next(channel); + } else { + const cChannel *next = channel; + while (next = channels->Next(next)) { + if(!next->GroupSep()) { + channel = next; + break; + } + } + } + if (callback) { + if (channel) + *callback = channel->Number(); + else + *callback = 0; + } + return rmsRefresh; + break; } + case k0 ... k9: { + if (fresh) { + channelNumber = 0; + fresh = false; + } + channelNumber = channelNumber * 10 + (Key - k0); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *chanNew = Channels->GetByNumber(channelNumber); +#else + const cChannel *chanNew = Channels.GetByNumber(channelNumber); +#endif + if (chanNew) { + channel = chanNew; + if (callback) + *callback = channel->Number(); + } + return rmsRefresh; + break; } + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemDayChooser ------------------------------------------------------- +cRecMenuItemDayChooser::cRecMenuItemDayChooser(string text, + int weekdays, + bool active, + int *callback) { + height = 8; + selectable = true; + this->text = text; + if (weekdays < 1) + weekdays *= -1; + this->weekdays = weekdays; + this->active = active; + this->callback = callback; + selectedDay = 0; +} + +cRecMenuItemDayChooser::~cRecMenuItemDayChooser(void) { +} + +void cRecMenuItemDayChooser::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::weekdayselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + menu->AddIntToken((int)eRecMenuIT::dayselected, selectedDay); + + string days = trVDR("MTWTFSS"); + for (unsigned day=0; dayAddStringToken((int)eRecMenuST::day0abbr + day, *strDay); + menu->AddIntToken((int)eRecMenuIT::day0set + day, WeekDaySet(day)); + } +} + +bool cRecMenuItemDayChooser::WeekDaySet(unsigned day) { + return weekdays & (1 << day); +} + +void cRecMenuItemDayChooser::ToggleDay(void) { + bool dayActive = WeekDaySet(selectedDay); + int dayBit = pow(2, selectedDay); + if (dayActive) { + weekdays -= dayBit; + } else { + weekdays += dayBit; + } + if (callback) { + *callback = weekdays; + } +} + +eRecMenuState cRecMenuItemDayChooser::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: { + selectedDay--; + if (selectedDay<0) + selectedDay += 7; + return rmsRefresh; + break; } + case kRight: { + selectedDay = (selectedDay+1)%7; + return rmsRefresh; + break; } + case kOk: + ToggleDay(); + return rmsRefresh; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemSelectDirectory ------------------------------------------------------- +cRecMenuItemSelectDirectory::cRecMenuItemSelectDirectory(string text, + string originalFolder, + bool active, + char *callback, + eRecMenuState action, + bool isSearchTimer) { + + height = 8; + selectable = true; + this->text = text; + this->originalFolder = originalFolder; + this->active = active; + this->callback = callback; + this->action = action; + folders.push_back(tr("root video folder")); + if (isSearchTimer && config.instRecFixedFolder.size() > 0) + folders.push_back(config.instRecFixedFolder); + ReadRecordingDirectories(&folders, NULL, ""); + numValues = folders.size(); + this->currentVal = GetInitial(); +} + +void cRecMenuItemSelectDirectory::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::directoryselector, 1); + menu->AddStringToken((int)eRecMenuST::text, text.c_str()); + menu->AddStringToken((int)eRecMenuST::folder, folders[currentVal].c_str()); +} + +eRecMenuState cRecMenuItemSelectDirectory::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + currentVal--; + if (currentVal<0) + currentVal = numValues - 1; + if (callback) { + SetCallback(); + } + return rmsRefresh; + break; + case kRight: { + currentVal = (currentVal+1)%numValues; + if (callback) { + SetCallback(); + } + return rmsRefresh; + break; } + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +void cRecMenuItemSelectDirectory::SetCallback(void) { + string newFolder = folders[currentVal]; + if (!newFolder.compare(tr("root video folder"))) + newFolder = ""; + strncpy(callback, newFolder.c_str(), TEXTINPUTLENGTH); +} + +int cRecMenuItemSelectDirectory::GetInitial(void) { + if (originalFolder.size() == 0) + return 0; + for (int i=0; i < numValues; i++) { + if (!folders[i].compare(originalFolder)) { + return i; + } + } + return 0; +} + +// --- cRecMenuItemTimerConflictHeader ------------------------------------------------------- +cRecMenuItemTimerConflictHeader::cRecMenuItemTimerConflictHeader(time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop) { + height = 10; + selectable = false; + active = false; + this->conflictStart = conflictStart; + this->conflictStop = conflictStop; + this->overlapStart = overlapStart; + this->overlapStop = overlapStop; +} + +cRecMenuItemTimerConflictHeader::~cRecMenuItemTimerConflictHeader(void) { +} + +void cRecMenuItemTimerConflictHeader::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::timerconflictheader, 1); + menu->AddStringToken((int)eRecMenuST::text, tr("Timer Conflict")); + menu->AddStringToken((int)eRecMenuST::conflictstart, *TimeString(conflictStart)); + menu->AddStringToken((int)eRecMenuST::conflictstop, *TimeString(conflictStop)); + menu->AddStringToken((int)eRecMenuST::overlapstart, *TimeString(overlapStart)); + menu->AddStringToken((int)eRecMenuST::overlapstop, *TimeString(overlapStop)); + + int olStart = (double)(overlapStart - conflictStart) / (double)(conflictStop - conflictStart) * 100; + int olWidth = (double)(overlapStop - overlapStart) / (double)(conflictStop - conflictStart) * 100; + menu->AddIntToken((int)eRecMenuIT::overlapstartpercent, olStart); + menu->AddIntToken((int)eRecMenuIT::overlapwidthpercent, olWidth); +} + +// --- cRecMenuItemTimer ------------------------------------------------------- +cRecMenuItemTimer::cRecMenuItemTimer(const cTimer *timer, + eRecMenuState action1, + eRecMenuState action2, + eRecMenuState action3, + eRecMenuState action4, + time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop, + bool active) { + height = 12; + selectable = true; + this->timer = timer; + this->action = action1; + this->action2 = action2; + this->action3 = action3; + this->action4 = action4; + iconActive = 0; + this->conflictStart = conflictStart; + this->conflictStop = conflictStop; + this->overlapStart = overlapStart; + this->overlapStop = overlapStop; + this->active = active; +} + +cRecMenuItemTimer::~cRecMenuItemTimer(void) { +} + +void cRecMenuItemTimer::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::timerconflict, 1); + + const cChannel *channel = timer->Channel(); + int channelTransponder = 0; + const char *channelName = NULL; + cString channelId = ""; + if (channel) { + channelTransponder = channel->Transponder(); + channelName = channel->Name() ? channel->Name() : ""; + channelId = channel->GetChannelID().ToString(); + } + menu->AddIntToken((int)eRecMenuIT::channeltransponder, channelTransponder); + menu->AddStringToken((int)eRecMenuST::channelname, channelName); + menu->AddStringToken((int)eRecMenuST::channelid, *channelId); + + const cEvent *event = timer->Event(); + string timerTitle = ""; + if (event && event->Title()) { + timerTitle = event->Title(); + } + menu->AddStringToken((int)eRecMenuST::timertitle, timerTitle.c_str()); + menu->AddStringToken((int)eRecMenuST::starttime, *TimeString(timer->StartTime())); + menu->AddStringToken((int)eRecMenuST::stoptime, *TimeString(timer->StopTime())); + menu->AddStringToken((int)eRecMenuST::date, *ShortDateString(timer->StartTime())); + menu->AddStringToken((int)eRecMenuST::weekday, *WeekDayName(timer->StartTime())); + + menu->AddIntToken((int)eRecMenuIT::infoactive, (iconActive==0)?true:false); + menu->AddIntToken((int)eRecMenuIT::deleteactive, (iconActive==1)?true:false); + menu->AddIntToken((int)eRecMenuIT::editactive, (iconActive==2)?true:false); + menu->AddIntToken((int)eRecMenuIT::searchactive, (iconActive==3)?true:false); + + + int conflictTime = conflictStop - conflictStart; + int timerStart = (double)(timer->StartTime() - conflictStart) / (double)conflictTime * 100; + int timerWidth = (double)(timer->StopTime() - timer->StartTime()) / (double)conflictTime * 100; + int olStart = (double)(overlapStart - conflictStart) / (double)(conflictStop - conflictStart) * 100; + int olWidth = (double)(overlapStop - overlapStart) / (double)(conflictStop - conflictStart) * 100; + menu->AddIntToken((int)eRecMenuIT::timerstartpercent, timerStart); + menu->AddIntToken((int)eRecMenuIT::timerwidthpercent, timerWidth); + menu->AddIntToken((int)eRecMenuIT::overlapstartpercent, olStart); + menu->AddIntToken((int)eRecMenuIT::overlapwidthpercent, olWidth); +} + +eRecMenuState cRecMenuItemTimer::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + if (iconActive > 0) { + iconActive--; + return rmsRefresh; + } else + return rmsNotConsumed; + break; + case kRight: + if (iconActive < 3) { + iconActive++; + return rmsRefresh; + } else + return rmsNotConsumed; + break; + case kOk: + if (iconActive == 0) + return action; + else if (iconActive == 1) + return action2; + else if (iconActive == 2) + return action3; + else if (iconActive == 3) + return action4; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemEvent ------------------------------------------------------- +cRecMenuItemEvent::cRecMenuItemEvent(const cEvent *event, + eRecMenuState action1, + eRecMenuState action2, + bool active) { + height = 8; + selectable = true; + this->event = event; + this->action = action1; + this->action2 = action2; + iconActive = 0; + this->active = active; +} + +cRecMenuItemEvent::~cRecMenuItemEvent(void) { +} + +void cRecMenuItemEvent::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::event, 1); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(event->ChannelID()); +#else + const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); +#endif + const char *channelName = NULL; + cString channelId = ""; + if (channel) { + channelName = channel->Name(); + channelId = channel->GetChannelID().ToString(); + menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); + } + + menu->AddStringToken((int)eRecMenuST::channelname, channelName); + menu->AddStringToken((int)eRecMenuST::channelid, *channelId); + menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); + menu->AddStringToken((int)eRecMenuST::title, event->Title()); + menu->AddStringToken((int)eRecMenuST::shorttext, event->ShortText()); + menu->AddStringToken((int)eRecMenuST::date, *ShortDateString(event->StartTime())); + menu->AddStringToken((int)eRecMenuST::weekday, *WeekDayName(event->StartTime())); + menu->AddStringToken((int)eRecMenuST::starttime, *TimeString(event->StartTime())); + menu->AddStringToken((int)eRecMenuST::stoptime, *TimeString(event->EndTime())); + menu->AddIntToken((int)eRecMenuIT::hastimer, event->HasTimer()); +} + +eRecMenuState cRecMenuItemEvent::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return action; + break; + case kRed: + if (!event->HasTimer()) + return action2; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemRecording ------------------------------------------------------- +cRecMenuItemRecording::cRecMenuItemRecording(const cRecording *recording, bool active) { + height = 8; + selectable = true; + this->recording = recording; + this->active = active; +} + +void cRecMenuItemRecording::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::recording, 1); + if (!recording) + return; + const cRecordingInfo *recInfo = recording->Info(); + const cChannel *channel = NULL; + if (recInfo) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + channel = Channels->GetByChannelID(recInfo->ChannelID()); +#else + channel = Channels.GetByChannelID(recInfo->ChannelID()); +#endif + } + string channelName = tr("unknown channel"); + string channelId = ""; + if (channel && channel->Name()) { + channelName = channel->Name(); + channelId = *(channel->GetChannelID().ToString()); + menu->AddIntToken((int)eRecMenuIT::channelnumber, channel->Number()); + } + menu->AddStringToken((int)eRecMenuST::channelname, channelName.c_str()); + menu->AddStringToken((int)eRecMenuST::channelid, channelId.c_str()); + menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(channelId)); + + string recName = recording->Name() ? recording->Name() : ""; + string recDate = *ShortDateString(recording->Start()); + string recStartTime = *TimeString(recording->Start()); + int recDuration = recording->LengthInSeconds() / 60; + + menu->AddStringToken((int)eRecMenuST::recname, recName.c_str()); + menu->AddStringToken((int)eRecMenuST::recdate, recDate.c_str()); + menu->AddStringToken((int)eRecMenuST::recstarttime, recStartTime.c_str()); + menu->AddIntToken((int)eRecMenuIT::recduration, recDuration); +} + +// --- cRecMenuItemSearchTimer ------------------------------------------------------- +cRecMenuItemSearchTimer::cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, + eRecMenuState action1, + eRecMenuState action2, + eRecMenuState action3, + bool active) { + height = 8; + this->timer = timer; + this->action = action1; + this->action2 = action2; + this->action3 = action3; + selectable = true; + this->active = active; + iconActive = 0; +} + +cRecMenuItemSearchTimer::~cRecMenuItemSearchTimer(void) { +} + +void cRecMenuItemSearchTimer::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::searchtimer, 1); + menu->AddIntToken((int)eRecMenuIT::timeractive, timer.Active()); + menu->AddStringToken((int)eRecMenuST::searchstring, timer.SearchString().c_str()); + menu->AddIntToken((int)eRecMenuIT::activetimers, timer.GetNumTimers()); + menu->AddIntToken((int)eRecMenuIT::recordingsdone, timer.GetNumRecordings()); + menu->AddIntToken((int)eRecMenuIT::searchactive, (iconActive==0)?true:false); + menu->AddIntToken((int)eRecMenuIT::editactive, (iconActive==1)?true:false); + menu->AddIntToken((int)eRecMenuIT::deleteactive, (iconActive==2)?true:false); +} + +eRecMenuState cRecMenuItemSearchTimer::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + if (iconActive > 0) { + iconActive--; + return rmsRefresh; + } + return rmsNotConsumed; + break; + case kRight: { + if (iconActive < 2) { + iconActive++; + return rmsRefresh; + } + return rmsNotConsumed; + break; } + case kOk: + if (iconActive == 0) + return action; + else if (iconActive == 1) + return action2; + else if (iconActive == 2) + return action3; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemTimelineHeader ------------------------------------------------------- +cRecMenuItemTimelineHeader::cRecMenuItemTimelineHeader(time_t day) { + height = 15; + timer = NULL; + this->day = day; + selectable = false; + active = false; +} + +cRecMenuItemTimelineHeader::~cRecMenuItemTimelineHeader(void) { +} + +void cRecMenuItemTimelineHeader::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::timelineheader, 1); + string daydate = *DateString(day); + menu->AddStringToken((int)eRecMenuST::date, daydate.c_str()); + if (!timer) { + menu->AddIntToken((int)eRecMenuIT::timerset, false); + return; + } + menu->AddIntToken((int)eRecMenuIT::timerset, true); + + const cChannel *channel = timer->Channel(); + const char *channelName = NULL; + cString channelId = ""; + int channelNumber = 0; + int transponder = 0; + if (channel) { + channelName = channel->Name(); + channelId = channel->GetChannelID().ToString(); + channelNumber = channel->Number(); + transponder = channel->Transponder(); + } + menu->AddStringToken((int)eRecMenuST::channelname, channelName); + menu->AddStringToken((int)eRecMenuST::channelid, *channelId); + menu->AddIntToken((int)eRecMenuIT::channelnumber, channelNumber); + menu->AddIntToken((int)eRecMenuIT::channeltransponder, transponder); + menu->AddIntToken((int)eRecMenuIT::channellogoexisis, menu->ChannelLogoExists(*channelId)); + + menu->AddStringToken((int)eRecMenuST::timerstart, *TimeString(timer->StartTime())); + menu->AddStringToken((int)eRecMenuST::timerstop, *TimeString(timer->StopTime())); + + const cEvent *event = timer->Event(); + const char *eventTitle = NULL; + const char *eventShortText = ""; + cString eventStart = ""; + cString eventStop = ""; + if (event) { + eventTitle = event->Title(); + eventShortText = event->ShortText(); + eventStart = event->GetTimeString(); + eventStop = event->GetEndTimeString(); + } + menu->AddStringToken((int)eRecMenuST::eventtitle, eventTitle); + menu->AddStringToken((int)eRecMenuST::eventshorttext, eventShortText); + menu->AddStringToken((int)eRecMenuST::eventstart, *eventStart); + menu->AddStringToken((int)eRecMenuST::eventstop, *eventStop); +} + +// --- cRecMenuItemTimelineTimer ------------------------------------------------------- +cRecMenuItemTimelineTimer::cRecMenuItemTimelineTimer(const cTimer *timer, time_t start, time_t stop, bool active) { + height = 8; + this->timer = timer; + this->start = start; + this->stop = stop; + selectable = true; + this->active = active; +} + +cRecMenuItemTimelineTimer::~cRecMenuItemTimelineTimer(void) { +} + +void cRecMenuItemTimelineTimer::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::timelinetimer, 1); + + int secsPerDay = 24*60*60; + time_t timerStart = timer->StartTime() - start; + time_t timerStop = timer->StopTime() - start; + if (timerStart < 0) + timerStart = 0; + if (timerStop > secsPerDay) + timerStop = secsPerDay; + + int percentStart = ((double)timerStart / (double)secsPerDay) * 1000; + int percentWidth = ((double)(timerStop - timerStart) / (double)secsPerDay) * 1000; + menu->AddIntToken((int)eRecMenuIT::timerstart, percentStart); + menu->AddIntToken((int)eRecMenuIT::timerwidth, percentWidth); +} + +const cTimer *cRecMenuItemTimelineTimer::GetTimer(void) { + return timer; +} + +eRecMenuState cRecMenuItemTimelineTimer::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return rmsTimelineTimerEdit; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemFavorite ------------------------------------------------------- +cRecMenuItemFavorite::cRecMenuItemFavorite(cTVGuideSearchTimer favorite, + eRecMenuState action1, + bool active) { + height = 8; + this->favorite = favorite; + this->action = action1; + selectable = true; + this->active = active; +} + +void cRecMenuItemFavorite::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::favorite, 1); + menu->AddStringToken((int)eRecMenuST::favdesc, favorite.SearchString().c_str()); +} + +eRecMenuState cRecMenuItemFavorite::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemFavoriteStatic ------------------------------------------------------- +cRecMenuItemFavoriteStatic::cRecMenuItemFavoriteStatic(string text, eRecMenuState action, bool active) { + height = 8; + this->text = text; + this->action = action; + selectable = true; + this->active = active; +} + +void cRecMenuItemFavoriteStatic::SetTokens(skindesignerapi::cViewGrid *menu) { + menu->ClearTokens(); + menu->AddIntToken((int)eRecMenuIT::favorite, 1); + menu->AddStringToken((int)eRecMenuST::favdesc, text.c_str()); +} + +eRecMenuState cRecMenuItemFavoriteStatic::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return action; + default: + break; + } + return rmsNotConsumed; +} + diff --git a/recmenuitem.h b/recmenuitem.h index 05818b8..b219b43 100644 --- a/recmenuitem.h +++ b/recmenuitem.h @@ -1,496 +1,496 @@ -#ifndef __TVGUIDE_RECMENUITEM_H -#define __TVGUIDE_RECMENUITEM_H - -#define AUTO_ADVANCE_TIMEOUT 1500 - -using namespace std; - -#include -#include -#include -#include -#include -#include "definitions.h" -#include "searchtimer.h" - -enum eRecMenuState { - rmsConsumed, - rmsNotConsumed, - rmsRefresh, - rmsContinue, - rmsClose, - rmsDisabled, - //INSTANT TIMER - rmsInstantRecord, - rmsInstantRecordFolder, - rmsIgnoreTimerConflict, - rmsDeleteTimerConflictMenu, - rmsEditTimerConflictMenu, - rmsSearchRerunsTimerConflictMenu, - rmsSaveTimerConflictMenu, - rmsTimerConflictShowInfo, - rmsDeleteTimer, - rmsDeleteTimerConfirmation, - rmsEditTimer, - rmsSaveTimer, - //SEARCH - rmsSearch, - rmsSearchWithOptions, - rmsSearchPerform, - rmsSearchShowInfo, - rmsSearchRecord, - rmsSearchRecordConfirm, - rmsSearchNothingFoundConfirm, - //SERIES TIMER - rmsSeriesTimer, - rmsSeriesTimerFolder, - rmsSeriesTimerCreate, - //SEARCHTIMER - rmsSearchTimer, - rmsSearchTimerOptions, - rmsSearchTimers, - rmsSearchTimerEdit, - rmsSearchTimerEditAdvanced, - rmsSearchTimerTest, - rmsSearchTimerSave, - rmsSearchTimerCreateWithTemplate, - rmsSearchTimerDeleteConfirm, - rmsSearchTimerDelete, - rmsSearchTimerDeleteWithTimers, - rmsSearchTimerRecord, - //SWITCHTIMER - rmsSwitchTimer, - rmsSwitchTimerCreate, - rmsSwitchTimerDelete, - //RECORDINGS SEARCH - rmsRecordingSearch, - rmsRecordingSearchResult, - //TIMER CONFLICTS - rmsTimerConflict, - rmsTimerConflicts, - rmsTimerConflictIgnoreReruns, - rmsTimerConflictRecordRerun, - //TIMELINE - rmsTimeline, - rmsTimelineTimerEdit, - rmsTimelineTimerSave, - rmsTimelineTimerDelete, - //FAVORITES - rmsFavoritesRecord, - rmsFavoritesNow, - rmsFavoritesNext, - rmsFavoritesUser1, - rmsFavoritesUser2, - rmsFavoritesUser3, - rmsFavoritesUser4, -}; - -// --- cRecMenuItem ------------------------------------------------------------- -class cRecMenuItem : public cListObject { -protected: - static long idCounter; - long id; - bool init; - bool active; - bool selectable; - eRecMenuState action; - //height of item in percent of screen height - int height; - string text; -public: - cRecMenuItem(void); - virtual ~cRecMenuItem(void); - virtual void SetActive(void) { active = true; } - virtual void SetInactive(void) { active = false; } - long Id(void) { return id; }; - bool Selectable(void) { return selectable; } - bool IsNew(void); - void SetNew(void) { init = true; }; - bool Active(void) { return active; } - int GetHeight(void) { return height; }; - string GetText(void) { return text; }; - virtual void SetTokens(skindesignerapi::cViewGrid *menu) {}; - virtual eRecMenuState ProcessKey(eKeys Key) { return rmsNotConsumed; }; -}; - -// --- cRecMenuItemInfo ------------------------------------------------------- -class cRecMenuItemInfo : public cRecMenuItem { -private: - int numLines; - string line1; - string line2; - string line3; - string line4; -public: - cRecMenuItemInfo(string line1, int numLines = 1, string line2 = "", string line3 = "", string line4 = ""); - virtual ~cRecMenuItemInfo(void); - string GetText(void) { return text; }; - void SetTokens(skindesignerapi::cViewGrid *menu); -}; - -// --- cRecMenuItemButton ------------------------------------------------------- -class cRecMenuItemButton : public cRecMenuItem { -private: - string text; -public: - cRecMenuItemButton(string text, eRecMenuState action, bool active); - virtual ~cRecMenuItemButton(void); - string GetText(void) { return text; }; - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemButtonYesNo ------------------------------------------------------- -class cRecMenuItemButtonYesNo : public cRecMenuItem { -private: - string textYes; - string textNo; - eRecMenuState actionNo; - bool yesActive; -public: - cRecMenuItemButtonYesNo(string textYes, - string textNo, - eRecMenuState actionYes, - eRecMenuState actionNo, - bool active); - virtual ~cRecMenuItemButtonYesNo(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemInt ------------------------------------------------------- -class cRecMenuItemInt : public cRecMenuItem { -private: - int currentVal; - int *callback; - int minVal; - int maxVal; - bool fresh; -public: - cRecMenuItemInt(string text, - int initialVal, - int minVal, - int maxVal, - bool active = false, - int *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemInt(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemBool ------------------------------------------------------- -class cRecMenuItemBool : public cRecMenuItem { -private: - bool yes; - bool *callback; -public: - cRecMenuItemBool(string text, - bool initialVal, - bool active = false, - bool *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemBool(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemSelect ------------------------------------------------------- -class cRecMenuItemSelect : public cRecMenuItem { -private: - int currentVal; - int *callback; - vector strings; - int numValues; -public: - cRecMenuItemSelect(string text, - vector strings, - int initialVal, - bool active = false, - int *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemSelect(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemText ------------------------------------------------------- -class cRecMenuItemText : public cRecMenuItem { -private: - char *value; - string buffer; - char *callback; - int length; - const char *allowed; - int pos, offset; - bool insert, newchar, uppercase; - int lengthUtf8; - uint *valueUtf8; - uint *allowedUtf8; - uint *charMapUtf8; - uint *currentCharUtf8; - eKeys lastKey; - cTimeMs autoAdvanceTimeout; - uint *IsAllowed(uint c); - void AdvancePos(void); - uint Inc(uint c, bool Up); - void Type(uint c); - void Insert(void); - void Delete(void); - void EnterEditMode(void); - void LeaveEditMode(bool SaveValue = false); - bool InEditMode(void) { return valueUtf8 != NULL; }; - void SetText(void); -public: - cRecMenuItemText(string title, - char *initialVal, - int length, - bool active = false, - char *callback = NULL); - virtual ~cRecMenuItemText(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemTime ------------------------------------------------------- -class cRecMenuItemTime : public cRecMenuItem { -private: - int value; - int *callback; - int mm; - int hh; - int pos; - bool fresh; -public: - cRecMenuItemTime(string text, - int initialVal, - bool active = false, - int *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemTime(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemDay ------------------------------------------------------- -class cRecMenuItemDay : public cRecMenuItem { -private: - time_t currentVal; - time_t *callback; -public: - cRecMenuItemDay(string text, - time_t initialVal, - bool active = false, - time_t *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemDay(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemChannelChooser ------------------------------------------------------- -class cRecMenuItemChannelChooser : public cRecMenuItem { -private: - cChannel *channel; - int channelNumber; - int *callback; - bool initialChannelSet; - bool fresh; -public: - cRecMenuItemChannelChooser (string text, - cChannel *initialChannel, - bool active = false, - int *callback = NULL, - eRecMenuState action = rmsNotConsumed); - virtual ~cRecMenuItemChannelChooser(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemDayChooser ------------------------------------------------------- -class cRecMenuItemDayChooser : public cRecMenuItem { -private: - int weekdays; - int *callback; - int selectedDay; - void ToggleDay(void); - bool WeekDaySet(unsigned day); -public: - cRecMenuItemDayChooser (string text, - int weekdays, - bool active = false, - int *callback = NULL); - virtual ~cRecMenuItemDayChooser(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemSelectDirectory ------------------------------------------------------- -class cRecMenuItemSelectDirectory : public cRecMenuItem { -private: - string text; - string originalFolder; - vector folders; - int currentVal; - char *callback; - int numValues; - void SetCallback(void); - int GetInitial(void); -public: - cRecMenuItemSelectDirectory(string text, - string originalFolder, - bool active = false, - char *callback = NULL, - eRecMenuState action = rmsNotConsumed, - bool isSearchTimer = false); - virtual ~cRecMenuItemSelectDirectory(void) {}; - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemTimerConflictHeader ------------------------------------------------------- -class cRecMenuItemTimerConflictHeader: public cRecMenuItem { -private: - time_t conflictStart; - time_t conflictStop; - time_t overlapStart; - time_t overlapStop; -public: - cRecMenuItemTimerConflictHeader(time_t conflictStart, - time_t conflictStop, - time_t overlapStart, - time_t overlapStop); - void SetTokens(skindesignerapi::cViewGrid *menu); - virtual ~cRecMenuItemTimerConflictHeader(void); -}; - -// --- cRecMenuItemTimer ------------------------------------------------------- -class cRecMenuItemTimer : public cRecMenuItem { -private: - const cTimer *timer; - eRecMenuState action2; - eRecMenuState action3; - eRecMenuState action4; - int iconActive; - time_t conflictStart; - time_t conflictStop; - time_t overlapStart; - time_t overlapStop; -public: - cRecMenuItemTimer(const cTimer *timer, - eRecMenuState action1, - eRecMenuState action2, - eRecMenuState action3, - eRecMenuState action4, - time_t conflictStart, - time_t conflictStop, - time_t overlapStart, - time_t overlapStop, - bool active); - virtual ~cRecMenuItemTimer(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemEvent ------------------------------------------------------- -class cRecMenuItemEvent : public cRecMenuItem { -private: - const cEvent *event; - eRecMenuState action2; - int iconActive; -public: - cRecMenuItemEvent(const cEvent *event, - eRecMenuState action1, - eRecMenuState action2, - bool active); - virtual ~cRecMenuItemEvent(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); - const cEvent *GetEvent(void) { return event; }; -}; - -// --- cRecMenuItemRecording ------------------------------------------------------- -class cRecMenuItemRecording : public cRecMenuItem { -private: - cRecording *recording; -public: - cRecMenuItemRecording(cRecording *recording, bool active); - virtual ~cRecMenuItemRecording(void) {}; - void SetTokens(skindesignerapi::cViewGrid *menu); -}; - -// --- cRecMenuItemSearchTimer ------------------------------------------------------- -class cRecMenuItemSearchTimer : public cRecMenuItem { -private: - cTVGuideSearchTimer timer; - eRecMenuState action1; - eRecMenuState action2; - eRecMenuState action3; - int iconActive; -public: - cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, - eRecMenuState action1, - eRecMenuState action2, - eRecMenuState action3, - bool active); - virtual ~cRecMenuItemSearchTimer(void); - cTVGuideSearchTimer GetTimer(void) { return timer; }; - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemTimelineHeader ------------------------------------------------------- -class cRecMenuItemTimelineHeader : public cRecMenuItem { -private: - time_t day; - cTimer *timer; -public: - cRecMenuItemTimelineHeader(time_t day); - virtual ~cRecMenuItemTimelineHeader(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - void SetDay(time_t day) { this->day = day; }; - void SetCurrentTimer(cTimer *timer) { this->timer = timer; }; - void UnsetCurrentTimer(void) { timer = NULL; }; -}; - -// --- cRecMenuItemTimelineTimer ------------------------------------------------------- -class cRecMenuItemTimelineTimer : public cRecMenuItem { -private: - cTimer *timer; - time_t start; - time_t stop; -public: - cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, bool active); - virtual ~cRecMenuItemTimelineTimer(void); - void SetTokens(skindesignerapi::cViewGrid *menu); - cTimer *GetTimer(void); - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemFavorite ------------------------------------------------------- -class cRecMenuItemFavorite : public cRecMenuItem { -private: - cTVGuideSearchTimer favorite; - eRecMenuState action1; -public: - cRecMenuItemFavorite(cTVGuideSearchTimer favorite, - eRecMenuState action1, - bool active); - virtual ~cRecMenuItemFavorite(void) {}; - void SetTokens(skindesignerapi::cViewGrid *menu); - cTVGuideSearchTimer GetFavorite(void) { return favorite; }; - eRecMenuState ProcessKey(eKeys Key); -}; - -// --- cRecMenuItemFavoriteStatic ------------------------------------------------------- -class cRecMenuItemFavoriteStatic : public cRecMenuItem { -private: - string text; -public: - cRecMenuItemFavoriteStatic(string text, eRecMenuState action, bool active); - virtual ~cRecMenuItemFavoriteStatic(void) {}; - void SetTokens(skindesignerapi::cViewGrid *menu); - eRecMenuState ProcessKey(eKeys Key); -}; - +#ifndef __TVGUIDE_RECMENUITEM_H +#define __TVGUIDE_RECMENUITEM_H + +#define AUTO_ADVANCE_TIMEOUT 1500 + +using namespace std; + +#include +#include +#include +#include +#include +#include "definitions.h" +#include "searchtimer.h" + +enum eRecMenuState { + rmsConsumed, + rmsNotConsumed, + rmsRefresh, + rmsContinue, + rmsClose, + rmsDisabled, + //INSTANT TIMER + rmsInstantRecord, + rmsInstantRecordFolder, + rmsIgnoreTimerConflict, + rmsDeleteTimerConflictMenu, + rmsEditTimerConflictMenu, + rmsSearchRerunsTimerConflictMenu, + rmsSaveTimerConflictMenu, + rmsTimerConflictShowInfo, + rmsDeleteTimer, + rmsDeleteTimerConfirmation, + rmsEditTimer, + rmsSaveTimer, + //SEARCH + rmsSearch, + rmsSearchWithOptions, + rmsSearchPerform, + rmsSearchShowInfo, + rmsSearchRecord, + rmsSearchRecordConfirm, + rmsSearchNothingFoundConfirm, + //SERIES TIMER + rmsSeriesTimer, + rmsSeriesTimerFolder, + rmsSeriesTimerCreate, + //SEARCHTIMER + rmsSearchTimer, + rmsSearchTimerOptions, + rmsSearchTimers, + rmsSearchTimerEdit, + rmsSearchTimerEditAdvanced, + rmsSearchTimerTest, + rmsSearchTimerSave, + rmsSearchTimerCreateWithTemplate, + rmsSearchTimerDeleteConfirm, + rmsSearchTimerDelete, + rmsSearchTimerDeleteWithTimers, + rmsSearchTimerRecord, + //SWITCHTIMER + rmsSwitchTimer, + rmsSwitchTimerCreate, + rmsSwitchTimerDelete, + //RECORDINGS SEARCH + rmsRecordingSearch, + rmsRecordingSearchResult, + //TIMER CONFLICTS + rmsTimerConflict, + rmsTimerConflicts, + rmsTimerConflictIgnoreReruns, + rmsTimerConflictRecordRerun, + //TIMELINE + rmsTimeline, + rmsTimelineTimerEdit, + rmsTimelineTimerSave, + rmsTimelineTimerDelete, + //FAVORITES + rmsFavoritesRecord, + rmsFavoritesNow, + rmsFavoritesNext, + rmsFavoritesUser1, + rmsFavoritesUser2, + rmsFavoritesUser3, + rmsFavoritesUser4, +}; + +// --- cRecMenuItem ------------------------------------------------------------- +class cRecMenuItem : public cListObject { +protected: + static long idCounter; + long id; + bool init; + bool active; + bool selectable; + eRecMenuState action; + //height of item in percent of screen height + int height; + string text; +public: + cRecMenuItem(void); + virtual ~cRecMenuItem(void); + virtual void SetActive(void) { active = true; } + virtual void SetInactive(void) { active = false; } + long Id(void) { return id; }; + bool Selectable(void) { return selectable; } + bool IsNew(void); + void SetNew(void) { init = true; }; + bool Active(void) { return active; } + int GetHeight(void) { return height; }; + string GetText(void) { return text; }; + virtual void SetTokens(skindesignerapi::cViewGrid *menu) {}; + virtual eRecMenuState ProcessKey(eKeys Key) { return rmsNotConsumed; }; +}; + +// --- cRecMenuItemInfo ------------------------------------------------------- +class cRecMenuItemInfo : public cRecMenuItem { +private: + int numLines; + string line1; + string line2; + string line3; + string line4; +public: + cRecMenuItemInfo(string line1, int numLines = 1, string line2 = "", string line3 = "", string line4 = ""); + virtual ~cRecMenuItemInfo(void); + string GetText(void) { return text; }; + void SetTokens(skindesignerapi::cViewGrid *menu); +}; + +// --- cRecMenuItemButton ------------------------------------------------------- +class cRecMenuItemButton : public cRecMenuItem { +private: + string text; +public: + cRecMenuItemButton(string text, eRecMenuState action, bool active); + virtual ~cRecMenuItemButton(void); + string GetText(void) { return text; }; + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemButtonYesNo ------------------------------------------------------- +class cRecMenuItemButtonYesNo : public cRecMenuItem { +private: + string textYes; + string textNo; + eRecMenuState actionNo; + bool yesActive; +public: + cRecMenuItemButtonYesNo(string textYes, + string textNo, + eRecMenuState actionYes, + eRecMenuState actionNo, + bool active); + virtual ~cRecMenuItemButtonYesNo(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemInt ------------------------------------------------------- +class cRecMenuItemInt : public cRecMenuItem { +private: + int currentVal; + int *callback; + int minVal; + int maxVal; + bool fresh; +public: + cRecMenuItemInt(string text, + int initialVal, + int minVal, + int maxVal, + bool active = false, + int *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemInt(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemBool ------------------------------------------------------- +class cRecMenuItemBool : public cRecMenuItem { +private: + bool yes; + bool *callback; +public: + cRecMenuItemBool(string text, + bool initialVal, + bool active = false, + bool *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemBool(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemSelect ------------------------------------------------------- +class cRecMenuItemSelect : public cRecMenuItem { +private: + int currentVal; + int *callback; + vector strings; + int numValues; +public: + cRecMenuItemSelect(string text, + vector strings, + int initialVal, + bool active = false, + int *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemSelect(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemText ------------------------------------------------------- +class cRecMenuItemText : public cRecMenuItem { +private: + char *value; + string buffer; + char *callback; + int length; + const char *allowed; + int pos, offset; + bool insert, newchar, uppercase; + int lengthUtf8; + uint *valueUtf8; + uint *allowedUtf8; + uint *charMapUtf8; + uint *currentCharUtf8; + eKeys lastKey; + cTimeMs autoAdvanceTimeout; + uint *IsAllowed(uint c); + void AdvancePos(void); + uint Inc(uint c, bool Up); + void Type(uint c); + void Insert(void); + void Delete(void); + void EnterEditMode(void); + void LeaveEditMode(bool SaveValue = false); + bool InEditMode(void) { return valueUtf8 != NULL; }; + void SetText(void); +public: + cRecMenuItemText(string title, + char *initialVal, + int length, + bool active = false, + char *callback = NULL); + virtual ~cRecMenuItemText(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemTime ------------------------------------------------------- +class cRecMenuItemTime : public cRecMenuItem { +private: + int value; + int *callback; + int mm; + int hh; + int pos; + bool fresh; +public: + cRecMenuItemTime(string text, + int initialVal, + bool active = false, + int *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemTime(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemDay ------------------------------------------------------- +class cRecMenuItemDay : public cRecMenuItem { +private: + time_t currentVal; + time_t *callback; +public: + cRecMenuItemDay(string text, + time_t initialVal, + bool active = false, + time_t *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemDay(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemChannelChooser ------------------------------------------------------- +class cRecMenuItemChannelChooser : public cRecMenuItem { +private: + const cChannel *channel; + int channelNumber; + int *callback; + bool initialChannelSet; + bool fresh; +public: + cRecMenuItemChannelChooser (string text, + const cChannel *initialChannel, + bool active = false, + int *callback = NULL, + eRecMenuState action = rmsNotConsumed); + virtual ~cRecMenuItemChannelChooser(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemDayChooser ------------------------------------------------------- +class cRecMenuItemDayChooser : public cRecMenuItem { +private: + int weekdays; + int *callback; + int selectedDay; + void ToggleDay(void); + bool WeekDaySet(unsigned day); +public: + cRecMenuItemDayChooser (string text, + int weekdays, + bool active = false, + int *callback = NULL); + virtual ~cRecMenuItemDayChooser(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemSelectDirectory ------------------------------------------------------- +class cRecMenuItemSelectDirectory : public cRecMenuItem { +private: + string text; + string originalFolder; + vector folders; + int currentVal; + char *callback; + int numValues; + void SetCallback(void); + int GetInitial(void); +public: + cRecMenuItemSelectDirectory(string text, + string originalFolder, + bool active = false, + char *callback = NULL, + eRecMenuState action = rmsNotConsumed, + bool isSearchTimer = false); + virtual ~cRecMenuItemSelectDirectory(void) {}; + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemTimerConflictHeader ------------------------------------------------------- +class cRecMenuItemTimerConflictHeader: public cRecMenuItem { +private: + time_t conflictStart; + time_t conflictStop; + time_t overlapStart; + time_t overlapStop; +public: + cRecMenuItemTimerConflictHeader(time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop); + void SetTokens(skindesignerapi::cViewGrid *menu); + virtual ~cRecMenuItemTimerConflictHeader(void); +}; + +// --- cRecMenuItemTimer ------------------------------------------------------- +class cRecMenuItemTimer : public cRecMenuItem { +private: + const cTimer *timer; + eRecMenuState action2; + eRecMenuState action3; + eRecMenuState action4; + int iconActive; + time_t conflictStart; + time_t conflictStop; + time_t overlapStart; + time_t overlapStop; +public: + cRecMenuItemTimer(const cTimer *timer, + eRecMenuState action1, + eRecMenuState action2, + eRecMenuState action3, + eRecMenuState action4, + time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop, + bool active); + virtual ~cRecMenuItemTimer(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemEvent ------------------------------------------------------- +class cRecMenuItemEvent : public cRecMenuItem { +private: + const cEvent *event; + eRecMenuState action2; + int iconActive; +public: + cRecMenuItemEvent(const cEvent *event, + eRecMenuState action1, + eRecMenuState action2, + bool active); + virtual ~cRecMenuItemEvent(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); + const cEvent *GetEvent(void) { return event; }; +}; + +// --- cRecMenuItemRecording ------------------------------------------------------- +class cRecMenuItemRecording : public cRecMenuItem { +private: + const cRecording *recording; +public: + cRecMenuItemRecording(const cRecording *recording, bool active); + virtual ~cRecMenuItemRecording(void) {}; + void SetTokens(skindesignerapi::cViewGrid *menu); +}; + +// --- cRecMenuItemSearchTimer ------------------------------------------------------- +class cRecMenuItemSearchTimer : public cRecMenuItem { +private: + cTVGuideSearchTimer timer; + eRecMenuState action1; + eRecMenuState action2; + eRecMenuState action3; + int iconActive; +public: + cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, + eRecMenuState action1, + eRecMenuState action2, + eRecMenuState action3, + bool active); + virtual ~cRecMenuItemSearchTimer(void); + cTVGuideSearchTimer GetTimer(void) { return timer; }; + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemTimelineHeader ------------------------------------------------------- +class cRecMenuItemTimelineHeader : public cRecMenuItem { +private: + time_t day; + const cTimer *timer; +public: + cRecMenuItemTimelineHeader(time_t day); + virtual ~cRecMenuItemTimelineHeader(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + void SetDay(time_t day) { this->day = day; }; + void SetCurrentTimer(const cTimer *timer) { this->timer = timer; }; + void UnsetCurrentTimer(void) { timer = NULL; }; +}; + +// --- cRecMenuItemTimelineTimer ------------------------------------------------------- +class cRecMenuItemTimelineTimer : public cRecMenuItem { +private: + const cTimer *timer; + time_t start; + time_t stop; +public: + cRecMenuItemTimelineTimer(const cTimer *timer, time_t start, time_t stop, bool active); + virtual ~cRecMenuItemTimelineTimer(void); + void SetTokens(skindesignerapi::cViewGrid *menu); + const cTimer *GetTimer(void); + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemFavorite ------------------------------------------------------- +class cRecMenuItemFavorite : public cRecMenuItem { +private: + cTVGuideSearchTimer favorite; + eRecMenuState action1; +public: + cRecMenuItemFavorite(cTVGuideSearchTimer favorite, + eRecMenuState action1, + bool active); + virtual ~cRecMenuItemFavorite(void) {}; + void SetTokens(skindesignerapi::cViewGrid *menu); + cTVGuideSearchTimer GetFavorite(void) { return favorite; }; + eRecMenuState ProcessKey(eKeys Key); +}; + +// --- cRecMenuItemFavoriteStatic ------------------------------------------------------- +class cRecMenuItemFavoriteStatic : public cRecMenuItem { +private: + string text; +public: + cRecMenuItemFavoriteStatic(string text, eRecMenuState action, bool active); + virtual ~cRecMenuItemFavoriteStatic(void) {}; + void SetTokens(skindesignerapi::cViewGrid *menu); + eRecMenuState ProcessKey(eKeys Key); +}; + #endif //__TVGUIDE_RECMENUITEM_H \ No newline at end of file diff --git a/recmenus.c b/recmenus.c index d6327bd..76b92b2 100644 --- a/recmenus.c +++ b/recmenus.c @@ -1,1144 +1,1192 @@ -#include -#include -#include -#include "config.h" -#include "services/remotetimers.h" -#include "helpers.h" -#include "recmenus.h" - -// --- cRecMenuMain --------------------------------------------------------- -cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive) { - SetMenuWidth(50); - eRecMenuState action = rmsInstantRecord; - if (!timerActive) { - if (config.instRecFolderMode == eFolderSelect) - action = rmsInstantRecordFolder; - AddMenuItem(new cRecMenuItemButton(tr("Instant Record"), action, true)); - } else { - AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsDeleteTimer, true)); - AddMenuItem(new cRecMenuItemButton(tr("Edit Timer"), rmsEditTimer, false)); - } - - AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false)); - - if (epgSearchAvailable) { - AddMenuItem(new cRecMenuItemButton(tr("Create Search Timer"), rmsSearchTimer, false)); - AddMenuItem(new cRecMenuItemButton(tr("Search Timers"), rmsSearchTimers, false)); - } - - if (config.instRecFolderMode == eFolderSelect) - action = rmsSeriesTimerFolder; - else - action = rmsSeriesTimer; - AddMenuItem(new cRecMenuItemButton(tr("Create Series Timer"), action, false)); - - if (epgSearchAvailable) { - if (!switchTimerActive) { - AddMenuItem(new cRecMenuItemButton(tr("Create Switch Timer"), rmsSwitchTimer, false)); - } else { - AddMenuItem(new cRecMenuItemButton(tr("Delete Switch Timer"), rmsSwitchTimerDelete, false)); - } - AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false)); - } - - if (epgSearchAvailable) { - AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false)); - } - - AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false)); -}; - -/****************************************************************************************** -* Instant Timer Menus -******************************************************************************************/ - -// --- cRecMenuConfirmTimer --------------------------------------------------------- -cRecMenuConfirmTimer::cRecMenuConfirmTimer(const cEvent *event) { - SetMenuWidth(50); - - bool eventHasTimer = false; - if (config.useRemoteTimers && pRemoteTimers) { - RemoteTimers_GetMatch_v1_0 rtMatch; - rtMatch.event = event; - pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); - if (rtMatch.timerMatch == tmFull) { - eventHasTimer = true; - } - } else { - eventHasTimer = event->HasTimer(); - } - - string message; - if (eventHasTimer) { - message = tr("Timer created"); - } else { - message = tr("Timer NOT created"); - } - cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); - string datetime = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); - string eventTitle = event->Title() ? event->Title() : ""; - AddHeader(new cRecMenuItemInfo(message, 4, *channelName, datetime, eventTitle)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuAskFolder --------------------------------------------------------- -cRecMenuAskFolder::cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction) { - SetMenuWidth(80); - this->nextAction = nextAction; - string message = tr("Set Folder for"); - string eventTitle = event->Title() ? event->Title() : ""; - AddHeader(new cRecMenuItemInfo(message, 2, eventTitle)); - AddMenuItem(new cRecMenuItemButton(tr("root video folder"), nextAction, true)); - - ReadRecordingDirectories(&folders, NULL, ""); - int numFolders = folders.size(); - for (int i=0; i < numFolders; i++) { - AddMenuItem(new cRecMenuItemButton(folders[i].c_str(), nextAction, false)); - } -} - -string cRecMenuAskFolder::GetFolder(void) { - std::string folder = ""; - int folderActive = GetNumActive(); - if (folderActive > 0 && folderActive < (int)folders.size() + 1) - folder = folders[folderActive - 1]; - return folder; -} - -// --- cRecMenuConfirmDeleteTimer --------------------------------------------------------- -cRecMenuConfirmDeleteTimer::cRecMenuConfirmDeleteTimer(const cEvent *event) { - SetMenuWidth(50); - string message = tr("Timer deleted"); - cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); - string datetime = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); - string eventTitle = event->Title() ? event->Title() : ""; - - AddHeader(new cRecMenuItemInfo(message, 4, *channelName, datetime, eventTitle)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuAskDeleteTimer --------------------------------------------------------- -cRecMenuAskDeleteTimer::cRecMenuAskDeleteTimer(const cEvent *event) { - SetMenuWidth(50); - string message = tr("Timer"); - cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); - string eventTitle = event->Title() ? event->Title() : ""; - string message2 = tr("still recording - really delete?"); - - AddHeader(new cRecMenuItemInfo(message, 4, *channelName, eventTitle, message2)); - AddMenuItem(new cRecMenuItemButtonYesNo(tr("Yes"), tr("No"), rmsDeleteTimerConfirmation, rmsClose, true)); -} - -// --- cRecMenuTimerConflicts --------------------------------------------------------- -cRecMenuTimerConflicts::cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts) { - SetMenuWidth(80); - int numConflicts = conflicts->NumConflicts(); - - string text; - if (numConflicts == 1) { - text = *cString::sprintf("%s %s %s", tr("One"), tr("Timer Conflict"), tr("detected")); - } else { - text = *cString::sprintf("%d %s %s", conflicts->NumConflicts(), tr("Timer Conflicts"), tr("detected")); - } - AddHeader(new cRecMenuItemInfo(text)); - - for (int i=0; iGetConflict(i); - if (!conflict) - continue; - cString dateTime = DayDateTime(conflict->time); - int numTimers = conflict->timerIDs.size(); - cString textConflict = cString::sprintf("%s: %s (%d %s)", tr("Show conflict"), *dateTime, numTimers, tr("timers involved")); - bool isActive = (i==0)?true:false; - AddMenuItem(new cRecMenuItemButton(*textConflict, rmsTimerConflict, isActive)); - } - - AddFooter(new cRecMenuItemButton(tr("Ignore Conflicts"), rmsClose, false)); -} - -int cRecMenuTimerConflicts::GetTimerConflict(void) { - return GetNumActive(); -} - -// --- cRecMenuTimerConflict --------------------------------------------------------- -cRecMenuTimerConflict::cRecMenuTimerConflict(cTVGuideTimerConflict *conflict) { - SetMenuWidth(95); - this->conflict = conflict; - AddHeader(new cRecMenuItemTimerConflictHeader(conflict->timeStart, - conflict->timeStop, - conflict->overlapStart, - conflict->overlapStop)); - - int i=0; - for(vector::iterator it = conflict->timerIDs.begin(); it != conflict->timerIDs.end(); it++) { - const cTimer *timer = Timers.Get(*it); - if (timer) { - AddMenuItem(new cRecMenuItemTimer(timer, - rmsTimerConflictShowInfo, - rmsDeleteTimerConflictMenu, - rmsEditTimerConflictMenu, - rmsSearchRerunsTimerConflictMenu, - conflict->timeStart, - conflict->timeStop, - conflict->overlapStart, - conflict->overlapStop, - (!i)?true:false)); - i++; - } - } - AddMenuItem(new cRecMenuItemButton(tr("Ignore Conflict"), rmsIgnoreTimerConflict, false)); -} - -int cRecMenuTimerConflict::GetTimerConflictIndex(void) { - return GetNumActive(); -} - -// --- cRecMenuNoTimerConflict --------------------------------------------------------- -cRecMenuNoTimerConflict::cRecMenuNoTimerConflict(void) { - SetMenuWidth(50); - string text = tr("No Timer Conflicts found"); - AddHeader(new cRecMenuItemInfo(text)); - AddMenuItem(new cRecMenuItemButton(tr("Close"), rmsClose, true)); -} - -// --- cRecMenuRerunResults --------------------------------------------------------- -cRecMenuRerunResults::cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns) { - this->reruns = reruns; - this->numReruns = numReruns; - SetMenuWidth(70); - - string message1 = tr("reruns for"); - string message2 = tr("rerun for"); - string message3 = tr("found"); - string line1 = *cString::sprintf("%d %s:", numReruns, (numReruns>1)?(message1.c_str()):(message2.c_str())); - string line2 = *cString::sprintf("\"%s\" %s", original->Title(), message3.c_str()); - - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - - cRecMenuItem *button = new cRecMenuItemButton(tr("Ignore reruns"), rmsTimerConflictIgnoreReruns, false); - AddFooter(button); - - if (reruns && (numReruns > 0)) { - for (int i=0; i(GetActive()); - if (activeItem) - return activeItem->GetEvent(); - return NULL; -} - -// --- cRecMenuNoRerunsFound --------------------------------------------------------- -cRecMenuNoRerunsFound::cRecMenuNoRerunsFound(string searchString) { - SetMenuWidth(50); - string message = tr("No reruns found for Event"); - string eventQuoted = *cString::sprintf("\"%s\"", searchString.c_str()); - - AddHeader(new cRecMenuItemInfo(message, 2, eventQuoted)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuConfirmRerunUsed --------------------------------------------------------- -cRecMenuConfirmRerunUsed::cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace) { - SetMenuWidth(70); - cString channelOrig = Channels.GetByChannelID(original->ChannelID())->Name(); - cString channelReplace = Channels.GetByChannelID(replace->ChannelID())->Name(); - string line1 = *cString::sprintf("%s \"%s\"", tr("Timer for"), original->Title()); - string line2 = *cString::sprintf("%s %s %s", *original->GetDateString(), *original->GetTimeString(), *channelOrig); - string line3 = *cString::sprintf("%s \"%s\"", tr("replaced by rerun"), replace->Title()); - string line4 = *cString::sprintf("%s %s %s", *replace->GetDateString(), *replace->GetTimeString(), *channelReplace); - - AddHeader(new cRecMenuItemInfo(line1, 4, line2, line3, line4)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflicts, true)); -} - -// --- cRecMenuEditTimer --------------------------------------------------------- -cRecMenuEditTimer::cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState) { - SetMenuWidth(70); - if (!timer) - return; - originalTimer = timer; - string title = ""; - string channelName = ""; - if (timer->Event() && timer->Event()->Title()) - title = timer->Event()->Title(); - if (timer->Channel() && timer->Channel()->Name()) - channelName = timer->Channel()->Name(); - cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(tr("Edit Timer"), 3, title, channelName); - AddHeader(infoItem); - - timerActive = false; - if (config.useRemoteTimers && pRemoteTimers) { - RemoteTimers_GetMatch_v1_0 rtMatch; - rtMatch.event = timer->Event(); - pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); - if (rtMatch.timer) { - if (rtMatch.timerMatch == tmFull) - timerActive = true; - } - } else - timerActive = timer->HasFlags(tfActive); - - day = timer->Day(); - start = timer->Start(); - stop = timer->Stop(); - prio = timer->Priority(); - lifetime = timer->Lifetime(); - strncpy(folder, GetDirectoryFromTimer(timer->File()).c_str(), TEXTINPUTLENGTH); - - AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, true, &timerActive)); - AddMenuItem(new cRecMenuItemInt(tr("Priority"), prio, 0, MAXPRIORITY, false, &prio)); - AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime)); - AddMenuItem(new cRecMenuItemDay(tr("Day"), day, false, &day)); - AddMenuItem(new cRecMenuItemTime(tr("Timer start time"), start, false, &start)); - AddMenuItem(new cRecMenuItemTime(tr("Timer stop time"), stop, false, &stop)); - AddMenuItem(new cRecMenuItemInfo(tr("Timer File"), 2, timer->File() ? timer->File() : "")); - AddMenuItem(new cRecMenuItemSelectDirectory(tr("New Folder"), string(folder), false, folder)); - if (nextState == rmsTimelineTimerSave) { - AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsTimelineTimerDelete, false)); - AddFooter(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsTimeline, false)); - } else { - AddFooter(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsClose, false)); - } -} - -cTimer *cRecMenuEditTimer::GetOriginalTimer(void) { - return originalTimer; -} - -cTimer cRecMenuEditTimer::GetTimer(void) { - cTimer t; - if (timerActive) - t.SetFlags(tfActive); - else - t.SetFlags(tfNone); - t.SetDay(day); - t.SetStart(start); - t.SetStop(stop); - t.SetPriority(prio); - t.SetLifetime(lifetime); - string newFolder(folder); - string newFile = originalTimer->File(); - size_t found = newFile.find_last_of('~'); - if (found != string::npos) { - string fileName = newFile.substr(found+1); - if (newFolder.size() > 0) - newFile = *cString::sprintf("%s~%s", newFolder.c_str(), fileName.c_str()); - else - newFile = fileName; - } else { - if (newFolder.size() > 0) - newFile = *cString::sprintf("%s~%s", newFolder.c_str(), newFile.c_str()); - } - std::replace(newFile.begin(), newFile.end(), '/', '~'); - t.SetFile(newFile.c_str()); - return t; -} - -/****************************************************************************************** -* Series Timer Menus -******************************************************************************************/ - -// --- cRecMenuSeriesTimer --------------------------------------------------------- -cRecMenuSeriesTimer::cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, string folder) { - if (!initialChannel) - return; - timerActive = true; - channel = initialChannel->Number(); - dayOfWeek = 127; - priority = MAXPRIORITY; - lifetime = MAXLIFETIME; - CalculateTimes(event); - this->folder = folder; - - SetMenuWidth(70); - string line1 = tr("Create Series Timer based on"); - string line2 = *cString::sprintf("\"%s\"", event->Title()); - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - - AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, &timerActive)); - AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel"), initialChannel, false, &channel)); - AddMenuItem(new cRecMenuItemTime(tr("Series Timer start time"), start, false, &start)); - AddMenuItem(new cRecMenuItemTime(tr("Series Timer stop time"), stop, false, &stop)); - AddMenuItem(new cRecMenuItemDayChooser(tr("Days to record"), dayOfWeek, false, &dayOfWeek)); - AddMenuItem(new cRecMenuItemDay(tr("Day to start"), tstart, false, &tstart)); - AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, MAXPRIORITY, false, &priority)); - AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime)); - - AddFooter(new cRecMenuItemButtonYesNo(tr("Create Timer"), tr("Cancel"), rmsSeriesTimerCreate, rmsClose, true)); -} - -cTimer *cRecMenuSeriesTimer::GetTimer(void) { - cChannel *chan = Channels.GetByNumber(channel); - cTimer *seriesTimer = new cTimer(NULL, NULL, chan); - cString fileName = "TITLE EPISODE"; - if (folder.size() > 0) { - std::replace(folder.begin(), folder.end(), '/', '~'); - fileName = cString::sprintf("%s~%s", folder.c_str(), *fileName); - } - seriesTimer->SetDay(tstart); - seriesTimer->SetStart(start); - seriesTimer->SetStop(stop); - seriesTimer->SetPriority(priority); - seriesTimer->SetLifetime(lifetime); - seriesTimer->SetWeekDays(dayOfWeek); - seriesTimer->SetFile(*fileName); - if (timerActive) - seriesTimer->SetFlags(tfActive); - else - seriesTimer->SetFlags(tfNone); - return seriesTimer; -} - -void cRecMenuSeriesTimer::CalculateTimes(const cEvent *event) { - tstart = event->StartTime(); - tstart -= Setup.MarginStart * 60; - time_t tstop = tstart + event->Duration(); - tstop += Setup.MarginStop * 60; - - struct tm tm_r; - struct tm *time = localtime_r(&tstart, &tm_r); - start = time->tm_hour * 100 + time->tm_min; - time = localtime_r(&tstop, &tm_r); - stop = time->tm_hour * 100 + time->tm_min; - if (stop >= 2400) - stop -= 2400; -} - -// --- cRecMenuConfirmSeriesTimer --------------------------------------------------------- -cRecMenuConfirmSeriesTimer::cRecMenuConfirmSeriesTimer(cTimer *seriesTimer) { - SetMenuWidth(50); - string line1 = tr("Series Timer created"); - string line2 = ""; - if (seriesTimer) { - cString days = cTimer::PrintDay(seriesTimer->Day(), seriesTimer->WeekDays(), true); - line2 = cString::sprintf("%s, %s: %s, %s: %s", *days, tr("Start"), *TimeString(seriesTimer->StartTime()), tr("Stop"), *TimeString(seriesTimer->StopTime())); - } - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -/****************************************************************************************** -* SearchTimer Menus -******************************************************************************************/ - -// --- cRecMenuSearchTimer --------------------------------------------------------- -cRecMenuSearchTimer::cRecMenuSearchTimer(const cEvent *event) { - SetMenuWidth(70); - string message = tr("Configure Search Timer based on"); - string infoText = *cString::sprintf("\"%s\"", event->Title()); - AddHeader(new cRecMenuItemInfo(message, 2, infoText)); - strncpy(searchString, event->Title(), TEXTINPUTLENGTH); - AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false)); - AddFooter(new cRecMenuItemButtonYesNo(tr("Continue"), tr("Cancel"), rmsSearchTimerOptions, rmsClose, true)); -} - -// --- cRecMenuSearchTimerTemplates --------------------------------------------------------- -cRecMenuSearchTimerTemplates::cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, vector templates) { - SetMenuWidth(70); - this->searchTimer = searchTimer; - this->templates = templates; - string message = tr("Configure Search Timer for Search String"); - AddHeader(new cRecMenuItemInfo(message, 2, searchTimer.SearchString())); - AddMenuItem(new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, true)); - - numTemplates = templates.size(); - for (int i=0; i= 0 && tmplActive < (int)templates.size()) - templ = templates[tmplActive]; - return templ; -} - -// --- cRecMenuSearchTimers --------------------------------------------------------- -cRecMenuSearchTimers::cRecMenuSearchTimers(std::vector searchTimers) { - SetMenuWidth(70); - this->searchTimers = searchTimers; - numSearchTimers = searchTimers.size(); - string headline; - if (numSearchTimers > 0) { - headline = tr("EPGSearch Search Timers"); - } else { - headline = tr("No Search Timers Configured"); - } - AddHeader(new cRecMenuItemInfo(headline)); - cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (!numSearchTimers)?true:false); - if (numSearchTimers > 0) { - SetMenuItems(); - AddFooter(button); - } else { - AddMenuItem(button); - } -} - -void cRecMenuSearchTimers::SetMenuItems(void) { - for (int i = 0; i < numSearchTimers; i++) { - AddMenuItem(new cRecMenuItemSearchTimer(searchTimers[i], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, (i==0)?true:false)); - } -} - -cTVGuideSearchTimer cRecMenuSearchTimers::GetSearchTimer(void) { - cRecMenuItemSearchTimer *activeItem = dynamic_cast(GetActive()); - return activeItem->GetTimer(); -} - -// --- cRecMenuSearchTimerEdit --------------------------------------------------------- -cRecMenuSearchTimerEdit::cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions) { - this->advancedOptions = advancedOptions; - this->searchTimer = searchTimer; - strncpy(searchString, searchTimer.SearchString().c_str(), TEXTINPUTLENGTH); - timerActive = searchTimer.Active(); - mode = searchTimer.SearchMode(); - useTitle = searchTimer.UseTitle(); - useSubtitle = searchTimer.UseSubtitle(); - useDescription = searchTimer.UseDescription(); - useChannel = searchTimer.UseChannel(); - startChannel = searchTimer.StartChannel(); - stopChannel = searchTimer.StopChannel(); - useTime = searchTimer.UseTime(); - startTime = searchTimer.StartTime(); - stopTime = searchTimer.StopTime(); - useDayOfWeek = searchTimer.UseDayOfWeek(); - dayOfWeek = searchTimer.DayOfWeek(); - priority = searchTimer.Priority(); - lifetime = searchTimer.Lifetime(); - useEpisode = searchTimer.UseEpisode(); - std::string dir = searchTimer.Directory(); - strncpy(directory, dir.c_str(), TEXTINPUTLENGTH); - marginStart = searchTimer.MarginStart(); - marginStop = searchTimer.MarginStop(); - useVPS = searchTimer.UseVPS(); - avoidRepeats = searchTimer.AvoidRepeats(); - allowedRepeats = searchTimer.AllowedRepeats(); - compareTitle = searchTimer.CompareTitle(); - compareSubtitle = searchTimer.CompareSubtitle(); - compareSummary = searchTimer.CompareSummary(); - useInFavorites = searchTimer.UseInFavorites(); - - SetMenuWidth(70); - string infoText; - if (searchTimer.GetID() > -1) { - infoText = tr("Configure Search Timer Options"); - } else { - infoText = tr("Create Search Timer"); - } - AddHeader(new cRecMenuItemInfo(infoText)); - cRecMenuItemButtonYesNo *footerButton = new cRecMenuItemButtonYesNo(tr("Save Search Timer"), tr("Cancel"), rmsSearchTimerSave, rmsSearchTimers, false); - AddFooter(footerButton); - CreateMenuItems(); -} - -void cRecMenuSearchTimerEdit::CreateMenuItems(void) { - AddMenuItem(new cRecMenuItemText(tr("Search String"), searchString, TEXTINPUTLENGTH, true, searchString)); - AddMenuItem(new cRecMenuItemBool(tr("Active"), timerActive, false, &timerActive, rmsSearchTimerSave)); - vector searchModes; - searchTimer.GetSearchModes(&searchModes); - esyslog("tvguideng: num search modes %ld", searchModes.size()); - AddMenuItem(new cRecMenuItemSelect(tr("Search Mode"), searchModes, mode, false, &mode, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Use Title"), useTitle, false, &useTitle, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Use Subtitle"), useSubtitle, false, &useSubtitle, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Use Description"), useDescription, false, &useDescription, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Limit Channels"), useChannel, false, &useChannel, rmsSearchTimerSave)); - if (startChannel == 0) - startChannel = 1; - if (stopChannel == 0) - stopChannel = 1; - AddMenuItem(new cRecMenuItemChannelChooser(tr("Start Channel"), Channels.GetByNumber(startChannel), false, &startChannel, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemChannelChooser(tr("Stop Channel"), Channels.GetByNumber(stopChannel), false, &stopChannel, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Use Time"), useTime, false, &useTime, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemTime(tr("Start after"), startTime, false, &startTime, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemTime(tr("Start before"), stopTime, false, &stopTime, rmsSearchTimerSave)); - - if (!advancedOptions) { - AddMenuItem(new cRecMenuItemButton(tr("Display advanced Options"), rmsSearchTimerEditAdvanced, false)); - } else { - AddMenuItem(new cRecMenuItemBool(tr("Limit Days of the Week"), useDayOfWeek, false, &useDayOfWeek, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemDayChooser(tr("Select Days"), dayOfWeek, false, &dayOfWeek)); - AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, 99, false, &priority, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, 99, false, &lifetime, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemInt(tr("Time margin for start in minutes"), marginStart, 0, 30, false, &marginStart, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemInt(tr("Time margin for stop in minutes"), marginStop, 0, 30, false, &marginStop, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Series Recording"), useEpisode, false, &useEpisode, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemSelectDirectory(tr("Folder"), string(directory), false, directory, rmsSearchTimerSave, true)); - AddMenuItem(new cRecMenuItemBool(tr("Use VPS"), useVPS, false, &useVPS, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Avoid Repeats"), avoidRepeats, false, &avoidRepeats, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemInt(tr("Number of allowed repeats"), allowedRepeats, 0, 30, false, &allowedRepeats, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Compare Title"), compareTitle, false, &compareTitle, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Compare Subtitle"), compareSubtitle, false, &compareSubtitle, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Compare Description"), compareSummary, false, &compareSummary, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemBool(tr("Use in Favorites"), useInFavorites, false, &useInFavorites, rmsSearchTimerSave)); - AddMenuItem(new cRecMenuItemButton(tr("Hide advanced Options"), rmsSearchTimerEdit, false)); - } - - AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, false)); -} - -cTVGuideSearchTimer cRecMenuSearchTimerEdit::GetSearchTimer(void) { - searchTimer.SetSearchString(searchString); - searchTimer.SetActive(timerActive); - searchTimer.SetSearchMode(mode); - searchTimer.SetUseTitle(useTitle); - searchTimer.SetUseSubtitle(useSubtitle); - searchTimer.SetUseDesription(useDescription); - searchTimer.SetUseChannel(useChannel); - if (useChannel) { - searchTimer.SetStartChannel(startChannel); - searchTimer.SetStopChannel(stopChannel); - } - searchTimer.SetUseTime(useTime); - if (useTime) { - searchTimer.SetStartTime(startTime); - searchTimer.SetStopTime(stopTime); - } - searchTimer.SetUseDayOfWeek(useDayOfWeek); - if (useDayOfWeek) { - searchTimer.SetDayOfWeek(dayOfWeek); - } - searchTimer.SetPriority(priority); - searchTimer.SetLifetime(lifetime); - searchTimer.SetUseEpisode(useEpisode); - string dir(directory); - std::replace(dir.begin(), dir.end(), '/', '~'); - searchTimer.SetDirectory(dir); - searchTimer.SetMarginStart(marginStart); - searchTimer.SetMarginStop(marginStop); - searchTimer.SetUseVPS(useVPS); - searchTimer.SetAvoidRepeats(avoidRepeats); - if (avoidRepeats) { - searchTimer.SetAllowedRepeats(allowedRepeats); - searchTimer.SetCompareTitle(compareTitle); - searchTimer.SetCompareSubtitle(compareSubtitle); - searchTimer.SetCompareSummary(compareSummary); - } - searchTimer.SetUseInFavorites(useInFavorites); - return searchTimer; -} - -// --- cRecMenuSearchTimerDeleteConfirm --------------------------------------------- -cRecMenuSearchTimerDeleteConfirm::cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer) { - SetMenuWidth(70); - this->searchTimer = searchTimer; - string line1 = tr("Really delete Search Timer"); - string line2 = *cString::sprintf("\"%s\"?", searchTimer.SearchString().c_str()); - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - AddMenuItem(new cRecMenuItemButton(tr("Delete only Search Timer"), rmsSearchTimerDelete, true)); - AddMenuItem(new cRecMenuItemButton(tr("Delete Search Timer and created Timers"), rmsSearchTimerDeleteWithTimers, false)); - AddFooter(new cRecMenuItemButton(tr("Cancel"), rmsClose, false)); -} - -cTVGuideSearchTimer cRecMenuSearchTimerDeleteConfirm::GetSearchTimer(void) { - return searchTimer; -} - -// --- cRecMenuSearchTimerCreateConfirm --------------------------------------------------------- -cRecMenuSearchTimerCreateConfirm::cRecMenuSearchTimerCreateConfirm(bool success) { - SetMenuWidth(50); - cRecMenuItemInfo *infoItem = NULL; - if (success) { - string line1 = tr("Search Timer sucessfully created"); - string line2 = tr("Search Timer update initialised"); - infoItem = new cRecMenuItemInfo(line1, 2, line2); - } else { - string line1 = tr("Search Timer NOT sucessfully created"); - infoItem = new cRecMenuItemInfo(line1); - } - AddHeader(infoItem); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuSearchTimerTemplatesCreate --------------------------------------------------------- -cRecMenuSearchTimerTemplatesCreate::cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer) { - SetMenuWidth(70); - this->templ = templ; - this->searchTimer = searchTimer; - - string line1 = tr("Creating Search Timer"); - string line2 = *cString::sprintf("%s: \"%s\"", tr("Search Term"), searchTimer.SearchString().c_str()); - string line3 = *cString::sprintf("%s \"%s\"", tr("Using Template"), templ.name.c_str()); - - AddHeader(new cRecMenuItemInfo(line1, 3, line2, line3)); - AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, true)); - AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Search Timer"), tr("Use other Template"), rmsSearchTimerSave, rmsSearchTimerOptions, false)); -} - - -// --- cRecMenuSearchTimerResults --------------------------------------------------------- -cRecMenuSearchTimerResults::cRecMenuSearchTimerResults(string searchString, const cEvent **searchResults, int numResults, string templateName, eRecMenuState action2) { - SetMenuWidth(70); - this->searchResults = searchResults; - this->action2 = action2; - this->numResults = numResults; - string message1 = "", message2 = "", message3 = ""; - if (action2 == rmsFavoritesRecord) { - message1 = tr("search results for Favorite"); - message2 = tr("search result for Favorite"); - } else { - message1 = tr("search results for Search Timer"); - message2 = tr("search result for Search Timer"); - message3 = tr("Using Template"); - } - cRecMenuItem *infoItem = NULL; - if (templateName.size() > 0) { - string line1 = *cString::sprintf("%d %s:", numResults, (numResults>1)?(message1.c_str()):(message2.c_str())); - string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); - string line3 = *cString::sprintf("%s \"%s\"", message3.c_str(), templateName.c_str()); - infoItem = new cRecMenuItemInfo(line1, 3, line2, line3); - } else { - string line1 = *cString::sprintf("%d %s:", numResults, (numResults>1)?(message1.c_str()):(message2.c_str())); - string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); - infoItem = new cRecMenuItemInfo(line1, 2, line2); - } - AddHeader(infoItem); - - cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, false); - if (searchResults && (numResults > 0)) { - for (int i=0; i(GetActive())) - ev = activeItem->GetEvent(); - return ev; -} - -// --- cRecMenuSearchTimerNothingFound --------------------------------------------------------- -cRecMenuSearchTimerNothingFound::cRecMenuSearchTimerNothingFound(string searchString) { - SetMenuWidth(50); - string line1 = tr("Nothing found for Search String"); - string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -/****************************************************************************************** -* SwitchTimer Menus -******************************************************************************************/ - -// --- cRecMenuSwitchTimer --------------------------------------------------------- -cRecMenuSwitchTimer::cRecMenuSwitchTimer(void) { - SetMenuWidth(60); - switchMinsBefore = config.switchMinsBefore; - announceOnly = 0; - - AddHeader(new cRecMenuItemInfo(tr("Configure Options for Switchtimer"))); - AddMenuItem(new cRecMenuItemInt(tr("Minutes before switching"), switchMinsBefore, 0, 10, false, &switchMinsBefore)); - vector switchModes; - switchModes.push_back(tr("switch")); - switchModes.push_back(tr("announce only")); - switchModes.push_back(tr("ask for switch")); - AddMenuItem(new cRecMenuItemSelect(tr("Switch Mode"), switchModes, announceOnly, false, &announceOnly)); - - AddFooter(new cRecMenuItemButtonYesNo(tr("Create"), tr("Cancel"), rmsSwitchTimerCreate, rmsClose, true)); -} - -cSwitchTimer cRecMenuSwitchTimer::GetSwitchTimer(void) { - cSwitchTimer st; - st.switchMinsBefore = switchMinsBefore; - st.announceOnly = announceOnly; - return st; -} - -// --- cRecMenuSwitchTimerConfirm --------------------------------------------------------- -cRecMenuSwitchTimerConfirm::cRecMenuSwitchTimerConfirm(bool success) { - SetMenuWidth(50); - string message1 = tr("Switch Timer sucessfully created"); - string message2 = tr("Switch Timer NOT sucessfully created"); - string infoText = success?message1:message2; - AddHeader(new cRecMenuItemInfo(infoText)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuSwitchTimerDelete --------------------------------------------------------- -cRecMenuSwitchTimerDelete::cRecMenuSwitchTimerDelete(void) { - SetMenuWidth(50); - AddHeader(new cRecMenuItemInfo(tr("Switch Timer deleted"))); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -/****************************************************************************************** -* Search Menus -******************************************************************************************/ - -// --- cRecMenuSearch --------------------------------------------------------- -cRecMenuSearch::cRecMenuSearch(string searchString, bool withOptions) { - SetMenuWidth(60); - strncpy(this->searchString, searchString.c_str(), TEXTINPUTLENGTH); - mode = 0; - channelNr = 0; - useTitle = true; - useSubTitle = true; - useDescription = false; - - AddHeader(new cRecMenuItemInfo(tr("Search"))); - AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), this->searchString, TEXTINPUTLENGTH, false, this->searchString)); - - if (withOptions) { - vector searchModes; - cTVGuideSearchTimer searchTimer; - searchTimer.GetSearchModes(&searchModes); - AddMenuItem(new cRecMenuItemSelect(tr("Search Mode"), searchModes, 0, false, &mode)); - AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel to Search"), NULL, false, &channelNr)); - AddMenuItem(new cRecMenuItemBool(tr("Search in title"), true, false, &useTitle)); - AddMenuItem(new cRecMenuItemBool(tr("Search in Subtitle"), true, false, &useSubTitle)); - AddMenuItem(new cRecMenuItemBool(tr("Search in Description"), false, false, &useDescription)); - } else { - AddMenuItem(new cRecMenuItemButton(tr("Show Search Options"), rmsSearchWithOptions, false)); - } - - cRecMenuItemButtonYesNo *button = new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsSearchPerform, rmsClose, true); - AddFooter(button); -} - -Epgsearch_searchresults_v1_0 cRecMenuSearch::GetEPGSearchStruct(void) { - Epgsearch_searchresults_v1_0 data; - data.query = searchString; - data.mode = mode; - data.channelNr = channelNr; - data.useTitle = useTitle; - data.useSubTitle = useSubTitle; - data.useDescription = useDescription; - return data; -} - -// --- cRecMenuSearchResults --------------------------------------------------------- -cRecMenuSearchResults::cRecMenuSearchResults(string searchString, const cEvent **searchResults, int numResults) { - this->searchResults = searchResults; - SetMenuWidth(70); - this->searchString = searchString; - this->numResults = numResults; - - string message = ""; - if (numResults > 1) { - message = *cString::sprintf("%d %s", numResults, tr("search results for")); - } else { - message = *cString::sprintf("%d %s", numResults, tr("search result for")); - } - string searchStringQuoted = *cString::sprintf("\"%s\"", searchString.c_str()); - AddHeader(new cRecMenuItemInfo(message, 2, searchStringQuoted)); - - cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsSearch, rmsClose, false); - AddFooter(buttons); - if (searchResults && (numResults > 0)) { - for (int i=0; i(GetActive()); - if (activeItem) - return activeItem->GetEvent(); - return NULL; -} - -// --- cRecMenuSearchNothingFound --------------------------------------------------------- -cRecMenuSearchNothingFound::cRecMenuSearchNothingFound(string searchString, bool tooShort) { - SetMenuWidth(50); - string text; - if (!tooShort) { - cString message = tr("Nothing found for Search String"); - text = *cString::sprintf("%s\n\"%s\"", - *message, - searchString.c_str()); - } else { - cString message = tr("Search String has to have at least three letters"); - text = *cString::sprintf("%s\n\"%s\"", - *message, - searchString.c_str()); - - } - AddHeader(new cRecMenuItemInfo(text)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -// --- cRecMenuSearchConfirmTimer --------------------------------------------------------- -cRecMenuSearchConfirmTimer::cRecMenuSearchConfirmTimer(const cEvent *event) { - SetMenuWidth(50); - - string message = tr("Timer created"); - cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); - string line3 = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); - string line4 = event->Title() ? event->Title() : ""; - - AddHeader(new cRecMenuItemInfo(message, 4, *channelName, line3, line4)); - AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); -} - -/****************************************************************************************** -* Timeline -******************************************************************************************/ - -// --- cRecMenuTimeline --------------------------------------------------------- -cRecMenuTimeline::cRecMenuTimeline(void) { - SetMenuWidth(95); - SetStartStop(); - GetTimersForDay(); - - timelineHeader = new cRecMenuItemTimelineHeader(timeStart); - AddHeader(timelineHeader); - - timelineFooter = new cRecMenuItemButton(tr("Close"), rmsClose, false); - AddFooter(timelineFooter); - SetTimers(); -} - -void cRecMenuTimeline::SetHeaderTimer(void) { - cTimer *currentTimer = NULL; - cRecMenuItem *currentItem = GetActive(); - if (!currentItem) { - timelineHeader->UnsetCurrentTimer(); - return; - } - if (cRecMenuItemTimelineTimer *myActiveItem = dynamic_cast(currentItem)) { - currentTimer = myActiveItem->GetTimer(); - } - timelineHeader->SetCurrentTimer(currentTimer); - timelineHeader->SetNew(); -} - -void cRecMenuTimeline::SetStartStop(void) { - time_t now = time(0); - tm *timeStruct = localtime(&now); - timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec; - today = timeStart; - timeStop = timeStart + 24*3600 - 1; -} - -void cRecMenuTimeline::GetTimersForDay(void) { - timersToday.clear(); - for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) { - if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) { - timersToday.push_back(t); - } - } - numTimersToday = timersToday.size(); -} - -void cRecMenuTimeline::SetTimers(void) { - if (numTimersToday == 0) { - AddMenuItem(new cRecMenuItemInfo(tr("No active Timers"))); - timelineFooter->SetActive(); - } else { - for (int i=0; iSetInactive(); - } -} - -void cRecMenuTimeline::PrevDay(void) { - if ((timeStart - 3600*24) < today) - return; - timeStart -= 3600*24; - timeStop -= 3600*24; - ClearMenuItems(true); - GetTimersForDay(); - SetTimers(); - InitMenuItems(); - SetHeaderTimer(); - timelineHeader->SetDay(timeStart); - timelineHeader->SetNew(); -} - -void cRecMenuTimeline::NextDay(void) { - timeStart += 3600*24; - timeStop += 3600*24; - ClearMenuItems(true); - GetTimersForDay(); - SetTimers(); - InitMenuItems(); - SetHeaderTimer(); - timelineHeader->SetDay(timeStart); - timelineHeader->SetNew(); -} - -cTimer *cRecMenuTimeline::GetTimer(void) { - if (cRecMenuItemTimelineTimer *activeItem = dynamic_cast(GetActive())) - return activeItem->GetTimer(); - return NULL; -} - - -eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) { - eRecMenuState state = rmsContinue; - switch (Key & ~k_Repeat) { - case kLeft: - PrevDay(); - Draw(); - break; - state = rmsConsumed; - case kRight: - NextDay(); - Draw(); - state = rmsConsumed; - break; - case kUp: { - if (ScrollUp(false)) { - SetHeaderTimer(); - Draw(); - } - state = rmsConsumed; - break; } - case kDown: { - if (ScrollDown(false)) { - SetHeaderTimer(); - Draw(); - } - state = rmsConsumed; - break; } - default: - break; - } - if (state != rmsConsumed) { - state = cRecMenu::ProcessKey(Key); - } - return state; -} - -/****************************************************************************************** -* Recording Search Menus -******************************************************************************************/ - -// --- cRecMenuRecordingSearch --------------------------------------------------------- -cRecMenuRecordingSearch::cRecMenuRecordingSearch(string search) { - SetMenuWidth(60); - strncpy(searchString, search.c_str(), TEXTINPUTLENGTH); - AddHeader(new cRecMenuItemInfo(tr("Search in Recordings"))); - AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false, searchString)); - AddMenuItem(new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsRecordingSearchResult, rmsClose, true)); -} - -// --- cRecMenuRecordingSearchResults --------------------------------------------------------- -cRecMenuRecordingSearchResults::cRecMenuRecordingSearchResults(string searchString, cRecording **searchResults, int numResults) { - SetMenuWidth(80); - this->searchString = searchString; - this->searchResults = searchResults; - this->numResults = numResults; - string line1 = *cString::sprintf("%s %d %s %s:", tr("Found"), numResults, (numResults>1)?tr("recordings"):tr("recording"), tr("for")); - string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); - AddHeader(new cRecMenuItemInfo(line1, 2, line2)); - - if (searchResults && (numResults > 0)) { - for (int i=0; i favorites) { - SetMenuWidth(70); - this->favorites = favorites; - - CreateFavoritesMenuItems(); - - string header; - if (numFavorites > 0) { - header = tr("Favorites"); - } else { - header = tr("No Favorites available"); - } - AddHeader(new cRecMenuItemInfo(header)); - cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (numFavorites==0)?true:false); - if (numFavorites != 0) - AddFooter(button); - else - AddMenuItem(button); -} - -void cRecMenuFavorites::CreateFavoritesMenuItems(void) { - bool active = true; - if (config.favWhatsOnNow) { - AddMenuItem(new cRecMenuItemFavoriteStatic(tr("What's on now"), rmsFavoritesNow, active)); - active = false; - numFavorites++; - } - if (config.favWhatsOnNext) { - AddMenuItem(new cRecMenuItemFavoriteStatic(tr("What's on next"), rmsFavoritesNext, active)); - active = false; - numFavorites++; - } - if (config.favUseTime1) { - string desc = *cString::sprintf("%s (%s)", config.descUser1.c_str(), NiceTime(config.favTime1).c_str()); - AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser1, active)); - active = false; - numFavorites++; - } - if (config.favUseTime2) { - string desc = *cString::sprintf("%s (%s)", config.descUser2.c_str(), NiceTime(config.favTime2).c_str()); - AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser2, active)); - active = false; - numFavorites++; - } - if (config.favUseTime3) { - string desc = *cString::sprintf("%s (%s)", config.descUser3.c_str(), NiceTime(config.favTime3).c_str()); - AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser3, active)); - active = false; - numFavorites++; - } - if (config.favUseTime4) { - string desc = *cString::sprintf("%s (%s)", config.descUser4.c_str(), NiceTime(config.favTime4).c_str()); - AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser4, active)); - active = false; - numFavorites++; - } - - int numAdditionalFavs = favorites.size(); - for (int i = 0; i < numAdditionalFavs; i++) { - AddMenuItem(new cRecMenuItemFavorite(favorites[i], rmsSearchTimerTest, active)); - active = false; - numFavorites++; - } -} - -string cRecMenuFavorites::NiceTime(int favTime) { - int hours = favTime/100; - int mins = favTime - hours * 100; - return *cString::sprintf("%02d:%02d", hours, mins); -} - -cTVGuideSearchTimer cRecMenuFavorites::GetFavorite(void) { - cRecMenuItemFavorite *activeItem = dynamic_cast(GetActive()); - return activeItem->GetFavorite(); -} +#include +#include +#include +#include "config.h" +#include "services/remotetimers.h" +#include "helpers.h" +#include "recmenus.h" + +// --- cRecMenuMain --------------------------------------------------------- +cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive) { + SetMenuWidth(50); + eRecMenuState action = rmsInstantRecord; + if (!timerActive) { + if (config.instRecFolderMode == eFolderSelect) + action = rmsInstantRecordFolder; + AddMenuItem(new cRecMenuItemButton(tr("Instant Record"), action, true)); + } else { + AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsDeleteTimer, true)); + AddMenuItem(new cRecMenuItemButton(tr("Edit Timer"), rmsEditTimer, false)); + } + + AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false)); + + if (epgSearchAvailable) { + AddMenuItem(new cRecMenuItemButton(tr("Create Search Timer"), rmsSearchTimer, false)); + AddMenuItem(new cRecMenuItemButton(tr("Search Timers"), rmsSearchTimers, false)); + } + + if (config.instRecFolderMode == eFolderSelect) + action = rmsSeriesTimerFolder; + else + action = rmsSeriesTimer; + AddMenuItem(new cRecMenuItemButton(tr("Create Series Timer"), action, false)); + + if (epgSearchAvailable) { + if (!switchTimerActive) { + AddMenuItem(new cRecMenuItemButton(tr("Create Switch Timer"), rmsSwitchTimer, false)); + } else { + AddMenuItem(new cRecMenuItemButton(tr("Delete Switch Timer"), rmsSwitchTimerDelete, false)); + } + AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false)); + } + + if (epgSearchAvailable) { + AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false)); + } + + AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false)); +}; + +/****************************************************************************************** +* Instant Timer Menus +******************************************************************************************/ + +// --- cRecMenuConfirmTimer --------------------------------------------------------- +cRecMenuConfirmTimer::cRecMenuConfirmTimer(const cEvent *event) { + SetMenuWidth(50); + + bool eventHasTimer = false; + if (config.useRemoteTimers && pRemoteTimers) { + RemoteTimers_GetMatch_v1_0 rtMatch; + rtMatch.event = event; + pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); + if (rtMatch.timerMatch == tmFull) { + eventHasTimer = true; + } + } else { + eventHasTimer = event->HasTimer(); + } + + string message; + if (eventHasTimer) { + message = tr("Timer created"); + } else { + message = tr("Timer NOT created"); + } +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cString channelName = Channels->GetByChannelID(event->ChannelID())->Name(); +#else + cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); +#endif + string datetime = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); + string eventTitle = event->Title() ? event->Title() : ""; + AddHeader(new cRecMenuItemInfo(message, 4, *channelName, datetime, eventTitle)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuAskFolder --------------------------------------------------------- +cRecMenuAskFolder::cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction) { + SetMenuWidth(80); + this->nextAction = nextAction; + string message = tr("Set Folder for"); + string eventTitle = event->Title() ? event->Title() : ""; + AddHeader(new cRecMenuItemInfo(message, 2, eventTitle)); + AddMenuItem(new cRecMenuItemButton(tr("root video folder"), nextAction, true)); + + ReadRecordingDirectories(&folders, NULL, ""); + int numFolders = folders.size(); + for (int i=0; i < numFolders; i++) { + AddMenuItem(new cRecMenuItemButton(folders[i].c_str(), nextAction, false)); + } +} + +string cRecMenuAskFolder::GetFolder(void) { + std::string folder = ""; + int folderActive = GetNumActive(); + if (folderActive > 0 && folderActive < (int)folders.size() + 1) + folder = folders[folderActive - 1]; + return folder; +} + +// --- cRecMenuConfirmDeleteTimer --------------------------------------------------------- +cRecMenuConfirmDeleteTimer::cRecMenuConfirmDeleteTimer(const cEvent *event) { + SetMenuWidth(50); + string message = tr("Timer deleted"); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cString channelName = Channels->GetByChannelID(event->ChannelID())->Name(); +#else + cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); +#endif + string datetime = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); + string eventTitle = event->Title() ? event->Title() : ""; + + AddHeader(new cRecMenuItemInfo(message, 4, *channelName, datetime, eventTitle)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuAskDeleteTimer --------------------------------------------------------- +cRecMenuAskDeleteTimer::cRecMenuAskDeleteTimer(const cEvent *event) { + SetMenuWidth(50); + string message = tr("Timer"); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cString channelName = Channels->GetByChannelID(event->ChannelID())->Name(); +#else + cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); +#endif + string eventTitle = event->Title() ? event->Title() : ""; + string message2 = tr("still recording - really delete?"); + + AddHeader(new cRecMenuItemInfo(message, 4, *channelName, eventTitle, message2)); + AddMenuItem(new cRecMenuItemButtonYesNo(tr("Yes"), tr("No"), rmsDeleteTimerConfirmation, rmsClose, true)); +} + +// --- cRecMenuTimerConflicts --------------------------------------------------------- +cRecMenuTimerConflicts::cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts) { + SetMenuWidth(80); + int numConflicts = conflicts->NumConflicts(); + + string text; + if (numConflicts == 1) { + text = *cString::sprintf("%s %s %s", tr("One"), tr("Timer Conflict"), tr("detected")); + } else { + text = *cString::sprintf("%d %s %s", conflicts->NumConflicts(), tr("Timer Conflicts"), tr("detected")); + } + AddHeader(new cRecMenuItemInfo(text)); + + for (int i=0; iGetConflict(i); + if (!conflict) + continue; + cString dateTime = DayDateTime(conflict->time); + int numTimers = conflict->timerIDs.size(); + cString textConflict = cString::sprintf("%s: %s (%d %s)", tr("Show conflict"), *dateTime, numTimers, tr("timers involved")); + bool isActive = (i==0)?true:false; + AddMenuItem(new cRecMenuItemButton(*textConflict, rmsTimerConflict, isActive)); + } + + AddFooter(new cRecMenuItemButton(tr("Ignore Conflicts"), rmsClose, false)); +} + +int cRecMenuTimerConflicts::GetTimerConflict(void) { + return GetNumActive(); +} + +// --- cRecMenuTimerConflict --------------------------------------------------------- +cRecMenuTimerConflict::cRecMenuTimerConflict(cTVGuideTimerConflict *conflict) { + SetMenuWidth(95); + this->conflict = conflict; + AddHeader(new cRecMenuItemTimerConflictHeader(conflict->timeStart, + conflict->timeStop, + conflict->overlapStart, + conflict->overlapStop)); + +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + int i=0; + for(vector::iterator it = conflict->timerIDs.begin(); it != conflict->timerIDs.end(); it++) { + const cTimer *timer = timers->Get(*it); + if (timer) { + AddMenuItem(new cRecMenuItemTimer(timer, + rmsTimerConflictShowInfo, + rmsDeleteTimerConflictMenu, + rmsEditTimerConflictMenu, + rmsSearchRerunsTimerConflictMenu, + conflict->timeStart, + conflict->timeStop, + conflict->overlapStart, + conflict->overlapStop, + (!i)?true:false)); + i++; + } + } + AddMenuItem(new cRecMenuItemButton(tr("Ignore Conflict"), rmsIgnoreTimerConflict, false)); +} + +int cRecMenuTimerConflict::GetTimerConflictIndex(void) { + return GetNumActive(); +} + +// --- cRecMenuNoTimerConflict --------------------------------------------------------- +cRecMenuNoTimerConflict::cRecMenuNoTimerConflict(void) { + SetMenuWidth(50); + string text = tr("No Timer Conflicts found"); + AddHeader(new cRecMenuItemInfo(text)); + AddMenuItem(new cRecMenuItemButton(tr("Close"), rmsClose, true)); +} + +// --- cRecMenuRerunResults --------------------------------------------------------- +cRecMenuRerunResults::cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns) { + this->reruns = reruns; + this->numReruns = numReruns; + SetMenuWidth(70); + + string message1 = tr("reruns for"); + string message2 = tr("rerun for"); + string message3 = tr("found"); + string line1 = *cString::sprintf("%d %s:", numReruns, (numReruns>1)?(message1.c_str()):(message2.c_str())); + string line2 = *cString::sprintf("\"%s\" %s", original->Title(), message3.c_str()); + + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + + cRecMenuItem *button = new cRecMenuItemButton(tr("Ignore reruns"), rmsTimerConflictIgnoreReruns, false); + AddFooter(button); + + if (reruns && (numReruns > 0)) { + for (int i=0; i(GetActive()); + if (activeItem) + return activeItem->GetEvent(); + return NULL; +} + +// --- cRecMenuNoRerunsFound --------------------------------------------------------- +cRecMenuNoRerunsFound::cRecMenuNoRerunsFound(string searchString) { + SetMenuWidth(50); + string message = tr("No reruns found for Event"); + string eventQuoted = *cString::sprintf("\"%s\"", searchString.c_str()); + + AddHeader(new cRecMenuItemInfo(message, 2, eventQuoted)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuConfirmRerunUsed --------------------------------------------------------- +cRecMenuConfirmRerunUsed::cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace) { + SetMenuWidth(70); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cString channelOrig = Channels->GetByChannelID(original->ChannelID())->Name(); + cString channelReplace = Channels->GetByChannelID(replace->ChannelID())->Name(); +#else + cString channelOrig = Channels.GetByChannelID(original->ChannelID())->Name(); + cString channelReplace = Channels.GetByChannelID(replace->ChannelID())->Name(); +#endif + string line1 = *cString::sprintf("%s \"%s\"", tr("Timer for"), original->Title()); + string line2 = *cString::sprintf("%s %s %s", *original->GetDateString(), *original->GetTimeString(), *channelOrig); + string line3 = *cString::sprintf("%s \"%s\"", tr("replaced by rerun"), replace->Title()); + string line4 = *cString::sprintf("%s %s %s", *replace->GetDateString(), *replace->GetTimeString(), *channelReplace); + + AddHeader(new cRecMenuItemInfo(line1, 4, line2, line3, line4)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflicts, true)); +} + +// --- cRecMenuEditTimer --------------------------------------------------------- +cRecMenuEditTimer::cRecMenuEditTimer(const cTimer *timer, eRecMenuState nextState) { + SetMenuWidth(70); + if (!timer) + return; + originalTimer = timer; + string title = ""; + string channelName = ""; + if (timer->Event() && timer->Event()->Title()) + title = timer->Event()->Title(); + if (timer->Channel() && timer->Channel()->Name()) + channelName = timer->Channel()->Name(); + cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(tr("Edit Timer"), 3, title, channelName); + AddHeader(infoItem); + + timerActive = false; + if (config.useRemoteTimers && pRemoteTimers) { + RemoteTimers_GetMatch_v1_0 rtMatch; + rtMatch.event = timer->Event(); + pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); + if (rtMatch.timer) { + if (rtMatch.timerMatch == tmFull) + timerActive = true; + } + } else + timerActive = timer->HasFlags(tfActive); + + day = timer->Day(); + start = timer->Start(); + stop = timer->Stop(); + prio = timer->Priority(); + lifetime = timer->Lifetime(); + strncpy(folder, GetDirectoryFromTimer(timer->File()).c_str(), TEXTINPUTLENGTH); + + AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, true, &timerActive)); + AddMenuItem(new cRecMenuItemInt(tr("Priority"), prio, 0, MAXPRIORITY, false, &prio)); + AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime)); + AddMenuItem(new cRecMenuItemDay(tr("Day"), day, false, &day)); + AddMenuItem(new cRecMenuItemTime(tr("Timer start time"), start, false, &start)); + AddMenuItem(new cRecMenuItemTime(tr("Timer stop time"), stop, false, &stop)); + AddMenuItem(new cRecMenuItemInfo(tr("Timer File"), 2, timer->File() ? timer->File() : "")); + AddMenuItem(new cRecMenuItemSelectDirectory(tr("New Folder"), string(folder), false, folder)); + if (nextState == rmsTimelineTimerSave) { + AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsTimelineTimerDelete, false)); + AddFooter(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsTimeline, false)); + } else { + AddFooter(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsClose, false)); + } +} + +const cTimer *cRecMenuEditTimer::GetOriginalTimer(void) { + return originalTimer; +} + +cTimer cRecMenuEditTimer::GetTimer(void) { + cTimer t; + if (timerActive) + t.SetFlags(tfActive); + else + t.SetFlags(tfNone); + t.SetDay(day); + t.SetStart(start); + t.SetStop(stop); + t.SetPriority(prio); + t.SetLifetime(lifetime); + string newFolder(folder); + string newFile = originalTimer->File(); + size_t found = newFile.find_last_of('~'); + if (found != string::npos) { + string fileName = newFile.substr(found+1); + if (newFolder.size() > 0) + newFile = *cString::sprintf("%s~%s", newFolder.c_str(), fileName.c_str()); + else + newFile = fileName; + } else { + if (newFolder.size() > 0) + newFile = *cString::sprintf("%s~%s", newFolder.c_str(), newFile.c_str()); + } + std::replace(newFile.begin(), newFile.end(), '/', '~'); + t.SetFile(newFile.c_str()); + return t; +} + +/****************************************************************************************** +* Series Timer Menus +******************************************************************************************/ + +// --- cRecMenuSeriesTimer --------------------------------------------------------- +cRecMenuSeriesTimer::cRecMenuSeriesTimer(const cChannel *initialChannel, const cEvent *event, string folder) { + if (!initialChannel) + return; + timerActive = true; + channel = initialChannel->Number(); + dayOfWeek = 127; + priority = MAXPRIORITY; + lifetime = MAXLIFETIME; + CalculateTimes(event); + this->folder = folder; + + SetMenuWidth(70); + string line1 = tr("Create Series Timer based on"); + string line2 = *cString::sprintf("\"%s\"", event->Title()); + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + + AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, &timerActive)); + AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel"), (cChannel*)initialChannel, false, &channel)); + AddMenuItem(new cRecMenuItemTime(tr("Series Timer start time"), start, false, &start)); + AddMenuItem(new cRecMenuItemTime(tr("Series Timer stop time"), stop, false, &stop)); + AddMenuItem(new cRecMenuItemDayChooser(tr("Days to record"), dayOfWeek, false, &dayOfWeek)); + AddMenuItem(new cRecMenuItemDay(tr("Day to start"), tstart, false, &tstart)); + AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, MAXPRIORITY, false, &priority)); + AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime)); + + AddFooter(new cRecMenuItemButtonYesNo(tr("Create Timer"), tr("Cancel"), rmsSeriesTimerCreate, rmsClose, true)); +} + +cTimer *cRecMenuSeriesTimer::GetTimer(void) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cTimer *seriesTimer = new cTimer(NULL, NULL, Channels->GetByNumber(channel)); +#else + cTimer *seriesTimer = new cTimer(NULL, NULL, Channels.GetByNumber(channel)); +#endif + cString fileName = "TITLE EPISODE"; + if (folder.size() > 0) { + std::replace(folder.begin(), folder.end(), '/', '~'); + fileName = cString::sprintf("%s~%s", folder.c_str(), *fileName); + } + seriesTimer->SetDay(tstart); + seriesTimer->SetStart(start); + seriesTimer->SetStop(stop); + seriesTimer->SetPriority(priority); + seriesTimer->SetLifetime(lifetime); + seriesTimer->SetWeekDays(dayOfWeek); + seriesTimer->SetFile(*fileName); + if (timerActive) + seriesTimer->SetFlags(tfActive); + else + seriesTimer->SetFlags(tfNone); + return seriesTimer; +} + +void cRecMenuSeriesTimer::CalculateTimes(const cEvent *event) { + tstart = event->StartTime(); + tstart -= Setup.MarginStart * 60; + time_t tstop = tstart + event->Duration(); + tstop += Setup.MarginStop * 60; + + struct tm tm_r; + struct tm *time = localtime_r(&tstart, &tm_r); + start = time->tm_hour * 100 + time->tm_min; + time = localtime_r(&tstop, &tm_r); + stop = time->tm_hour * 100 + time->tm_min; + if (stop >= 2400) + stop -= 2400; +} + +// --- cRecMenuConfirmSeriesTimer --------------------------------------------------------- +cRecMenuConfirmSeriesTimer::cRecMenuConfirmSeriesTimer(cTimer *seriesTimer) { + SetMenuWidth(50); + string line1 = tr("Series Timer created"); + string line2 = ""; + if (seriesTimer) { + cString days = cTimer::PrintDay(seriesTimer->Day(), seriesTimer->WeekDays(), true); + line2 = cString::sprintf("%s, %s: %s, %s: %s", *days, tr("Start"), *TimeString(seriesTimer->StartTime()), tr("Stop"), *TimeString(seriesTimer->StopTime())); + } + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +/****************************************************************************************** +* SearchTimer Menus +******************************************************************************************/ + +// --- cRecMenuSearchTimer --------------------------------------------------------- +cRecMenuSearchTimer::cRecMenuSearchTimer(const cEvent *event) { + SetMenuWidth(70); + string message = tr("Configure Search Timer based on"); + string infoText = *cString::sprintf("\"%s\"", event->Title()); + AddHeader(new cRecMenuItemInfo(message, 2, infoText)); + strncpy(searchString, event->Title(), TEXTINPUTLENGTH); + AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false)); + AddFooter(new cRecMenuItemButtonYesNo(tr("Continue"), tr("Cancel"), rmsSearchTimerOptions, rmsClose, true)); +} + +// --- cRecMenuSearchTimerTemplates --------------------------------------------------------- +cRecMenuSearchTimerTemplates::cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, vector templates) { + SetMenuWidth(70); + this->searchTimer = searchTimer; + this->templates = templates; + string message = tr("Configure Search Timer for Search String"); + AddHeader(new cRecMenuItemInfo(message, 2, searchTimer.SearchString())); + AddMenuItem(new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, true)); + + numTemplates = templates.size(); + for (int i=0; i= 0 && tmplActive < (int)templates.size()) + templ = templates[tmplActive]; + return templ; +} + +// --- cRecMenuSearchTimers --------------------------------------------------------- +cRecMenuSearchTimers::cRecMenuSearchTimers(std::vector searchTimers) { + SetMenuWidth(70); + this->searchTimers = searchTimers; + numSearchTimers = searchTimers.size(); + string headline; + if (numSearchTimers > 0) { + headline = tr("EPGSearch Search Timers"); + } else { + headline = tr("No Search Timers Configured"); + } + AddHeader(new cRecMenuItemInfo(headline)); + cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (!numSearchTimers)?true:false); + if (numSearchTimers > 0) { + SetMenuItems(); + AddFooter(button); + } else { + AddMenuItem(button); + } +} + +void cRecMenuSearchTimers::SetMenuItems(void) { + for (int i = 0; i < numSearchTimers; i++) { + AddMenuItem(new cRecMenuItemSearchTimer(searchTimers[i], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, (i==0)?true:false)); + } +} + +cTVGuideSearchTimer cRecMenuSearchTimers::GetSearchTimer(void) { + cRecMenuItemSearchTimer *activeItem = dynamic_cast(GetActive()); + return activeItem->GetTimer(); +} + +// --- cRecMenuSearchTimerEdit --------------------------------------------------------- +cRecMenuSearchTimerEdit::cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions) { + this->advancedOptions = advancedOptions; + this->searchTimer = searchTimer; + strncpy(searchString, searchTimer.SearchString().c_str(), TEXTINPUTLENGTH); + timerActive = searchTimer.Active(); + mode = searchTimer.SearchMode(); + useTitle = searchTimer.UseTitle(); + useSubtitle = searchTimer.UseSubtitle(); + useDescription = searchTimer.UseDescription(); + useChannel = searchTimer.UseChannel(); + startChannel = searchTimer.StartChannel(); + stopChannel = searchTimer.StopChannel(); + useTime = searchTimer.UseTime(); + startTime = searchTimer.StartTime(); + stopTime = searchTimer.StopTime(); + useDayOfWeek = searchTimer.UseDayOfWeek(); + dayOfWeek = searchTimer.DayOfWeek(); + priority = searchTimer.Priority(); + lifetime = searchTimer.Lifetime(); + useEpisode = searchTimer.UseEpisode(); + std::string dir = searchTimer.Directory(); + strncpy(directory, dir.c_str(), TEXTINPUTLENGTH); + marginStart = searchTimer.MarginStart(); + marginStop = searchTimer.MarginStop(); + useVPS = searchTimer.UseVPS(); + avoidRepeats = searchTimer.AvoidRepeats(); + allowedRepeats = searchTimer.AllowedRepeats(); + compareTitle = searchTimer.CompareTitle(); + compareSubtitle = searchTimer.CompareSubtitle(); + compareSummary = searchTimer.CompareSummary(); + useInFavorites = searchTimer.UseInFavorites(); + + SetMenuWidth(70); + string infoText; + if (searchTimer.GetID() > -1) { + infoText = tr("Configure Search Timer Options"); + } else { + infoText = tr("Create Search Timer"); + } + AddHeader(new cRecMenuItemInfo(infoText)); + cRecMenuItemButtonYesNo *footerButton = new cRecMenuItemButtonYesNo(tr("Save Search Timer"), tr("Cancel"), rmsSearchTimerSave, rmsSearchTimers, false); + AddFooter(footerButton); + CreateMenuItems(); +} + +void cRecMenuSearchTimerEdit::CreateMenuItems(void) { + AddMenuItem(new cRecMenuItemText(tr("Search String"), searchString, TEXTINPUTLENGTH, true, searchString)); + AddMenuItem(new cRecMenuItemBool(tr("Active"), timerActive, false, &timerActive, rmsSearchTimerSave)); + vector searchModes; + searchTimer.GetSearchModes(&searchModes); + esyslog("tvguideng: num search modes %ld", searchModes.size()); + AddMenuItem(new cRecMenuItemSelect(tr("Search Mode"), searchModes, mode, false, &mode, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Use Title"), useTitle, false, &useTitle, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Use Subtitle"), useSubtitle, false, &useSubtitle, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Use Description"), useDescription, false, &useDescription, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Limit Channels"), useChannel, false, &useChannel, rmsSearchTimerSave)); + if (startChannel == 0) + startChannel = 1; + if (stopChannel == 0) + stopChannel = 1; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + AddMenuItem(new cRecMenuItemChannelChooser(tr("Start Channel"), Channels->GetByNumber(startChannel), false, &startChannel, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemChannelChooser(tr("Stop Channel"), Channels->GetByNumber(stopChannel), false, &stopChannel, rmsSearchTimerSave)); +#else + AddMenuItem(new cRecMenuItemChannelChooser(tr("Start Channel"), Channels.GetByNumber(startChannel), false, &startChannel, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemChannelChooser(tr("Stop Channel"), Channels.GetByNumber(stopChannel), false, &stopChannel, rmsSearchTimerSave)); +#endif + AddMenuItem(new cRecMenuItemBool(tr("Use Time"), useTime, false, &useTime, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemTime(tr("Start after"), startTime, false, &startTime, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemTime(tr("Start before"), stopTime, false, &stopTime, rmsSearchTimerSave)); + + if (!advancedOptions) { + AddMenuItem(new cRecMenuItemButton(tr("Display advanced Options"), rmsSearchTimerEditAdvanced, false)); + } else { + AddMenuItem(new cRecMenuItemBool(tr("Limit Days of the Week"), useDayOfWeek, false, &useDayOfWeek, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemDayChooser(tr("Select Days"), dayOfWeek, false, &dayOfWeek)); + AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, 99, false, &priority, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, 99, false, &lifetime, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemInt(tr("Time margin for start in minutes"), marginStart, 0, 30, false, &marginStart, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemInt(tr("Time margin for stop in minutes"), marginStop, 0, 30, false, &marginStop, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Series Recording"), useEpisode, false, &useEpisode, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemSelectDirectory(tr("Folder"), string(directory), false, directory, rmsSearchTimerSave, true)); + AddMenuItem(new cRecMenuItemBool(tr("Use VPS"), useVPS, false, &useVPS, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Avoid Repeats"), avoidRepeats, false, &avoidRepeats, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemInt(tr("Number of allowed repeats"), allowedRepeats, 0, 30, false, &allowedRepeats, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Compare Title"), compareTitle, false, &compareTitle, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Compare Subtitle"), compareSubtitle, false, &compareSubtitle, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Compare Description"), compareSummary, false, &compareSummary, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemBool(tr("Use in Favorites"), useInFavorites, false, &useInFavorites, rmsSearchTimerSave)); + AddMenuItem(new cRecMenuItemButton(tr("Hide advanced Options"), rmsSearchTimerEdit, false)); + } + + AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, false)); +} + +cTVGuideSearchTimer cRecMenuSearchTimerEdit::GetSearchTimer(void) { + searchTimer.SetSearchString(searchString); + searchTimer.SetActive(timerActive); + searchTimer.SetSearchMode(mode); + searchTimer.SetUseTitle(useTitle); + searchTimer.SetUseSubtitle(useSubtitle); + searchTimer.SetUseDesription(useDescription); + searchTimer.SetUseChannel(useChannel); + if (useChannel) { + searchTimer.SetStartChannel(startChannel); + searchTimer.SetStopChannel(stopChannel); + } + searchTimer.SetUseTime(useTime); + if (useTime) { + searchTimer.SetStartTime(startTime); + searchTimer.SetStopTime(stopTime); + } + searchTimer.SetUseDayOfWeek(useDayOfWeek); + if (useDayOfWeek) { + searchTimer.SetDayOfWeek(dayOfWeek); + } + searchTimer.SetPriority(priority); + searchTimer.SetLifetime(lifetime); + searchTimer.SetUseEpisode(useEpisode); + string dir(directory); + std::replace(dir.begin(), dir.end(), '/', '~'); + searchTimer.SetDirectory(dir); + searchTimer.SetMarginStart(marginStart); + searchTimer.SetMarginStop(marginStop); + searchTimer.SetUseVPS(useVPS); + searchTimer.SetAvoidRepeats(avoidRepeats); + if (avoidRepeats) { + searchTimer.SetAllowedRepeats(allowedRepeats); + searchTimer.SetCompareTitle(compareTitle); + searchTimer.SetCompareSubtitle(compareSubtitle); + searchTimer.SetCompareSummary(compareSummary); + } + searchTimer.SetUseInFavorites(useInFavorites); + return searchTimer; +} + +// --- cRecMenuSearchTimerDeleteConfirm --------------------------------------------- +cRecMenuSearchTimerDeleteConfirm::cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer) { + SetMenuWidth(70); + this->searchTimer = searchTimer; + string line1 = tr("Really delete Search Timer"); + string line2 = *cString::sprintf("\"%s\"?", searchTimer.SearchString().c_str()); + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + AddMenuItem(new cRecMenuItemButton(tr("Delete only Search Timer"), rmsSearchTimerDelete, true)); + AddMenuItem(new cRecMenuItemButton(tr("Delete Search Timer and created Timers"), rmsSearchTimerDeleteWithTimers, false)); + AddFooter(new cRecMenuItemButton(tr("Cancel"), rmsClose, false)); +} + +cTVGuideSearchTimer cRecMenuSearchTimerDeleteConfirm::GetSearchTimer(void) { + return searchTimer; +} + +// --- cRecMenuSearchTimerCreateConfirm --------------------------------------------------------- +cRecMenuSearchTimerCreateConfirm::cRecMenuSearchTimerCreateConfirm(bool success) { + SetMenuWidth(50); + cRecMenuItemInfo *infoItem = NULL; + if (success) { + string line1 = tr("Search Timer sucessfully created"); + string line2 = tr("Search Timer update initialised"); + infoItem = new cRecMenuItemInfo(line1, 2, line2); + } else { + string line1 = tr("Search Timer NOT sucessfully created"); + infoItem = new cRecMenuItemInfo(line1); + } + AddHeader(infoItem); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuSearchTimerTemplatesCreate --------------------------------------------------------- +cRecMenuSearchTimerTemplatesCreate::cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer) { + SetMenuWidth(70); + this->templ = templ; + this->searchTimer = searchTimer; + + string line1 = tr("Creating Search Timer"); + string line2 = *cString::sprintf("%s: \"%s\"", tr("Search Term"), searchTimer.SearchString().c_str()); + string line3 = *cString::sprintf("%s \"%s\"", tr("Using Template"), templ.name.c_str()); + + AddHeader(new cRecMenuItemInfo(line1, 3, line2, line3)); + AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, true)); + AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Search Timer"), tr("Use other Template"), rmsSearchTimerSave, rmsSearchTimerOptions, false)); +} + + +// --- cRecMenuSearchTimerResults --------------------------------------------------------- +cRecMenuSearchTimerResults::cRecMenuSearchTimerResults(string searchString, const cEvent **searchResults, int numResults, string templateName, eRecMenuState action2) { + SetMenuWidth(70); + this->searchResults = searchResults; + this->action2 = action2; + this->numResults = numResults; + string message1 = "", message2 = "", message3 = ""; + if (action2 == rmsFavoritesRecord) { + message1 = tr("search results for Favorite"); + message2 = tr("search result for Favorite"); + } else { + message1 = tr("search results for Search Timer"); + message2 = tr("search result for Search Timer"); + message3 = tr("Using Template"); + } + cRecMenuItem *infoItem = NULL; + if (templateName.size() > 0) { + string line1 = *cString::sprintf("%d %s:", numResults, (numResults>1)?(message1.c_str()):(message2.c_str())); + string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); + string line3 = *cString::sprintf("%s \"%s\"", message3.c_str(), templateName.c_str()); + infoItem = new cRecMenuItemInfo(line1, 3, line2, line3); + } else { + string line1 = *cString::sprintf("%d %s:", numResults, (numResults>1)?(message1.c_str()):(message2.c_str())); + string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); + infoItem = new cRecMenuItemInfo(line1, 2, line2); + } + AddHeader(infoItem); + + cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, false); + if (searchResults && (numResults > 0)) { + for (int i=0; i(GetActive())) + ev = activeItem->GetEvent(); + return ev; +} + +// --- cRecMenuSearchTimerNothingFound --------------------------------------------------------- +cRecMenuSearchTimerNothingFound::cRecMenuSearchTimerNothingFound(string searchString) { + SetMenuWidth(50); + string line1 = tr("Nothing found for Search String"); + string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +/****************************************************************************************** +* SwitchTimer Menus +******************************************************************************************/ + +// --- cRecMenuSwitchTimer --------------------------------------------------------- +cRecMenuSwitchTimer::cRecMenuSwitchTimer(void) { + SetMenuWidth(60); + switchMinsBefore = config.switchMinsBefore; + announceOnly = 0; + + AddHeader(new cRecMenuItemInfo(tr("Configure Options for Switchtimer"))); + AddMenuItem(new cRecMenuItemInt(tr("Minutes before switching"), switchMinsBefore, 0, 10, false, &switchMinsBefore)); + vector switchModes; + switchModes.push_back(tr("switch")); + switchModes.push_back(tr("announce only")); + switchModes.push_back(tr("ask for switch")); + AddMenuItem(new cRecMenuItemSelect(tr("Switch Mode"), switchModes, announceOnly, false, &announceOnly)); + + AddFooter(new cRecMenuItemButtonYesNo(tr("Create"), tr("Cancel"), rmsSwitchTimerCreate, rmsClose, true)); +} + +cSwitchTimer cRecMenuSwitchTimer::GetSwitchTimer(void) { + cSwitchTimer st; + st.switchMinsBefore = switchMinsBefore; + st.announceOnly = announceOnly; + return st; +} + +// --- cRecMenuSwitchTimerConfirm --------------------------------------------------------- +cRecMenuSwitchTimerConfirm::cRecMenuSwitchTimerConfirm(bool success) { + SetMenuWidth(50); + string message1 = tr("Switch Timer sucessfully created"); + string message2 = tr("Switch Timer NOT sucessfully created"); + string infoText = success?message1:message2; + AddHeader(new cRecMenuItemInfo(infoText)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuSwitchTimerDelete --------------------------------------------------------- +cRecMenuSwitchTimerDelete::cRecMenuSwitchTimerDelete(void) { + SetMenuWidth(50); + AddHeader(new cRecMenuItemInfo(tr("Switch Timer deleted"))); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +/****************************************************************************************** +* Search Menus +******************************************************************************************/ + +// --- cRecMenuSearch --------------------------------------------------------- +cRecMenuSearch::cRecMenuSearch(string searchString, bool withOptions) { + SetMenuWidth(60); + strncpy(this->searchString, searchString.c_str(), TEXTINPUTLENGTH); + mode = 0; + channelNr = 0; + useTitle = true; + useSubTitle = true; + useDescription = false; + + AddHeader(new cRecMenuItemInfo(tr("Search"))); + AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), this->searchString, TEXTINPUTLENGTH, false, this->searchString)); + + if (withOptions) { + vector searchModes; + cTVGuideSearchTimer searchTimer; + searchTimer.GetSearchModes(&searchModes); + AddMenuItem(new cRecMenuItemSelect(tr("Search Mode"), searchModes, 0, false, &mode)); + AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel to Search"), NULL, false, &channelNr)); + AddMenuItem(new cRecMenuItemBool(tr("Search in title"), true, false, &useTitle)); + AddMenuItem(new cRecMenuItemBool(tr("Search in Subtitle"), true, false, &useSubTitle)); + AddMenuItem(new cRecMenuItemBool(tr("Search in Description"), false, false, &useDescription)); + } else { + AddMenuItem(new cRecMenuItemButton(tr("Show Search Options"), rmsSearchWithOptions, false)); + } + + cRecMenuItemButtonYesNo *button = new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsSearchPerform, rmsClose, true); + AddFooter(button); +} + +Epgsearch_searchresults_v1_0 cRecMenuSearch::GetEPGSearchStruct(void) { + Epgsearch_searchresults_v1_0 data; + data.query = searchString; + data.mode = mode; + data.channelNr = channelNr; + data.useTitle = useTitle; + data.useSubTitle = useSubTitle; + data.useDescription = useDescription; + return data; +} + +// --- cRecMenuSearchResults --------------------------------------------------------- +cRecMenuSearchResults::cRecMenuSearchResults(string searchString, const cEvent **searchResults, int numResults) { + this->searchResults = searchResults; + SetMenuWidth(70); + this->searchString = searchString; + this->numResults = numResults; + + string message = ""; + if (numResults > 1) { + message = *cString::sprintf("%d %s", numResults, tr("search results for")); + } else { + message = *cString::sprintf("%d %s", numResults, tr("search result for")); + } + string searchStringQuoted = *cString::sprintf("\"%s\"", searchString.c_str()); + AddHeader(new cRecMenuItemInfo(message, 2, searchStringQuoted)); + + cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsSearch, rmsClose, false); + AddFooter(buttons); + if (searchResults && (numResults > 0)) { + for (int i=0; i(GetActive()); + if (activeItem) + return activeItem->GetEvent(); + return NULL; +} + +// --- cRecMenuSearchNothingFound --------------------------------------------------------- +cRecMenuSearchNothingFound::cRecMenuSearchNothingFound(string searchString, bool tooShort) { + SetMenuWidth(50); + string text; + if (!tooShort) { + cString message = tr("Nothing found for Search String"); + text = *cString::sprintf("%s\n\"%s\"", + *message, + searchString.c_str()); + } else { + cString message = tr("Search String has to have at least three letters"); + text = *cString::sprintf("%s\n\"%s\"", + *message, + searchString.c_str()); + + } + AddHeader(new cRecMenuItemInfo(text)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +// --- cRecMenuSearchConfirmTimer --------------------------------------------------------- +cRecMenuSearchConfirmTimer::cRecMenuSearchConfirmTimer(const cEvent *event) { + SetMenuWidth(50); + + string message = tr("Timer created"); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + cString channelName = Channels->GetByChannelID(event->ChannelID())->Name(); +#else + cString channelName = Channels.GetByChannelID(event->ChannelID())->Name(); +#endif + string line3 = *cString::sprintf("%s %s - %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString()); + string line4 = event->Title() ? event->Title() : ""; + + AddHeader(new cRecMenuItemInfo(message, 4, *channelName, line3, line4)); + AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true)); +} + +/****************************************************************************************** +* Timeline +******************************************************************************************/ + +// --- cRecMenuTimeline --------------------------------------------------------- +cRecMenuTimeline::cRecMenuTimeline(void) { + SetMenuWidth(95); + SetStartStop(); + GetTimersForDay(); + + timelineHeader = new cRecMenuItemTimelineHeader(timeStart); + AddHeader(timelineHeader); + + timelineFooter = new cRecMenuItemButton(tr("Close"), rmsClose, false); + AddFooter(timelineFooter); + SetTimers(); +} + +void cRecMenuTimeline::SetHeaderTimer(void) { + const cTimer *currentTimer = NULL; + cRecMenuItem *currentItem = GetActive(); + if (!currentItem) { + timelineHeader->UnsetCurrentTimer(); + return; + } + if (cRecMenuItemTimelineTimer *myActiveItem = dynamic_cast(currentItem)) { + currentTimer = myActiveItem->GetTimer(); + } + timelineHeader->SetCurrentTimer(currentTimer); + timelineHeader->SetNew(); +} + +void cRecMenuTimeline::SetStartStop(void) { + time_t now = time(0); + tm *timeStruct = localtime(&now); + timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec; + today = timeStart; + timeStop = timeStart + 24*3600 - 1; +} + +void cRecMenuTimeline::GetTimersForDay(void) { + timersToday.clear(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + for (const cTimer *t = timers->First(); t; t = timers->Next(t)) { + if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) { + timersToday.push_back(t); + } + } + numTimersToday = timersToday.size(); +} + +void cRecMenuTimeline::SetTimers(void) { + if (numTimersToday == 0) { + AddMenuItem(new cRecMenuItemInfo(tr("No active Timers"))); + timelineFooter->SetActive(); + } else { + for (int i=0; iSetInactive(); + } +} + +void cRecMenuTimeline::PrevDay(void) { + if ((timeStart - 3600*24) < today) + return; + timeStart -= 3600*24; + timeStop -= 3600*24; + ClearMenuItems(true); + GetTimersForDay(); + SetTimers(); + InitMenuItems(); + SetHeaderTimer(); + timelineHeader->SetDay(timeStart); + timelineHeader->SetNew(); +} + +void cRecMenuTimeline::NextDay(void) { + timeStart += 3600*24; + timeStop += 3600*24; + ClearMenuItems(true); + GetTimersForDay(); + SetTimers(); + InitMenuItems(); + SetHeaderTimer(); + timelineHeader->SetDay(timeStart); + timelineHeader->SetNew(); +} + +const cTimer *cRecMenuTimeline::GetTimer(void) { + if (cRecMenuItemTimelineTimer *activeItem = dynamic_cast(GetActive())) + return activeItem->GetTimer(); + return NULL; +} + + +eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) { + eRecMenuState state = rmsContinue; + switch (Key & ~k_Repeat) { + case kLeft: + PrevDay(); + Draw(); + break; + state = rmsConsumed; + case kRight: + NextDay(); + Draw(); + state = rmsConsumed; + break; + case kUp: { + if (ScrollUp(false)) { + SetHeaderTimer(); + Draw(); + } + state = rmsConsumed; + break; } + case kDown: { + if (ScrollDown(false)) { + SetHeaderTimer(); + Draw(); + } + state = rmsConsumed; + break; } + default: + break; + } + if (state != rmsConsumed) { + state = cRecMenu::ProcessKey(Key); + } + return state; +} + +/****************************************************************************************** +* Recording Search Menus +******************************************************************************************/ + +// --- cRecMenuRecordingSearch --------------------------------------------------------- +cRecMenuRecordingSearch::cRecMenuRecordingSearch(string search) { + SetMenuWidth(60); + strncpy(searchString, search.c_str(), TEXTINPUTLENGTH); + AddHeader(new cRecMenuItemInfo(tr("Search in Recordings"))); + AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false, searchString)); + AddMenuItem(new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsRecordingSearchResult, rmsClose, true)); +} + +// --- cRecMenuRecordingSearchResults --------------------------------------------------------- +cRecMenuRecordingSearchResults::cRecMenuRecordingSearchResults(string searchString, const cRecording **searchResults, int numResults) { + SetMenuWidth(80); + this->searchString = searchString; + this->searchResults = searchResults; + this->numResults = numResults; + string line1 = *cString::sprintf("%s %d %s %s:", tr("Found"), numResults, (numResults>1)?tr("recordings"):tr("recording"), tr("for")); + string line2 = *cString::sprintf("\"%s\"", searchString.c_str()); + AddHeader(new cRecMenuItemInfo(line1, 2, line2)); + + if (searchResults && (numResults > 0)) { + for (int i=0; i favorites) { + SetMenuWidth(70); + this->favorites = favorites; + + CreateFavoritesMenuItems(); + + string header; + if (numFavorites > 0) { + header = tr("Favorites"); + } else { + header = tr("No Favorites available"); + } + AddHeader(new cRecMenuItemInfo(header)); + cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (numFavorites==0)?true:false); + if (numFavorites != 0) + AddFooter(button); + else + AddMenuItem(button); +} + +void cRecMenuFavorites::CreateFavoritesMenuItems(void) { + bool active = true; + if (config.favWhatsOnNow) { + AddMenuItem(new cRecMenuItemFavoriteStatic(tr("What's on now"), rmsFavoritesNow, active)); + active = false; + numFavorites++; + } + if (config.favWhatsOnNext) { + AddMenuItem(new cRecMenuItemFavoriteStatic(tr("What's on next"), rmsFavoritesNext, active)); + active = false; + numFavorites++; + } + if (config.favUseTime1) { + string desc = *cString::sprintf("%s (%s)", config.descUser1.c_str(), NiceTime(config.favTime1).c_str()); + AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser1, active)); + active = false; + numFavorites++; + } + if (config.favUseTime2) { + string desc = *cString::sprintf("%s (%s)", config.descUser2.c_str(), NiceTime(config.favTime2).c_str()); + AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser2, active)); + active = false; + numFavorites++; + } + if (config.favUseTime3) { + string desc = *cString::sprintf("%s (%s)", config.descUser3.c_str(), NiceTime(config.favTime3).c_str()); + AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser3, active)); + active = false; + numFavorites++; + } + if (config.favUseTime4) { + string desc = *cString::sprintf("%s (%s)", config.descUser4.c_str(), NiceTime(config.favTime4).c_str()); + AddMenuItem(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser4, active)); + active = false; + numFavorites++; + } + + int numAdditionalFavs = favorites.size(); + for (int i = 0; i < numAdditionalFavs; i++) { + AddMenuItem(new cRecMenuItemFavorite(favorites[i], rmsSearchTimerTest, active)); + active = false; + numFavorites++; + } +} + +string cRecMenuFavorites::NiceTime(int favTime) { + int hours = favTime/100; + int mins = favTime - hours * 100; + return *cString::sprintf("%02d:%02d", hours, mins); +} + +cTVGuideSearchTimer cRecMenuFavorites::GetFavorite(void) { + cRecMenuItemFavorite *activeItem = dynamic_cast(GetActive()); + return activeItem->GetFavorite(); +} diff --git a/recmenus.h b/recmenus.h index ad2bf8d..9b452d1 100644 --- a/recmenus.h +++ b/recmenus.h @@ -1,451 +1,451 @@ -#ifndef __TVGUIDE_RECMENUS_H -#define __TVGUIDE_RECMENUS_H - -#define TEXTINPUTLENGTH 256 - -#include "services/epgsearch.h" -#include "recmenu.h" -#include "recmanager.h" -#include "timerconflict.h" -#include "switchtimer.h" - -// --- cRecMenuMain --------------------------------------------------------- -class cRecMenuMain : public cRecMenu { -private: - int intcallback; - bool boolcallback; - int stringselectcallback; - char searchString[TEXTINPUTLENGTH]; - int timecallback; - time_t daycallback; -public: - cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive); - virtual ~cRecMenuMain(void) {}; -}; - -/****************************************************************************************** -* Instant Timer Menus -******************************************************************************************/ - -// --- cRecMenuConfirmTimer --------------------------------------------------------- -class cRecMenuConfirmTimer: public cRecMenu { -public: - cRecMenuConfirmTimer(const cEvent *event); - virtual ~cRecMenuConfirmTimer(void) {}; -}; - -// --- cRecMenuAskFolder --------------------------------------------------------- -class cRecMenuAskFolder: public cRecMenu { -private: - vector folders; - eRecMenuState nextAction; -public: - cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction); - virtual ~cRecMenuAskFolder(void) {}; - string GetFolder(void); -}; - -// --- cRecMenuConfirmDeleteTimer --------------------------------------------------------- -class cRecMenuConfirmDeleteTimer: public cRecMenu { -public: - cRecMenuConfirmDeleteTimer(const cEvent *event); - virtual ~cRecMenuConfirmDeleteTimer(void) {}; -}; - -// --- cRecMenuAskDeleteTimer --------------------------------------------------------- -class cRecMenuAskDeleteTimer: public cRecMenu { -public: - cRecMenuAskDeleteTimer(const cEvent *event); - virtual ~cRecMenuAskDeleteTimer(void) {}; -}; - -// --- cRecMenuTimerConflicts --------------------------------------------------------- -class cRecMenuTimerConflicts: public cRecMenu { -public: - cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts); - virtual ~cRecMenuTimerConflicts(void) {}; - int GetTimerConflict(void); -}; - -// --- cRecMenuTimerConflict --------------------------------------------------------- -class cRecMenuTimerConflict: public cRecMenu { -private: - cTVGuideTimerConflict *conflict; -public: - cRecMenuTimerConflict(cTVGuideTimerConflict *conflict); - virtual ~cRecMenuTimerConflict(void) {}; - int GetTimerConflictIndex(void); -}; - -// --- cRecMenuNoTimerConflict --------------------------------------------------------- -class cRecMenuNoTimerConflict: public cRecMenu { -public: - cRecMenuNoTimerConflict(void); - virtual ~cRecMenuNoTimerConflict(void) {}; -}; - -// --- cRecMenuRerunResults --------------------------------------------------------- -class cRecMenuRerunResults: public cRecMenu { -private: - const cEvent **reruns; - int numReruns; -public: - cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns); - int GetTotalNumMenuItems(void); - virtual ~cRecMenuRerunResults(void) { - delete[] reruns; - }; - const cEvent *GetEvent(void); -}; - -// --- cRecMenuNoRerunsFound --------------------------------------------------------- -class cRecMenuNoRerunsFound: public cRecMenu { -public: - cRecMenuNoRerunsFound(string searchString); - virtual ~cRecMenuNoRerunsFound(void) {}; -}; - -// --- cRecMenuConfirmRerunUsed --------------------------------------------------------- -class cRecMenuConfirmRerunUsed: public cRecMenu { -public: - cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace); - virtual ~cRecMenuConfirmRerunUsed(void) {}; -}; - -// --- cRecMenuEditTimer --------------------------------------------------------- -class cRecMenuEditTimer: public cRecMenu { -private: - cTimer *originalTimer; - bool timerActive; - time_t day; - int start; - int stop; - int prio; - int lifetime; - char folder[TEXTINPUTLENGTH]; -public: - cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState); - virtual ~cRecMenuEditTimer(void) {}; - cTimer GetTimer(void); - cTimer *GetOriginalTimer(void); -}; - -/****************************************************************************************** -* Series Timer Menus -******************************************************************************************/ - -// --- cRecMenuSeriesTimer --------------------------------------------------------- -class cRecMenuSeriesTimer: public cRecMenu { - string folder; - bool timerActive; - int channel; - time_t tstart; - int start; - int stop; - int dayOfWeek; - int priority; - int lifetime; - void CalculateTimes(const cEvent *event); -public: - cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, string folder); - virtual ~cRecMenuSeriesTimer(void) {}; - cTimer *GetTimer(void); -}; - -// --- cRecMenuConfirmSeriesTimer --------------------------------------------------------- -class cRecMenuConfirmSeriesTimer: public cRecMenu { -public: - cRecMenuConfirmSeriesTimer(cTimer *seriesTimer); - virtual ~cRecMenuConfirmSeriesTimer(void) {}; -}; - -/****************************************************************************************** -* SearchTimer Menus -******************************************************************************************/ - -// --- cRecMenuSearchTimer --------------------------------------------------------- -class cRecMenuSearchTimer: public cRecMenu { -private: - char searchString[TEXTINPUTLENGTH]; -public: - cRecMenuSearchTimer(const cEvent *event); - virtual ~cRecMenuSearchTimer(void) {}; - string GetSearchString(void) { return searchString; }; -}; - -// --- cRecMenuSearchTimerTemplates --------------------------------------------------------- -class cRecMenuSearchTimerTemplates: public cRecMenu { -private: - int numTemplates; - cTVGuideSearchTimer searchTimer; - vector templates; -public: - cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, vector templates); - virtual ~cRecMenuSearchTimerTemplates(void) {}; - cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; }; - TVGuideEPGSearchTemplate GetTemplate(void); -}; - -// --- cRecMenuSearchTimers --------------------------------------------------------- -class cRecMenuSearchTimers: public cRecMenu { -private: - int numSearchTimers; - vector searchTimers; - void SetMenuItems(void); -public: - cRecMenuSearchTimers(vector searchTimers); - virtual ~cRecMenuSearchTimers(void) {}; - cTVGuideSearchTimer GetSearchTimer(void); -}; - -// --- cRecMenuSearchTimerEdit --------------------------------------------------------- -class cRecMenuSearchTimerEdit: public cRecMenu { -private: - bool advancedOptions; - cTVGuideSearchTimer searchTimer; - char searchString[TEXTINPUTLENGTH]; - bool timerActive; - int mode; - bool useTitle; - bool useSubtitle; - bool useDescription; - bool useChannel; - int startChannel; - int stopChannel; - bool useTime; - int startTime; - int stopTime; - bool useDayOfWeek; - int dayOfWeek; - int priority; - int lifetime; - bool useEpisode; - char directory[TEXTINPUTLENGTH]; - int marginStart; - int marginStop; - bool useVPS; - bool avoidRepeats; - int allowedRepeats; - bool compareTitle; - bool compareSubtitle; - bool compareSummary; - bool useInFavorites; - void CreateMenuItems(void); -public: - cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions); - virtual ~cRecMenuSearchTimerEdit(void) {}; - cTVGuideSearchTimer GetSearchTimer(void); -}; - -// --- cRecMenuSearchTimerDeleteConfirm --------------------------------------------- -class cRecMenuSearchTimerDeleteConfirm: public cRecMenu { -private: - cTVGuideSearchTimer searchTimer; -public: - cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer); - virtual ~cRecMenuSearchTimerDeleteConfirm(void) {}; - cTVGuideSearchTimer GetSearchTimer(void); -}; - -// --- cRecMenuSearchTimerCreateConfirm --------------------------------------------------------- -class cRecMenuSearchTimerCreateConfirm: public cRecMenu { -private: -public: - cRecMenuSearchTimerCreateConfirm(bool success); - virtual ~cRecMenuSearchTimerCreateConfirm(void) {}; -}; - -// --- cRecMenuSearchTimerTemplatesCreate --------------------------------------------------------- -class cRecMenuSearchTimerTemplatesCreate: public cRecMenu { -private: - TVGuideEPGSearchTemplate templ; - cTVGuideSearchTimer searchTimer; -public: - cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer); - virtual ~cRecMenuSearchTimerTemplatesCreate(void) {}; - cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; }; - TVGuideEPGSearchTemplate GetTemplate(void) { return templ; }; -}; - -// --- cRecMenuSearchTimerResults --------------------------------------------------------- -class cRecMenuSearchTimerResults: public cRecMenu { -private: - const cEvent **searchResults; - int numResults; - eRecMenuState action2; -public: - cRecMenuSearchTimerResults(string searchString, const cEvent **searchResults, int numResults, string templateName = "", eRecMenuState action2 = rmsDisabled); - virtual ~cRecMenuSearchTimerResults(void) { - delete[] searchResults; - }; - const cEvent *GetEvent(void); -}; - -// --- cRecMenuSearchTimerNothingFound --------------------------------------------------------- -class cRecMenuSearchTimerNothingFound: public cRecMenu { -public: - cRecMenuSearchTimerNothingFound(string searchString); - virtual ~cRecMenuSearchTimerNothingFound(void) {}; -}; - -/****************************************************************************************** -* SwitchTimer Menus -******************************************************************************************/ - -// --- cRecMenuSwitchTimer --------------------------------------------------------- -class cRecMenuSwitchTimer: public cRecMenu { -private: - int switchMinsBefore; - int announceOnly; -public: - cRecMenuSwitchTimer(void); - virtual ~cRecMenuSwitchTimer(void) {}; - cSwitchTimer GetSwitchTimer(void); -}; - -// --- cRecMenuSwitchTimerConfirm --------------------------------------------------------- -class cRecMenuSwitchTimerConfirm: public cRecMenu { -private: -public: - cRecMenuSwitchTimerConfirm(bool success); - virtual ~cRecMenuSwitchTimerConfirm(void) {}; -}; - -// --- cRecMenuSwitchTimerDelete --------------------------------------------------------- -class cRecMenuSwitchTimerDelete: public cRecMenu { -private: -public: - cRecMenuSwitchTimerDelete(void); - virtual ~cRecMenuSwitchTimerDelete(void) {}; -}; - -/****************************************************************************************** -* Search Menus -******************************************************************************************/ - -// --- cRecMenuSearch --------------------------------------------------------- -class cRecMenuSearch: public cRecMenu { -private: - char searchString[TEXTINPUTLENGTH]; - int mode; - int channelNr; - bool useTitle; - bool useSubTitle; - bool useDescription; -public: - cRecMenuSearch(string searchString, bool withOptions); - virtual ~cRecMenuSearch(void) {}; - string GetSearchString(void) { return searchString; }; - Epgsearch_searchresults_v1_0 GetEPGSearchStruct(void); -}; - -// --- cRecMenuSearchResults --------------------------------------------------------- -class cRecMenuSearchResults: public cRecMenu { -private: - string searchString; - const cEvent **searchResults; - int numResults; -public: - cRecMenuSearchResults(string searchString, const cEvent **searchResults, int numResults); - virtual ~cRecMenuSearchResults(void) { - delete[] searchResults; - }; - string GetSearchString(void) { return searchString; }; - const cEvent *GetEvent(void); -}; - -// --- cRecMenuSearchNothingFound --------------------------------------------------------- -class cRecMenuSearchNothingFound: public cRecMenu { -public: - cRecMenuSearchNothingFound(string searchString, bool tooShort = false); - virtual ~cRecMenuSearchNothingFound(void) {}; -}; - -// --- cRecMenuSearchConfirmTimer --------------------------------------------------------- -class cRecMenuSearchConfirmTimer: public cRecMenu { -public: - cRecMenuSearchConfirmTimer(const cEvent *event); - virtual ~cRecMenuSearchConfirmTimer(void) {}; -}; - -/****************************************************************************************** -* Timeline -******************************************************************************************/ - -// --- cRecMenuTimeline --------------------------------------------------------- -class cRecMenuTimeline: public cRecMenu { -private: - vector timersToday; - int numTimersToday; - time_t today; - time_t timeStart; - time_t timeStop; - cRecMenuItemTimelineHeader *timelineHeader; - cRecMenuItem *timelineFooter; - void SetStartStop(void); - void GetTimersForDay(void); - void SetTimers(void); - void PrevDay(void); - void NextDay(void); - void ClearMenu(void); -public: - cRecMenuTimeline(void); - virtual ~cRecMenuTimeline(void) {}; - eRecMenuState ProcessKey(eKeys Key); - void SetHeaderTimer(void); - cTimer *GetTimer(void); -}; - -/****************************************************************************************** -* Recording Search Menus -******************************************************************************************/ - -// --- cRecMenuRecordingSearch --------------------------------------------------------- -class cRecMenuRecordingSearch: public cRecMenu { -private: - char searchString[TEXTINPUTLENGTH]; -public: - cRecMenuRecordingSearch(string search); - virtual ~cRecMenuRecordingSearch(void) {}; - string GetSearchString(void) { return searchString; }; -}; - -// --- cRecMenuRecordingSearchResults --------------------------------------------------------- -class cRecMenuRecordingSearchResults: public cRecMenu { -private: - string searchString; - cRecording **searchResults; - int numResults; -public: - cRecMenuRecordingSearchResults(string searchString, cRecording **searchResults, int numResults); - virtual ~cRecMenuRecordingSearchResults(void) { - delete[] searchResults; - }; - string GetSearchString(void) { return searchString; }; -}; - -// --- cRecMenuRecordingSearchNotFound --------------------------------------------------------- -class cRecMenuRecordingSearchNotFound: public cRecMenu { -public: - cRecMenuRecordingSearchNotFound(string searchString); - virtual ~cRecMenuRecordingSearchNotFound(void) {}; -}; - -/****************************************************************************************** -* Favorites -******************************************************************************************/ - -// --- cRecMenuFavorites --------------------------------------------------------- -class cRecMenuFavorites: public cRecMenu { -private: - vector favorites; - int numFavorites; - void CreateFavoritesMenuItems(void); - string NiceTime(int favTime); -public: - cRecMenuFavorites(vector favorites); - virtual ~cRecMenuFavorites(void) {}; - cTVGuideSearchTimer GetFavorite(void); -}; - -#endif //__TVGUIDE_RECMENUS_H \ No newline at end of file +#ifndef __TVGUIDE_RECMENUS_H +#define __TVGUIDE_RECMENUS_H + +#define TEXTINPUTLENGTH 256 + +#include "services/epgsearch.h" +#include "recmenu.h" +#include "recmanager.h" +#include "timerconflict.h" +#include "switchtimer.h" + +// --- cRecMenuMain --------------------------------------------------------- +class cRecMenuMain : public cRecMenu { +private: + int intcallback; + bool boolcallback; + int stringselectcallback; + char searchString[TEXTINPUTLENGTH]; + int timecallback; + time_t daycallback; +public: + cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive); + virtual ~cRecMenuMain(void) {}; +}; + +/****************************************************************************************** +* Instant Timer Menus +******************************************************************************************/ + +// --- cRecMenuConfirmTimer --------------------------------------------------------- +class cRecMenuConfirmTimer: public cRecMenu { +public: + cRecMenuConfirmTimer(const cEvent *event); + virtual ~cRecMenuConfirmTimer(void) {}; +}; + +// --- cRecMenuAskFolder --------------------------------------------------------- +class cRecMenuAskFolder: public cRecMenu { +private: + vector folders; + eRecMenuState nextAction; +public: + cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction); + virtual ~cRecMenuAskFolder(void) {}; + string GetFolder(void); +}; + +// --- cRecMenuConfirmDeleteTimer --------------------------------------------------------- +class cRecMenuConfirmDeleteTimer: public cRecMenu { +public: + cRecMenuConfirmDeleteTimer(const cEvent *event); + virtual ~cRecMenuConfirmDeleteTimer(void) {}; +}; + +// --- cRecMenuAskDeleteTimer --------------------------------------------------------- +class cRecMenuAskDeleteTimer: public cRecMenu { +public: + cRecMenuAskDeleteTimer(const cEvent *event); + virtual ~cRecMenuAskDeleteTimer(void) {}; +}; + +// --- cRecMenuTimerConflicts --------------------------------------------------------- +class cRecMenuTimerConflicts: public cRecMenu { +public: + cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts); + virtual ~cRecMenuTimerConflicts(void) {}; + int GetTimerConflict(void); +}; + +// --- cRecMenuTimerConflict --------------------------------------------------------- +class cRecMenuTimerConflict: public cRecMenu { +private: + cTVGuideTimerConflict *conflict; +public: + cRecMenuTimerConflict(cTVGuideTimerConflict *conflict); + virtual ~cRecMenuTimerConflict(void) {}; + int GetTimerConflictIndex(void); +}; + +// --- cRecMenuNoTimerConflict --------------------------------------------------------- +class cRecMenuNoTimerConflict: public cRecMenu { +public: + cRecMenuNoTimerConflict(void); + virtual ~cRecMenuNoTimerConflict(void) {}; +}; + +// --- cRecMenuRerunResults --------------------------------------------------------- +class cRecMenuRerunResults: public cRecMenu { +private: + const cEvent **reruns; + int numReruns; +public: + cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns); + int GetTotalNumMenuItems(void); + virtual ~cRecMenuRerunResults(void) { + delete[] reruns; + }; + const cEvent *GetEvent(void); +}; + +// --- cRecMenuNoRerunsFound --------------------------------------------------------- +class cRecMenuNoRerunsFound: public cRecMenu { +public: + cRecMenuNoRerunsFound(string searchString); + virtual ~cRecMenuNoRerunsFound(void) {}; +}; + +// --- cRecMenuConfirmRerunUsed --------------------------------------------------------- +class cRecMenuConfirmRerunUsed: public cRecMenu { +public: + cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace); + virtual ~cRecMenuConfirmRerunUsed(void) {}; +}; + +// --- cRecMenuEditTimer --------------------------------------------------------- +class cRecMenuEditTimer: public cRecMenu { +private: + const cTimer *originalTimer; + bool timerActive; + time_t day; + int start; + int stop; + int prio; + int lifetime; + char folder[TEXTINPUTLENGTH]; +public: + cRecMenuEditTimer(const cTimer *timer, eRecMenuState nextState); + virtual ~cRecMenuEditTimer(void) {}; + cTimer GetTimer(void); + const cTimer *GetOriginalTimer(void); +}; + +/****************************************************************************************** +* Series Timer Menus +******************************************************************************************/ + +// --- cRecMenuSeriesTimer --------------------------------------------------------- +class cRecMenuSeriesTimer: public cRecMenu { + string folder; + bool timerActive; + int channel; + time_t tstart; + int start; + int stop; + int dayOfWeek; + int priority; + int lifetime; + void CalculateTimes(const cEvent *event); +public: + cRecMenuSeriesTimer(const cChannel *initialChannel, const cEvent *event, string folder); + virtual ~cRecMenuSeriesTimer(void) {}; + cTimer *GetTimer(void); +}; + +// --- cRecMenuConfirmSeriesTimer --------------------------------------------------------- +class cRecMenuConfirmSeriesTimer: public cRecMenu { +public: + cRecMenuConfirmSeriesTimer(cTimer *seriesTimer); + virtual ~cRecMenuConfirmSeriesTimer(void) {}; +}; + +/****************************************************************************************** +* SearchTimer Menus +******************************************************************************************/ + +// --- cRecMenuSearchTimer --------------------------------------------------------- +class cRecMenuSearchTimer: public cRecMenu { +private: + char searchString[TEXTINPUTLENGTH]; +public: + cRecMenuSearchTimer(const cEvent *event); + virtual ~cRecMenuSearchTimer(void) {}; + string GetSearchString(void) { return searchString; }; +}; + +// --- cRecMenuSearchTimerTemplates --------------------------------------------------------- +class cRecMenuSearchTimerTemplates: public cRecMenu { +private: + int numTemplates; + cTVGuideSearchTimer searchTimer; + vector templates; +public: + cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, vector templates); + virtual ~cRecMenuSearchTimerTemplates(void) {}; + cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; }; + TVGuideEPGSearchTemplate GetTemplate(void); +}; + +// --- cRecMenuSearchTimers --------------------------------------------------------- +class cRecMenuSearchTimers: public cRecMenu { +private: + int numSearchTimers; + vector searchTimers; + void SetMenuItems(void); +public: + cRecMenuSearchTimers(vector searchTimers); + virtual ~cRecMenuSearchTimers(void) {}; + cTVGuideSearchTimer GetSearchTimer(void); +}; + +// --- cRecMenuSearchTimerEdit --------------------------------------------------------- +class cRecMenuSearchTimerEdit: public cRecMenu { +private: + bool advancedOptions; + cTVGuideSearchTimer searchTimer; + char searchString[TEXTINPUTLENGTH]; + bool timerActive; + int mode; + bool useTitle; + bool useSubtitle; + bool useDescription; + bool useChannel; + int startChannel; + int stopChannel; + bool useTime; + int startTime; + int stopTime; + bool useDayOfWeek; + int dayOfWeek; + int priority; + int lifetime; + bool useEpisode; + char directory[TEXTINPUTLENGTH]; + int marginStart; + int marginStop; + bool useVPS; + bool avoidRepeats; + int allowedRepeats; + bool compareTitle; + bool compareSubtitle; + bool compareSummary; + bool useInFavorites; + void CreateMenuItems(void); +public: + cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions); + virtual ~cRecMenuSearchTimerEdit(void) {}; + cTVGuideSearchTimer GetSearchTimer(void); +}; + +// --- cRecMenuSearchTimerDeleteConfirm --------------------------------------------- +class cRecMenuSearchTimerDeleteConfirm: public cRecMenu { +private: + cTVGuideSearchTimer searchTimer; +public: + cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer); + virtual ~cRecMenuSearchTimerDeleteConfirm(void) {}; + cTVGuideSearchTimer GetSearchTimer(void); +}; + +// --- cRecMenuSearchTimerCreateConfirm --------------------------------------------------------- +class cRecMenuSearchTimerCreateConfirm: public cRecMenu { +private: +public: + cRecMenuSearchTimerCreateConfirm(bool success); + virtual ~cRecMenuSearchTimerCreateConfirm(void) {}; +}; + +// --- cRecMenuSearchTimerTemplatesCreate --------------------------------------------------------- +class cRecMenuSearchTimerTemplatesCreate: public cRecMenu { +private: + TVGuideEPGSearchTemplate templ; + cTVGuideSearchTimer searchTimer; +public: + cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer); + virtual ~cRecMenuSearchTimerTemplatesCreate(void) {}; + cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; }; + TVGuideEPGSearchTemplate GetTemplate(void) { return templ; }; +}; + +// --- cRecMenuSearchTimerResults --------------------------------------------------------- +class cRecMenuSearchTimerResults: public cRecMenu { +private: + const cEvent **searchResults; + int numResults; + eRecMenuState action2; +public: + cRecMenuSearchTimerResults(string searchString, const cEvent **searchResults, int numResults, string templateName = "", eRecMenuState action2 = rmsDisabled); + virtual ~cRecMenuSearchTimerResults(void) { + delete[] searchResults; + }; + const cEvent *GetEvent(void); +}; + +// --- cRecMenuSearchTimerNothingFound --------------------------------------------------------- +class cRecMenuSearchTimerNothingFound: public cRecMenu { +public: + cRecMenuSearchTimerNothingFound(string searchString); + virtual ~cRecMenuSearchTimerNothingFound(void) {}; +}; + +/****************************************************************************************** +* SwitchTimer Menus +******************************************************************************************/ + +// --- cRecMenuSwitchTimer --------------------------------------------------------- +class cRecMenuSwitchTimer: public cRecMenu { +private: + int switchMinsBefore; + int announceOnly; +public: + cRecMenuSwitchTimer(void); + virtual ~cRecMenuSwitchTimer(void) {}; + cSwitchTimer GetSwitchTimer(void); +}; + +// --- cRecMenuSwitchTimerConfirm --------------------------------------------------------- +class cRecMenuSwitchTimerConfirm: public cRecMenu { +private: +public: + cRecMenuSwitchTimerConfirm(bool success); + virtual ~cRecMenuSwitchTimerConfirm(void) {}; +}; + +// --- cRecMenuSwitchTimerDelete --------------------------------------------------------- +class cRecMenuSwitchTimerDelete: public cRecMenu { +private: +public: + cRecMenuSwitchTimerDelete(void); + virtual ~cRecMenuSwitchTimerDelete(void) {}; +}; + +/****************************************************************************************** +* Search Menus +******************************************************************************************/ + +// --- cRecMenuSearch --------------------------------------------------------- +class cRecMenuSearch: public cRecMenu { +private: + char searchString[TEXTINPUTLENGTH]; + int mode; + int channelNr; + bool useTitle; + bool useSubTitle; + bool useDescription; +public: + cRecMenuSearch(string searchString, bool withOptions); + virtual ~cRecMenuSearch(void) {}; + string GetSearchString(void) { return searchString; }; + Epgsearch_searchresults_v1_0 GetEPGSearchStruct(void); +}; + +// --- cRecMenuSearchResults --------------------------------------------------------- +class cRecMenuSearchResults: public cRecMenu { +private: + string searchString; + const cEvent **searchResults; + int numResults; +public: + cRecMenuSearchResults(string searchString, const cEvent **searchResults, int numResults); + virtual ~cRecMenuSearchResults(void) { + delete[] searchResults; + }; + string GetSearchString(void) { return searchString; }; + const cEvent *GetEvent(void); +}; + +// --- cRecMenuSearchNothingFound --------------------------------------------------------- +class cRecMenuSearchNothingFound: public cRecMenu { +public: + cRecMenuSearchNothingFound(string searchString, bool tooShort = false); + virtual ~cRecMenuSearchNothingFound(void) {}; +}; + +// --- cRecMenuSearchConfirmTimer --------------------------------------------------------- +class cRecMenuSearchConfirmTimer: public cRecMenu { +public: + cRecMenuSearchConfirmTimer(const cEvent *event); + virtual ~cRecMenuSearchConfirmTimer(void) {}; +}; + +/****************************************************************************************** +* Timeline +******************************************************************************************/ + +// --- cRecMenuTimeline --------------------------------------------------------- +class cRecMenuTimeline: public cRecMenu { +private: + vector timersToday; + int numTimersToday; + time_t today; + time_t timeStart; + time_t timeStop; + cRecMenuItemTimelineHeader *timelineHeader; + cRecMenuItem *timelineFooter; + void SetStartStop(void); + void GetTimersForDay(void); + void SetTimers(void); + void PrevDay(void); + void NextDay(void); + void ClearMenu(void); +public: + cRecMenuTimeline(void); + virtual ~cRecMenuTimeline(void) {}; + eRecMenuState ProcessKey(eKeys Key); + void SetHeaderTimer(void); + const cTimer *GetTimer(void); +}; + +/****************************************************************************************** +* Recording Search Menus +******************************************************************************************/ + +// --- cRecMenuRecordingSearch --------------------------------------------------------- +class cRecMenuRecordingSearch: public cRecMenu { +private: + char searchString[TEXTINPUTLENGTH]; +public: + cRecMenuRecordingSearch(string search); + virtual ~cRecMenuRecordingSearch(void) {}; + string GetSearchString(void) { return searchString; }; +}; + +// --- cRecMenuRecordingSearchResults --------------------------------------------------------- +class cRecMenuRecordingSearchResults: public cRecMenu { +private: + string searchString; + const cRecording **searchResults; + int numResults; +public: + cRecMenuRecordingSearchResults(string searchString, const cRecording **searchResults, int numResults); + virtual ~cRecMenuRecordingSearchResults(void) { + delete[] searchResults; + }; + string GetSearchString(void) { return searchString; }; +}; + +// --- cRecMenuRecordingSearchNotFound --------------------------------------------------------- +class cRecMenuRecordingSearchNotFound: public cRecMenu { +public: + cRecMenuRecordingSearchNotFound(string searchString); + virtual ~cRecMenuRecordingSearchNotFound(void) {}; +}; + +/****************************************************************************************** +* Favorites +******************************************************************************************/ + +// --- cRecMenuFavorites --------------------------------------------------------- +class cRecMenuFavorites: public cRecMenu { +private: + vector favorites; + int numFavorites; + void CreateFavoritesMenuItems(void); + string NiceTime(int favTime); +public: + cRecMenuFavorites(vector favorites); + virtual ~cRecMenuFavorites(void) {}; + cTVGuideSearchTimer GetFavorite(void); +}; + +#endif //__TVGUIDE_RECMENUS_H diff --git a/recmenuview.c b/recmenuview.c index a4c8ceb..67c4ac4 100644 --- a/recmenuview.c +++ b/recmenuview.c @@ -1,860 +1,897 @@ -#include "tvguidengosd.h" -#include "recmenuview.h" - -cRecMenuView::cRecMenuView(void) { - active = false; - recMenuView = NULL; - recMenuViewBuffer = NULL; - recMenuViewBuffer2 = NULL; - event = NULL; - displayEvent = NULL; - activeMenu = NULL; - activeMenuBuffer = NULL; - activeMenuBuffer2 = NULL; - recManager = new cRecManager(); - recManager->SetEPGSearchPlugin(); - timerConflicts = NULL; -} - -cRecMenuView::~cRecMenuView() { - if (activeMenu) - delete activeMenu; - if (activeMenuBuffer) - delete activeMenuBuffer; - if (activeMenuBuffer2) - delete activeMenuBuffer2; - if (recMenuView) - delete recMenuView; - if (recMenuViewBuffer) - delete recMenuViewBuffer; - if (recMenuViewBuffer2) - delete recMenuViewBuffer2; -} - -void cRecMenuView::Init(skindesignerapi::cOsdView *recMenuView, skindesignerapi::cOsdView *recMenuViewBuffer, skindesignerapi::cOsdView *recMenuViewBuffer2) { - active = true; - this->recMenuView = recMenuView; - this->recMenuViewBuffer = recMenuViewBuffer; - this->recMenuViewBuffer2 = recMenuViewBuffer2; -} - -void cRecMenuView::DisplayRecMenu(const cEvent *event) { - if (!event) { - return; - } - this->event = event; - activeMenu = new cRecMenuMain(recManager->EpgSearchAvailable(), recManager->CheckEventForTimer(event), SwitchTimers.EventInSwitchList(event)); - DisplayMenu(); -} - -void cRecMenuView::DisplayFavorites(void) { - vector favorites; - recManager->GetFavorites(&favorites); - activeMenu = new cRecMenuFavorites(favorites); - DisplayMenu(); -} - -void cRecMenuView::DisplayRecSearch(const cEvent *e) { - activeMenu = new cRecMenuRecordingSearch(e->Title() ? e->Title() : ""); - DisplayMenu(); -} - -void cRecMenuView::DisplaySearchEPG(const cEvent *e) { - activeMenu = new cRecMenuSearch(e->Title() ? e->Title() : "", false); - DisplayMenu(); -} - -void cRecMenuView::Close(void) { - if (activeMenu) { - delete activeMenu; - activeMenu = NULL; - } - if (activeMenuBuffer) { - delete activeMenuBuffer; - activeMenuBuffer = NULL; - } - if (activeMenuBuffer2) { - delete activeMenuBuffer2; - activeMenuBuffer2 = NULL; - } - delete recMenuView; - recMenuView = NULL; - delete recMenuViewBuffer; - recMenuViewBuffer = NULL; - delete recMenuViewBuffer2; - recMenuViewBuffer2 = NULL; - active = false; -} - -void cRecMenuView::Hide(bool full) { - if (recMenuViewBuffer) { - recMenuViewBuffer->Deactivate(true); - if (full) - recMenuView->Deactivate(true); - } else - recMenuView->Deactivate(true); -} - -void cRecMenuView::Activate(bool full) { - if (recMenuViewBuffer) { - recMenuViewBuffer->Activate(); - if (full) - recMenuView->Activate(); - } else - recMenuView->Activate(); -} - -eOSState cRecMenuView::ProcessKey(eKeys Key) { - eOSState state = osContinue; - eRecMenuState nextState = rmsContinue; - if (!activeMenu) - return state; - nextState = activeMenu->ProcessKey(Key); - if ((nextState == rmsClose) || ((nextState == rmsNotConsumed)&&(Key == kBack))) { - if (activeMenuBuffer2) { - delete activeMenu; - activeMenu = activeMenuBuffer2; - activeMenuBuffer2 = NULL; - activeMenu->Show(); - return osContinue; - } else if (activeMenuBuffer) { - delete activeMenu; - activeMenu = activeMenuBuffer; - activeMenuBuffer = NULL; - activeMenu->Show(); - return osContinue; - } else { - Close(); - return osEnd; - } - } - state = StateMachine(nextState); - if (activeMenu) - activeMenu->Flush(); - return state; -} - -void cRecMenuView::DisplayMenu(bool buffer, bool buffer2) { - if (!activeMenu) - return; - if (buffer) { - activeMenu->Init(recMenuViewBuffer); - } else if (buffer2) { - activeMenu->Init(recMenuViewBuffer2); - } else { - activeMenu->Init(recMenuView); - } - if (cRecMenuTimeline *timeline = dynamic_cast(activeMenu)) { - timeline->SetHeaderTimer(); - } - activeMenu->Draw(); -} - -void cRecMenuView::DisplaySearchTimerList(void) { - delete activeMenu; - vector searchTimers; - recManager->GetSearchTimers(&searchTimers); - activeMenu = new cRecMenuSearchTimers(searchTimers); - DisplayMenu(); -} - -bool cRecMenuView::DisplayTimerConflict(cTimer *timer) { - int timerID = 0; - for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) { - if (t == timer) - return DisplayTimerConflict(timerID); - timerID++; - } - return false; -} - -bool cRecMenuView::DisplayTimerConflict(int timerID) { - if (timerConflicts) - delete timerConflicts; - timerConflicts = recManager->CheckTimerConflict(); - if (!timerConflicts) - return false; - int showTimerConflict = timerConflicts->GetCorrespondingConflict(timerID); - if (showTimerConflict > -1) { - timerConflicts->SetCurrentConflict(showTimerConflict); - cTVGuideTimerConflict *conflict = timerConflicts->GetCurrentConflict(); - if (!conflict) - return false; - activeMenu = new cRecMenuTimerConflict(conflict); - DisplayMenu(); - return true; - } - return false; -} - -void cRecMenuView::DisplayFavoriteResults(string header, const cEvent **result, int numResults) { - if (numResults) { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchTimerResults(header, result, numResults, "", rmsFavoritesRecord); - } else { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchTimerNothingFound(header); - } - DisplayMenu(true); -} - -eOSState cRecMenuView::StateMachine(eRecMenuState nextState) { - eOSState state = osContinue; - switch (nextState) { -/*************************************************************************************** -* INSTANT RECORDING -****************************************************************************************/ - case rmsInstantRecord: { - //caller: main menu or folder chooser - //Creating timer for active Event, if no conflict, confirm and exit - string recFolder = ""; - if (cRecMenuAskFolder *menu = dynamic_cast(activeMenu)) { - recFolder = menu->GetFolder(); - } - delete activeMenu; - cTimer *timer = recManager->createTimer(event, recFolder); - if (!DisplayTimerConflict(timer)) { - activeMenu = new cRecMenuConfirmTimer(event); - DisplayMenu(); - } - break; } - case rmsInstantRecordFolder: { - //caller: main menu - //Asking for Folder - delete activeMenu; - activeMenu = new cRecMenuAskFolder(event, rmsInstantRecord); - DisplayMenu(); - break; } - case rmsDeleteTimer: { - //caller: main menu - //delete timer for active event - delete activeMenu; - if (recManager->IsRecorded(event)) { - activeMenu = new cRecMenuAskDeleteTimer(event); - } else { - recManager->DeleteTimer(event); - activeMenu = new cRecMenuConfirmDeleteTimer(event); - } - DisplayMenu(); - break; } - case rmsDeleteTimerConfirmation: { - //delete running timer for active event - recManager->DeleteTimer(event); - delete activeMenu; - activeMenu = new cRecMenuConfirmDeleteTimer(event); - DisplayMenu(); - break; } - case rmsEditTimer: { - //edit timer for active event - cTimer *timer = recManager->GetTimerForEvent(event); - if (timer) { - delete activeMenu; - activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimer); - DisplayMenu(); - } - break; } - case rmsSaveTimer: { - //caller: cRecMenuEditTimer - //save timer for active event - cTimer timerModified; - cTimer *originalTimer; - if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { - timerModified = menu->GetTimer(); - originalTimer = menu->GetOriginalTimer(); - } else break; - recManager->SaveTimer(originalTimer, timerModified); - Close(); - state = osEnd; - break; } - case rmsIgnoreTimerConflict: - //caller: cRecMenuTimerConflict - //Confirming created Timer - delete activeMenu; - activeMenu = new cRecMenuConfirmTimer(event); - DisplayMenu(); - break; - case rmsTimerConflictShowInfo: { - //caller: cRecMenuTimerConflict - int timerIndex; - if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { - timerIndex = menu->GetTimerConflictIndex(); - } else break; - int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); - cTimer *t = Timers.Get(timerID); - if (t) { - displayEvent = t->Event(); - if (displayEvent) { - state = osUser1; - } - } - break; } - case rmsDeleteTimerConflictMenu: { - //caller: cRecMenuTimerConflict - //delete timer out of current timer conflict - int timerIndex; - if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { - timerIndex = menu->GetTimerConflictIndex(); - } else break; - int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); - recManager->DeleteTimer(timerID); - delete activeMenu; - if (!DisplayTimerConflict(timerID)) { - activeMenu = new cRecMenuConfirmTimer(event); - DisplayMenu(); - } - break; } - case rmsEditTimerConflictMenu: { - //caller: cRecMenuTimerConflict - //edit timer out of current timer conflict - int timerIndex; - if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { - timerIndex = menu->GetTimerConflictIndex(); - } else break; - int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); - cTimer *timer = Timers.Get(timerID); - if (timer) { - delete activeMenu; - activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimerConflictMenu); - DisplayMenu(); - } - break; } - case rmsSaveTimerConflictMenu: { - //caller: cRecMenuEditTimer - //save timer from current timer conflict - cTimer timerModified; - cTimer *originalTimer; - if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { - timerModified = menu->GetTimer(); - originalTimer = menu->GetOriginalTimer(); - } else break; - recManager->SaveTimer(originalTimer, timerModified); - delete activeMenu; - if (!DisplayTimerConflict(originalTimer)) { - activeMenu = new cRecMenuConfirmTimer(event); - DisplayMenu(); - } - break; } -/*************************************************************************************** -* SERIES TIMER -****************************************************************************************/ - case rmsSeriesTimer: { - //caller: main menu oder folder chooser - string recFolder = ""; - if (cRecMenuAskFolder *menu = dynamic_cast(activeMenu)) { - recFolder = menu->GetFolder(); - } - delete activeMenu; - cChannel *channel = Channels.GetByChannelID(event->ChannelID()); - activeMenu = new cRecMenuSeriesTimer(channel, event, recFolder); - DisplayMenu(); - break; } - case rmsSeriesTimerFolder: - //caller: main menu - //Asking for Folder - delete activeMenu; - activeMenu = new cRecMenuAskFolder(event, rmsSeriesTimer); - DisplayMenu(); - break; - case rmsSeriesTimerCreate: { - //caller: cRecMenuSeriesTimer - cTimer *seriesTimer; - if (cRecMenuSeriesTimer *menu = dynamic_cast(activeMenu)) { - seriesTimer = menu->GetTimer(); - } else break; - recManager->CreateSeriesTimer(seriesTimer); - delete activeMenu; - activeMenu = new cRecMenuConfirmSeriesTimer(seriesTimer); - DisplayMenu(); - break; } -/********************************************************************************************** - * SWITCH TIMER - ***********************************************************************************************/ - case rmsSwitchTimer: - delete activeMenu; - activeMenu = new cRecMenuSwitchTimer(); - DisplayMenu(); - break; - case rmsSwitchTimerCreate: { - cSwitchTimer switchTimer; - if (cRecMenuSwitchTimer *menu = dynamic_cast(activeMenu)) { - switchTimer = menu->GetSwitchTimer(); - } else break; - bool success = recManager->CreateSwitchTimer(event, switchTimer); - delete activeMenu; - activeMenu = new cRecMenuSwitchTimerConfirm(success); - DisplayMenu(); - break; } - case rmsSwitchTimerDelete: - recManager->DeleteSwitchTimer(event); - delete activeMenu; - activeMenu = new cRecMenuSwitchTimerDelete(); - DisplayMenu(); - break; -/********************************************************************************************** - * SEARCH TIMER - ***********************************************************************************************/ - case rmsSearchTimer: - //Caller: main menu - //set search String for search timer - delete activeMenu; - activeMenu = new cRecMenuSearchTimer(event); - DisplayMenu(); - break; - case rmsSearchTimerOptions: { - //Caller: cRecMenuSearchTimer, cRecMenuSearchTimerTemplates - //Choose to set options manually or by template - string searchString; - cTVGuideSearchTimer searchTimer; - bool reload = false; - if (cRecMenuSearchTimer *menu = dynamic_cast(activeMenu)) { - searchString = menu->GetSearchString(); - } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - reload = true; - } else break; - delete activeMenu; - if (searchString.size() < 4) { - activeMenu = new cRecMenuSearchTimer(event); - } else { - if (!reload) { - searchTimer.SetSearchString(searchString); - } - vector epgSearchTemplates; - recManager->ReadEPGSearchTemplates(&epgSearchTemplates); - if (epgSearchTemplates.size() > 0) { - activeMenu = new cRecMenuSearchTimerTemplates(searchTimer, epgSearchTemplates); - } else { - activeMenu = new cRecMenuSearchTimerEdit(searchTimer, false); - } - } - DisplayMenu(); - break; } - case rmsSearchTimers: { - //caller: main menu - DisplaySearchTimerList(); - break; } - case rmsSearchTimerEdit: - case rmsSearchTimerEditAdvanced: { - //caller: cRecMenuSearchTimers, cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplates - cTVGuideSearchTimer searchTimer; - bool advancedOptions = false; - if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - } else if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - advancedOptions = (nextState == rmsSearchTimerEditAdvanced)?true:false; - } else if (cRecMenuSearchTimerTemplates *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - } else break; - delete activeMenu; - activeMenu = new cRecMenuSearchTimerEdit(searchTimer, advancedOptions); - DisplayMenu(); - break; } - case rmsSearchTimerTest: { - //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate, cRecMenuSearchTimers, cRecMenuFavorites - //show results of currently choosen search timer - cTVGuideSearchTimer searchTimer; - eRecMenuState recState = rmsDisabled; - if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - recState = rmsSearchTimerRecord; - } else if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - recState = rmsSearchTimerRecord; - } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - TVGuideEPGSearchTemplate tmpl = menu->GetTemplate(); - searchTimer.SetTemplate(tmpl.templValue); - searchTimer.Parse(true); - } else if (cRecMenuFavorites *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetFavorite(); - recState = rmsFavoritesRecord; - } - else break; - int numSearchResults = 0; - string searchString = searchTimer.BuildSearchString(); - const cEvent **searchResult = recManager->PerformSearchTimerSearch(searchString, numSearchResults); - if (numSearchResults) { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchTimerResults(searchTimer.SearchString(), searchResult, numSearchResults, "", recState); - } else { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchTimerNothingFound(searchTimer.SearchString()); - } - DisplayMenu(true); - break; } - case rmsSearchTimerSave: { - //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate - //create new or modify existing search timer - cTVGuideSearchTimer searchTimer; - if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - TVGuideEPGSearchTemplate tmpl = menu->GetTemplate(); - searchTimer.SetTemplate(tmpl.templValue); - searchTimer.Parse(true); - } else break; - bool success = recManager->SaveSearchTimer(&searchTimer); - recManager->UpdateSearchTimers(); - if (searchTimer.GetID() >= 0) { - //Timer modified, show list - DisplaySearchTimerList(); - } else { - //new timer, confirm - delete activeMenu; - activeMenu = new cRecMenuSearchTimerCreateConfirm(success); - DisplayMenu(); - } - break; } - case rmsSearchTimerCreateWithTemplate: { - //caller: cRecMenuSearchTimerTemplates - //create new search timer from template - TVGuideEPGSearchTemplate templ; - cTVGuideSearchTimer searchTimer; - if (cRecMenuSearchTimerTemplates *menu = dynamic_cast(activeMenu)) { - templ = menu->GetTemplate(); - searchTimer = menu->GetSearchTimer(); - } else break; - delete activeMenu; - activeMenu = new cRecMenuSearchTimerTemplatesCreate(templ, searchTimer); - DisplayMenu(); - break; } - case rmsSearchTimerDeleteConfirm: { - //caller: cRecMenuSearchTimers - //Ask for confirmation and if timers created by this search timer should alo be deleted - cTVGuideSearchTimer searchTimer; - if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - } else break; - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchTimerDeleteConfirm(searchTimer); - DisplayMenu(true); - break; } - case rmsSearchTimerDelete: - case rmsSearchTimerDeleteWithTimers: { - //caller: cRecMenuSearchTimerDeleteConfirm - //actually delete searchtimer - cTVGuideSearchTimer searchTimer; - if (cRecMenuSearchTimerDeleteConfirm *menu = dynamic_cast(activeMenu)) { - searchTimer = menu->GetSearchTimer(); - } else break; - bool delTimers = (nextState==rmsSearchTimerDeleteWithTimers)?true:false; - recManager->DeleteSearchTimer(&searchTimer, delTimers); - delete activeMenuBuffer; - activeMenuBuffer = NULL; - DisplaySearchTimerList(); - break; } - case rmsSearchTimerRecord: { - //caller: cRecMenuSearchTimerResults - const cEvent *ev = NULL; - if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { - ev = menu->GetEvent(); - } else break; - if (!ev) - break; - recManager->createTimer(ev, ""); - activeMenuBuffer2 = activeMenu; - activeMenuBuffer2->Hide(); - activeMenu = new cRecMenuSearchConfirmTimer(ev); - DisplayMenu(false, true); - break; } -/********************************************************************************************** -* SEARCH -***********************************************************************************************/ - case rmsSearch: - case rmsSearchWithOptions: { - //caller: main menu, cRecMenuSearch, cRecMenuSearchResults - bool withOptions = false; - string searchString = event->Title(); - if (cRecMenuSearch *menu = dynamic_cast(activeMenu)) { - withOptions = true; - searchString = menu->GetSearchString(); - } else if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { - searchString = menu->GetSearchString(); - } - delete activeMenu; - activeMenu = new cRecMenuSearch(searchString, withOptions); - DisplayMenu(); - break; } - case rmsSearchPerform: { - //caller: cRecMenuSearch - bool useBuffer = false; - Epgsearch_searchresults_v1_0 epgSearchData; - if (cRecMenuSearch *menu = dynamic_cast(activeMenu)) { - epgSearchData = menu->GetEPGSearchStruct(); - } else break; - string searchString = epgSearchData.query; - if (searchString.size() < 3) { - activeMenu->Hide(); - activeMenuBuffer = activeMenu; - useBuffer = true; - activeMenu = new cRecMenuSearchNothingFound(searchString, true); - } else { - int numSearchResults = 0; - const cEvent **searchResult = recManager->PerformSearch(epgSearchData, numSearchResults); - if (searchResult) { - delete activeMenu; - activeMenu = new cRecMenuSearchResults(searchString, searchResult, numSearchResults); - } else { - activeMenu->Hide(); - activeMenuBuffer = activeMenu; - useBuffer = true; - activeMenu = new cRecMenuSearchNothingFound(searchString); - } - } - DisplayMenu(useBuffer); - break; } - case rmsSearchShowInfo: { - //caller: cRecMenuSearchResults, cRecMenuSearchTimerResults, cRecMenuRerunResults - if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { - displayEvent = menu->GetEvent(); - } else if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { - displayEvent = menu->GetEvent(); - } else if (cRecMenuRerunResults *menu = dynamic_cast(activeMenu)) { - displayEvent = menu->GetEvent(); - } else break; - if (displayEvent) { - state = osUser1; - } - break;} - case rmsSearchRecord: { - //caller: cRecMenuSearchResults - const cEvent *ev = NULL; - if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { - ev = menu->GetEvent(); - } else break; - if (!ev) - break; - recManager->createTimer(ev, ""); - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuSearchConfirmTimer(ev); - DisplayMenu(true); - break;} -/********************************************************************************************** - * CHECK FOR TIMER CONFLICTS - ***********************************************************************************************/ - case rmsTimerConflicts: { - //caller: main menu - //Show timer conflict - if (timerConflicts) { - delete timerConflicts; - } - timerConflicts = recManager->CheckTimerConflict(); - delete activeMenu; - int numConflicts = timerConflicts->NumConflicts(); - if (numConflicts > 0) { - activeMenu = new cRecMenuTimerConflicts(timerConflicts); - } else { - activeMenu = new cRecMenuNoTimerConflict(); - } - DisplayMenu(); - break; } - case rmsTimerConflict: { - //caller: cRecMenuTimerConflicts - //Show timer conflict - if (!timerConflicts) - break; - int timerConflict; - if (cRecMenuTimerConflicts *menu = dynamic_cast(activeMenu)) { - timerConflict = menu->GetTimerConflict(); - } else break; - timerConflicts->SetCurrentConflict(timerConflict); - delete activeMenu; - activeMenu = new cRecMenuTimerConflict(timerConflicts->GetCurrentConflict()); - DisplayMenu(); - break; } - case rmsSearchRerunsTimerConflictMenu: { - //caller: cRecMenuTimerConflict - //Show reruns for timer from timer conflict - if (!timerConflicts) - break; - int timerConflict; - if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { - timerConflict = menu->GetTimerConflictIndex(); - } else break; - int timerID = timerConflicts->GetCurrentConflictTimerID(timerConflict); - cTimer *timer = Timers.Get(timerID); - if (timer) { - const cEvent *event = timer->Event(); - if (event) { - int numReruns = 0; - const cEvent **reruns = recManager->LoadReruns(event, numReruns); - if (reruns && (numReruns > 0)) { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuRerunResults(event, reruns, numReruns); - } else { - activeMenuBuffer = activeMenu; - activeMenuBuffer->Hide(); - activeMenu = new cRecMenuNoRerunsFound((event->Title())?event->Title():""); - } - DisplayMenu(true); - } - } - break; } - case rmsTimerConflictRecordRerun: { - //caller: cRecMenuRerunResults - //buffer: cRecMenuTimerConflict - if (!activeMenuBuffer) - break; - if (!timerConflicts) - break; - const cEvent *replace; - int originalConflictIndex; - if (cRecMenuRerunResults *menu = dynamic_cast(activeMenu)) { - replace = menu->GetEvent(); - } else break; - if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenuBuffer)) { - originalConflictIndex = menu->GetTimerConflictIndex(); - } else break; - int originalTimerID = timerConflicts->GetCurrentConflictTimerID(originalConflictIndex); - cTimer *timerOriginal = Timers.Get(originalTimerID); - if (replace && timerOriginal) { - recManager->DeleteTimer(timerOriginal->Event()); - recManager->createTimer(replace); - activeMenuBuffer->Show(); - delete activeMenuBuffer; - activeMenuBuffer = NULL; - delete activeMenu; - activeMenu = new cRecMenuConfirmRerunUsed(timerOriginal->Event(), replace); - DisplayMenu(); - } - break; } - /********************************************************************************************** - * TIMELINE - ***********************************************************************************************/ - case rmsTimeline: { - delete activeMenu; - activeMenu = new cRecMenuTimeline(); - DisplayMenu(); - break; } - case rmsTimelineTimerEdit: { - cTimer *timer; - if (cRecMenuTimeline *menu = dynamic_cast(activeMenu)) { - timer = menu->GetTimer(); - } else break; - if (timer) { - delete activeMenu; - activeMenu = new cRecMenuEditTimer(timer, rmsTimelineTimerSave); - DisplayMenu(); - } - break;} - case rmsTimelineTimerSave: { - cTimer timerModified; - cTimer *originalTimer; - if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { - timerModified = menu->GetTimer(); - originalTimer = menu->GetOriginalTimer(); - } else break; - recManager->SaveTimer(originalTimer, timerModified); - delete activeMenu; - activeMenu = new cRecMenuTimeline(); - DisplayMenu(); - break; } - case rmsTimelineTimerDelete: { - cTimer *timer; - if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { - timer = menu->GetOriginalTimer(); - } else break; - recManager->DeleteTimer(timer); - delete activeMenu; - activeMenu = new cRecMenuTimeline(); - DisplayMenu(); - break; } - default: - break; -/********************************************************************************************** - * RECORDINGS SEARCH - ***********************************************************************************************/ - case rmsRecordingSearch: { - //caller: main menu or rmsRecordingSearchResult - string searchString = event->Title(); - if (cRecMenuRecordingSearchResults *menu = dynamic_cast(activeMenu)) { - searchString = menu->GetSearchString(); - }; - delete activeMenu; - activeMenu = new cRecMenuRecordingSearch(searchString); - DisplayMenu(); - break; } - case rmsRecordingSearchResult: { - //caller: cRecMenuRecordingSearch - string searchString; - if (cRecMenuRecordingSearch *menu = dynamic_cast(activeMenu)) { - searchString = menu->GetSearchString(); - } else break; - delete activeMenu; - if (searchString.size() < 4) { - activeMenu = new cRecMenuRecordingSearch(searchString); - } else { - int numSearchResults = 0; - cRecording **searchResult = recManager->SearchForRecordings(searchString, numSearchResults); - if (numSearchResults == 0) { - activeMenu = new cRecMenuRecordingSearchNotFound(searchString); - } else { - activeMenu = new cRecMenuRecordingSearchResults(searchString, searchResult, numSearchResults); - } - } - DisplayMenu(); - break; } - /********************************************************************************************** - * FAVORITES - *********************************************************************************************/ - case rmsFavoritesRecord: { - //caller: cRecMenuSearchTimerResults - const cEvent *ev = NULL; - if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { - ev = menu->GetEvent(); - } else break; - if (!ev) - break; - recManager->createTimer(ev, ""); - activeMenuBuffer2 = activeMenu; - activeMenuBuffer2->Hide(); - activeMenu = new cRecMenuSearchConfirmTimer(ev); - DisplayMenu(false, true); - break;} - case rmsFavoritesNow: - case rmsFavoritesNext: { - int numResults = 0; - bool nowOrNext; - string header; - if (nextState == rmsFavoritesNow) { - nowOrNext = true; - header = tr("What's on now"); - } else { - nowOrNext = false; - header = tr("What's on next"); - } - const cEvent **result = recManager->WhatsOnNow(nowOrNext, numResults); - DisplayFavoriteResults(header, result, numResults); - break; } - case rmsFavoritesUser1: { - int numResults = 0; - const cEvent **result = recManager->UserDefinedTime(1, numResults); - DisplayFavoriteResults(config.descUser1, result, numResults); - break; } - case rmsFavoritesUser2: { - int numResults = 0; - const cEvent **result = recManager->UserDefinedTime(2, numResults); - DisplayFavoriteResults(config.descUser2, result, numResults); - break; } - case rmsFavoritesUser3: { - int numResults = 0; - const cEvent **result = recManager->UserDefinedTime(3, numResults); - DisplayFavoriteResults(config.descUser3, result, numResults); - break; } - case rmsFavoritesUser4: { - int numResults = 0; - const cEvent **result = recManager->UserDefinedTime(4, numResults); - DisplayFavoriteResults(config.descUser4, result, numResults); - break; } - } - return state; -} +#include "tvguidengosd.h" +#include "recmenuview.h" + +cRecMenuView::cRecMenuView(void) { + active = false; + recMenuView = NULL; + recMenuViewBuffer = NULL; + recMenuViewBuffer2 = NULL; + event = NULL; + displayEvent = NULL; + activeMenu = NULL; + activeMenuBuffer = NULL; + activeMenuBuffer2 = NULL; + recManager = new cRecManager(); + recManager->SetEPGSearchPlugin(); + timerConflicts = NULL; +} + +cRecMenuView::~cRecMenuView() { + if (activeMenu) + delete activeMenu; + if (activeMenuBuffer) + delete activeMenuBuffer; + if (activeMenuBuffer2) + delete activeMenuBuffer2; + if (recMenuView) + delete recMenuView; + if (recMenuViewBuffer) + delete recMenuViewBuffer; + if (recMenuViewBuffer2) + delete recMenuViewBuffer2; +} + +void cRecMenuView::Init(skindesignerapi::cOsdView *recMenuView, skindesignerapi::cOsdView *recMenuViewBuffer, skindesignerapi::cOsdView *recMenuViewBuffer2) { + active = true; + this->recMenuView = recMenuView; + this->recMenuViewBuffer = recMenuViewBuffer; + this->recMenuViewBuffer2 = recMenuViewBuffer2; +} + +void cRecMenuView::DisplayRecMenu(const cEvent *event) { + if (!event) { + return; + } + this->event = event; + activeMenu = new cRecMenuMain(recManager->EpgSearchAvailable(), recManager->CheckEventForTimer(event), SwitchTimers.EventInSwitchList(event)); + DisplayMenu(); +} + +void cRecMenuView::DisplayFavorites(void) { + vector favorites; + recManager->GetFavorites(&favorites); + activeMenu = new cRecMenuFavorites(favorites); + DisplayMenu(); +} + +void cRecMenuView::DisplayRecSearch(const cEvent *e) { + activeMenu = new cRecMenuRecordingSearch(e->Title() ? e->Title() : ""); + DisplayMenu(); +} + +void cRecMenuView::DisplaySearchEPG(const cEvent *e) { + activeMenu = new cRecMenuSearch(e->Title() ? e->Title() : "", false); + DisplayMenu(); +} + +void cRecMenuView::Close(void) { + if (activeMenu) { + delete activeMenu; + activeMenu = NULL; + } + if (activeMenuBuffer) { + delete activeMenuBuffer; + activeMenuBuffer = NULL; + } + if (activeMenuBuffer2) { + delete activeMenuBuffer2; + activeMenuBuffer2 = NULL; + } + delete recMenuView; + recMenuView = NULL; + delete recMenuViewBuffer; + recMenuViewBuffer = NULL; + delete recMenuViewBuffer2; + recMenuViewBuffer2 = NULL; + active = false; +} + +void cRecMenuView::Hide(bool full) { + if (recMenuViewBuffer) { + recMenuViewBuffer->Deactivate(true); + if (full) + recMenuView->Deactivate(true); + } else + recMenuView->Deactivate(true); +} + +void cRecMenuView::Activate(bool full) { + if (recMenuViewBuffer) { + recMenuViewBuffer->Activate(); + if (full) + recMenuView->Activate(); + } else + recMenuView->Activate(); +} + +eOSState cRecMenuView::ProcessKey(eKeys Key) { + eOSState state = osContinue; + eRecMenuState nextState = rmsContinue; + if (!activeMenu) + return state; + nextState = activeMenu->ProcessKey(Key); + if ((nextState == rmsClose) || ((nextState == rmsNotConsumed)&&(Key == kBack))) { + if (activeMenuBuffer2) { + delete activeMenu; + activeMenu = activeMenuBuffer2; + activeMenuBuffer2 = NULL; + activeMenu->Show(); + return osContinue; + } else if (activeMenuBuffer) { + delete activeMenu; + activeMenu = activeMenuBuffer; + activeMenuBuffer = NULL; + activeMenu->Show(); + return osContinue; + } else { + Close(); + return osEnd; + } + } + state = StateMachine(nextState); + if (activeMenu) + activeMenu->Flush(); + return state; +} + +void cRecMenuView::DisplayMenu(bool buffer, bool buffer2) { + if (!activeMenu) + return; + if (buffer) { + activeMenu->Init(recMenuViewBuffer); + } else if (buffer2) { + activeMenu->Init(recMenuViewBuffer2); + } else { + activeMenu->Init(recMenuView); + } + if (cRecMenuTimeline *timeline = dynamic_cast(activeMenu)) { + timeline->SetHeaderTimer(); + } + activeMenu->Draw(); +} + +void cRecMenuView::DisplaySearchTimerList(void) { + delete activeMenu; + vector searchTimers; + recManager->GetSearchTimers(&searchTimers); + activeMenu = new cRecMenuSearchTimers(searchTimers); + DisplayMenu(); +} + +bool cRecMenuView::DisplayTimerConflict(const cTimer *timer) { + int timerID = 0; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + for (const cTimer *t = timers->First(); t; t = timers->Next(t)) { + if (t == timer) + return DisplayTimerConflict(timerID); + timerID++; + } + return false; +} + +bool cRecMenuView::DisplayTimerConflict(int timerID) { + if (timerConflicts) + delete timerConflicts; + timerConflicts = recManager->CheckTimerConflict(); + if (!timerConflicts) + return false; + int showTimerConflict = timerConflicts->GetCorrespondingConflict(timerID); + if (showTimerConflict > -1) { + timerConflicts->SetCurrentConflict(showTimerConflict); + cTVGuideTimerConflict *conflict = timerConflicts->GetCurrentConflict(); + if (!conflict) + return false; + activeMenu = new cRecMenuTimerConflict(conflict); + DisplayMenu(); + return true; + } + return false; +} + +void cRecMenuView::DisplayFavoriteResults(string header, const cEvent **result, int numResults) { + if (numResults) { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchTimerResults(header, result, numResults, "", rmsFavoritesRecord); + } else { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchTimerNothingFound(header); + } + DisplayMenu(true); +} + +eOSState cRecMenuView::StateMachine(eRecMenuState nextState) { + eOSState state = osContinue; + switch (nextState) { +/*************************************************************************************** +* INSTANT RECORDING +****************************************************************************************/ + case rmsInstantRecord: { + //caller: main menu or folder chooser + //Creating timer for active Event, if no conflict, confirm and exit + string recFolder = ""; + if (cRecMenuAskFolder *menu = dynamic_cast(activeMenu)) { + recFolder = menu->GetFolder(); + } + delete activeMenu; + cTimer *timer = recManager->createTimer(event, recFolder); + if (!DisplayTimerConflict(timer)) { + activeMenu = new cRecMenuConfirmTimer(event); + DisplayMenu(); + } + break; } + case rmsInstantRecordFolder: { + //caller: main menu + //Asking for Folder + delete activeMenu; + activeMenu = new cRecMenuAskFolder(event, rmsInstantRecord); + DisplayMenu(); + break; } + case rmsDeleteTimer: { + //caller: main menu + //delete timer for active event + delete activeMenu; + if (recManager->IsRecorded(event)) { + activeMenu = new cRecMenuAskDeleteTimer(event); + } else { + recManager->DeleteTimer(event); + activeMenu = new cRecMenuConfirmDeleteTimer(event); + } + DisplayMenu(); + break; } + case rmsDeleteTimerConfirmation: { + //delete running timer for active event + recManager->DeleteTimer(event); + delete activeMenu; + activeMenu = new cRecMenuConfirmDeleteTimer(event); + DisplayMenu(); + break; } + case rmsEditTimer: { + //edit timer for active event + const cTimer *timer = recManager->GetTimerForEvent(event); + if (timer) { + delete activeMenu; + activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimer); + DisplayMenu(); + } + break; } + case rmsSaveTimer: { + //caller: cRecMenuEditTimer + //save timer for active event + cTimer timerModified; + const cTimer *originalTimer; + if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { + timerModified = menu->GetTimer(); + originalTimer = menu->GetOriginalTimer(); + } else break; + recManager->SaveTimer(originalTimer, timerModified); + Close(); + state = osEnd; + break; } + case rmsIgnoreTimerConflict: + //caller: cRecMenuTimerConflict + //Confirming created Timer + delete activeMenu; + activeMenu = new cRecMenuConfirmTimer(event); + DisplayMenu(); + break; + case rmsTimerConflictShowInfo: { + //caller: cRecMenuTimerConflict + int timerIndex; + if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { + timerIndex = menu->GetTimerConflictIndex(); + } else break; + int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + const cTimer *t = timers->Get(timerID); + if (t) { + displayEvent = t->Event(); + if (displayEvent) { + state = osUser1; + } + } + break; } + case rmsDeleteTimerConflictMenu: { + //caller: cRecMenuTimerConflict + //delete timer out of current timer conflict + int timerIndex; + if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { + timerIndex = menu->GetTimerConflictIndex(); + } else break; + int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); + recManager->DeleteTimer(timerID); + delete activeMenu; + if (!DisplayTimerConflict(timerID)) { + activeMenu = new cRecMenuConfirmTimer(event); + DisplayMenu(); + } + break; } + case rmsEditTimerConflictMenu: { + //caller: cRecMenuTimerConflict + //edit timer out of current timer conflict + int timerIndex; + if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { + timerIndex = menu->GetTimerConflictIndex(); + } else break; + int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + const cTimer *timer = timers->Get(timerID); + if (timer) { + delete activeMenu; + activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimerConflictMenu); + DisplayMenu(); + } + break; } + case rmsSaveTimerConflictMenu: { + //caller: cRecMenuEditTimer + //save timer from current timer conflict + cTimer timerModified; + const cTimer *originalTimer; + if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { + timerModified = menu->GetTimer(); + originalTimer = menu->GetOriginalTimer(); + } else break; + recManager->SaveTimer(originalTimer, timerModified); + delete activeMenu; + if (!DisplayTimerConflict(originalTimer)) { + activeMenu = new cRecMenuConfirmTimer(event); + DisplayMenu(); + } + break; } +/*************************************************************************************** +* SERIES TIMER +****************************************************************************************/ + case rmsSeriesTimer: { + //caller: main menu oder folder chooser + string recFolder = ""; + if (cRecMenuAskFolder *menu = dynamic_cast(activeMenu)) { + recFolder = menu->GetFolder(); + } + delete activeMenu; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + cChannels* channels = &Channels; +#endif + + const cChannel *channel = channels->GetByChannelID(event->ChannelID()); + activeMenu = new cRecMenuSeriesTimer(channel, event, recFolder); + DisplayMenu(); + break; } + case rmsSeriesTimerFolder: + //caller: main menu + //Asking for Folder + delete activeMenu; + activeMenu = new cRecMenuAskFolder(event, rmsSeriesTimer); + DisplayMenu(); + break; + case rmsSeriesTimerCreate: { + //caller: cRecMenuSeriesTimer + cTimer *seriesTimer; + if (cRecMenuSeriesTimer *menu = dynamic_cast(activeMenu)) { + seriesTimer = menu->GetTimer(); + } else break; + recManager->CreateSeriesTimer(seriesTimer); + delete activeMenu; + activeMenu = new cRecMenuConfirmSeriesTimer(seriesTimer); + DisplayMenu(); + break; } +/********************************************************************************************** + * SWITCH TIMER + ***********************************************************************************************/ + case rmsSwitchTimer: + delete activeMenu; + activeMenu = new cRecMenuSwitchTimer(); + DisplayMenu(); + break; + case rmsSwitchTimerCreate: { + cSwitchTimer switchTimer; + if (cRecMenuSwitchTimer *menu = dynamic_cast(activeMenu)) { + switchTimer = menu->GetSwitchTimer(); + } else break; + bool success = recManager->CreateSwitchTimer(event, switchTimer); + delete activeMenu; + activeMenu = new cRecMenuSwitchTimerConfirm(success); + DisplayMenu(); + break; } + case rmsSwitchTimerDelete: + recManager->DeleteSwitchTimer(event); + delete activeMenu; + activeMenu = new cRecMenuSwitchTimerDelete(); + DisplayMenu(); + break; +/********************************************************************************************** + * SEARCH TIMER + ***********************************************************************************************/ + case rmsSearchTimer: + //Caller: main menu + //set search String for search timer + delete activeMenu; + activeMenu = new cRecMenuSearchTimer(event); + DisplayMenu(); + break; + case rmsSearchTimerOptions: { + //Caller: cRecMenuSearchTimer, cRecMenuSearchTimerTemplates + //Choose to set options manually or by template + string searchString; + cTVGuideSearchTimer searchTimer; + bool reload = false; + if (cRecMenuSearchTimer *menu = dynamic_cast(activeMenu)) { + searchString = menu->GetSearchString(); + } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + reload = true; + } else break; + delete activeMenu; + if (searchString.size() < 4) { + activeMenu = new cRecMenuSearchTimer(event); + } else { + if (!reload) { + searchTimer.SetSearchString(searchString); + } + vector epgSearchTemplates; + recManager->ReadEPGSearchTemplates(&epgSearchTemplates); + if (epgSearchTemplates.size() > 0) { + activeMenu = new cRecMenuSearchTimerTemplates(searchTimer, epgSearchTemplates); + } else { + activeMenu = new cRecMenuSearchTimerEdit(searchTimer, false); + } + } + DisplayMenu(); + break; } + case rmsSearchTimers: { + //caller: main menu + DisplaySearchTimerList(); + break; } + case rmsSearchTimerEdit: + case rmsSearchTimerEditAdvanced: { + //caller: cRecMenuSearchTimers, cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplates + cTVGuideSearchTimer searchTimer; + bool advancedOptions = false; + if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + } else if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + advancedOptions = (nextState == rmsSearchTimerEditAdvanced)?true:false; + } else if (cRecMenuSearchTimerTemplates *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + } else break; + delete activeMenu; + activeMenu = new cRecMenuSearchTimerEdit(searchTimer, advancedOptions); + DisplayMenu(); + break; } + case rmsSearchTimerTest: { + //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate, cRecMenuSearchTimers, cRecMenuFavorites + //show results of currently choosen search timer + cTVGuideSearchTimer searchTimer; + eRecMenuState recState = rmsDisabled; + if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + recState = rmsSearchTimerRecord; + } else if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + recState = rmsSearchTimerRecord; + } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + TVGuideEPGSearchTemplate tmpl = menu->GetTemplate(); + searchTimer.SetTemplate(tmpl.templValue); + searchTimer.Parse(true); + } else if (cRecMenuFavorites *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetFavorite(); + recState = rmsFavoritesRecord; + } + else break; + int numSearchResults = 0; + string searchString = searchTimer.BuildSearchString(); + const cEvent **searchResult = recManager->PerformSearchTimerSearch(searchString, numSearchResults); + if (numSearchResults) { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchTimerResults(searchTimer.SearchString(), searchResult, numSearchResults, "", recState); + } else { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchTimerNothingFound(searchTimer.SearchString()); + } + DisplayMenu(true); + break; } + case rmsSearchTimerSave: { + //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate + //create new or modify existing search timer + cTVGuideSearchTimer searchTimer; + if (cRecMenuSearchTimerEdit *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + TVGuideEPGSearchTemplate tmpl = menu->GetTemplate(); + searchTimer.SetTemplate(tmpl.templValue); + searchTimer.Parse(true); + } else break; + bool success = recManager->SaveSearchTimer(&searchTimer); + recManager->UpdateSearchTimers(); + if (searchTimer.GetID() >= 0) { + //Timer modified, show list + DisplaySearchTimerList(); + } else { + //new timer, confirm + delete activeMenu; + activeMenu = new cRecMenuSearchTimerCreateConfirm(success); + DisplayMenu(); + } + break; } + case rmsSearchTimerCreateWithTemplate: { + //caller: cRecMenuSearchTimerTemplates + //create new search timer from template + TVGuideEPGSearchTemplate templ; + cTVGuideSearchTimer searchTimer; + if (cRecMenuSearchTimerTemplates *menu = dynamic_cast(activeMenu)) { + templ = menu->GetTemplate(); + searchTimer = menu->GetSearchTimer(); + } else break; + delete activeMenu; + activeMenu = new cRecMenuSearchTimerTemplatesCreate(templ, searchTimer); + DisplayMenu(); + break; } + case rmsSearchTimerDeleteConfirm: { + //caller: cRecMenuSearchTimers + //Ask for confirmation and if timers created by this search timer should alo be deleted + cTVGuideSearchTimer searchTimer; + if (cRecMenuSearchTimers *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + } else break; + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchTimerDeleteConfirm(searchTimer); + DisplayMenu(true); + break; } + case rmsSearchTimerDelete: + case rmsSearchTimerDeleteWithTimers: { + //caller: cRecMenuSearchTimerDeleteConfirm + //actually delete searchtimer + cTVGuideSearchTimer searchTimer; + if (cRecMenuSearchTimerDeleteConfirm *menu = dynamic_cast(activeMenu)) { + searchTimer = menu->GetSearchTimer(); + } else break; + bool delTimers = (nextState==rmsSearchTimerDeleteWithTimers)?true:false; + recManager->DeleteSearchTimer(&searchTimer, delTimers); + delete activeMenuBuffer; + activeMenuBuffer = NULL; + DisplaySearchTimerList(); + break; } + case rmsSearchTimerRecord: { + //caller: cRecMenuSearchTimerResults + const cEvent *ev = NULL; + if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { + ev = menu->GetEvent(); + } else break; + if (!ev) + break; + recManager->createTimer(ev, ""); + activeMenuBuffer2 = activeMenu; + activeMenuBuffer2->Hide(); + activeMenu = new cRecMenuSearchConfirmTimer(ev); + DisplayMenu(false, true); + break; } +/********************************************************************************************** +* SEARCH +***********************************************************************************************/ + case rmsSearch: + case rmsSearchWithOptions: { + //caller: main menu, cRecMenuSearch, cRecMenuSearchResults + bool withOptions = false; + string searchString = event->Title(); + if (cRecMenuSearch *menu = dynamic_cast(activeMenu)) { + withOptions = true; + searchString = menu->GetSearchString(); + } else if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { + searchString = menu->GetSearchString(); + } + delete activeMenu; + activeMenu = new cRecMenuSearch(searchString, withOptions); + DisplayMenu(); + break; } + case rmsSearchPerform: { + //caller: cRecMenuSearch + bool useBuffer = false; + Epgsearch_searchresults_v1_0 epgSearchData; + if (cRecMenuSearch *menu = dynamic_cast(activeMenu)) { + epgSearchData = menu->GetEPGSearchStruct(); + } else break; + string searchString = epgSearchData.query; + if (searchString.size() < 3) { + activeMenu->Hide(); + activeMenuBuffer = activeMenu; + useBuffer = true; + activeMenu = new cRecMenuSearchNothingFound(searchString, true); + } else { + int numSearchResults = 0; + const cEvent **searchResult = recManager->PerformSearch(epgSearchData, numSearchResults); + if (searchResult) { + delete activeMenu; + activeMenu = new cRecMenuSearchResults(searchString, searchResult, numSearchResults); + } else { + activeMenu->Hide(); + activeMenuBuffer = activeMenu; + useBuffer = true; + activeMenu = new cRecMenuSearchNothingFound(searchString); + } + } + DisplayMenu(useBuffer); + break; } + case rmsSearchShowInfo: { + //caller: cRecMenuSearchResults, cRecMenuSearchTimerResults, cRecMenuRerunResults + if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { + displayEvent = menu->GetEvent(); + } else if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { + displayEvent = menu->GetEvent(); + } else if (cRecMenuRerunResults *menu = dynamic_cast(activeMenu)) { + displayEvent = menu->GetEvent(); + } else break; + if (displayEvent) { + state = osUser1; + } + break;} + case rmsSearchRecord: { + //caller: cRecMenuSearchResults + const cEvent *ev = NULL; + if (cRecMenuSearchResults *menu = dynamic_cast(activeMenu)) { + ev = menu->GetEvent(); + } else break; + if (!ev) + break; + recManager->createTimer(ev, ""); + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuSearchConfirmTimer(ev); + DisplayMenu(true); + break;} +/********************************************************************************************** + * CHECK FOR TIMER CONFLICTS + ***********************************************************************************************/ + case rmsTimerConflicts: { + //caller: main menu + //Show timer conflict + if (timerConflicts) { + delete timerConflicts; + } + timerConflicts = recManager->CheckTimerConflict(); + delete activeMenu; + int numConflicts = timerConflicts->NumConflicts(); + if (numConflicts > 0) { + activeMenu = new cRecMenuTimerConflicts(timerConflicts); + } else { + activeMenu = new cRecMenuNoTimerConflict(); + } + DisplayMenu(); + break; } + case rmsTimerConflict: { + //caller: cRecMenuTimerConflicts + //Show timer conflict + if (!timerConflicts) + break; + int timerConflict; + if (cRecMenuTimerConflicts *menu = dynamic_cast(activeMenu)) { + timerConflict = menu->GetTimerConflict(); + } else break; + timerConflicts->SetCurrentConflict(timerConflict); + delete activeMenu; + activeMenu = new cRecMenuTimerConflict(timerConflicts->GetCurrentConflict()); + DisplayMenu(); + break; } + case rmsSearchRerunsTimerConflictMenu: { + //caller: cRecMenuTimerConflict + //Show reruns for timer from timer conflict + if (!timerConflicts) + break; + int timerConflict; + if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenu)) { + timerConflict = menu->GetTimerConflictIndex(); + } else break; + int timerID = timerConflicts->GetCurrentConflictTimerID(timerConflict); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + const cTimer *timer = timers->Get(timerID); + if (timer) { + const cEvent *event = timer->Event(); + if (event) { + int numReruns = 0; + const cEvent **reruns = recManager->LoadReruns(event, numReruns); + if (reruns && (numReruns > 0)) { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuRerunResults(event, reruns, numReruns); + } else { + activeMenuBuffer = activeMenu; + activeMenuBuffer->Hide(); + activeMenu = new cRecMenuNoRerunsFound((event->Title())?event->Title():""); + } + DisplayMenu(true); + } + } + break; } + case rmsTimerConflictRecordRerun: { + //caller: cRecMenuRerunResults + //buffer: cRecMenuTimerConflict + if (!activeMenuBuffer) + break; + if (!timerConflicts) + break; + const cEvent *replace; + int originalConflictIndex; + if (cRecMenuRerunResults *menu = dynamic_cast(activeMenu)) { + replace = menu->GetEvent(); + } else break; + if (cRecMenuTimerConflict *menu = dynamic_cast(activeMenuBuffer)) { + originalConflictIndex = menu->GetTimerConflictIndex(); + } else break; + int originalTimerID = timerConflicts->GetCurrentConflictTimerID(originalConflictIndex); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + const cTimer *timerOriginal = timers->Get(originalTimerID); + if (replace && timerOriginal) { + recManager->DeleteTimer(timerOriginal->Event()); + recManager->createTimer(replace); + activeMenuBuffer->Show(); + delete activeMenuBuffer; + activeMenuBuffer = NULL; + delete activeMenu; + activeMenu = new cRecMenuConfirmRerunUsed(timerOriginal->Event(), replace); + DisplayMenu(); + } + break; } + /********************************************************************************************** + * TIMELINE + ***********************************************************************************************/ + case rmsTimeline: { + delete activeMenu; + activeMenu = new cRecMenuTimeline(); + DisplayMenu(); + break; } + case rmsTimelineTimerEdit: { + const cTimer *timer; + if (cRecMenuTimeline *menu = dynamic_cast(activeMenu)) { + timer = menu->GetTimer(); + } else break; + if (timer) { + delete activeMenu; + activeMenu = new cRecMenuEditTimer(timer, rmsTimelineTimerSave); + DisplayMenu(); + } + break;} + case rmsTimelineTimerSave: { + cTimer timerModified; + const cTimer *originalTimer; + if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { + timerModified = menu->GetTimer(); + originalTimer = menu->GetOriginalTimer(); + } else break; + recManager->SaveTimer(originalTimer, timerModified); + delete activeMenu; + activeMenu = new cRecMenuTimeline(); + DisplayMenu(); + break; } + case rmsTimelineTimerDelete: { + const cTimer *timer; + if (cRecMenuEditTimer *menu = dynamic_cast(activeMenu)) { + timer = menu->GetOriginalTimer(); + } else break; + recManager->DeleteTimer(timer); + delete activeMenu; + activeMenu = new cRecMenuTimeline(); + DisplayMenu(); + break; } + default: + break; +/********************************************************************************************** + * RECORDINGS SEARCH + ***********************************************************************************************/ + case rmsRecordingSearch: { + //caller: main menu or rmsRecordingSearchResult + string searchString = event->Title(); + if (cRecMenuRecordingSearchResults *menu = dynamic_cast(activeMenu)) { + searchString = menu->GetSearchString(); + }; + delete activeMenu; + activeMenu = new cRecMenuRecordingSearch(searchString); + DisplayMenu(); + break; } + case rmsRecordingSearchResult: { + //caller: cRecMenuRecordingSearch + string searchString; + if (cRecMenuRecordingSearch *menu = dynamic_cast(activeMenu)) { + searchString = menu->GetSearchString(); + } else break; + delete activeMenu; + if (searchString.size() < 4) { + activeMenu = new cRecMenuRecordingSearch(searchString); + } else { + int numSearchResults = 0; + const cRecording **searchResult = recManager->SearchForRecordings(searchString, numSearchResults); + if (numSearchResults == 0) { + activeMenu = new cRecMenuRecordingSearchNotFound(searchString); + } else { + activeMenu = new cRecMenuRecordingSearchResults(searchString, searchResult, numSearchResults); + } + } + DisplayMenu(); + break; } + /********************************************************************************************** + * FAVORITES + *********************************************************************************************/ + case rmsFavoritesRecord: { + //caller: cRecMenuSearchTimerResults + const cEvent *ev = NULL; + if (cRecMenuSearchTimerResults *menu = dynamic_cast(activeMenu)) { + ev = menu->GetEvent(); + } else break; + if (!ev) + break; + recManager->createTimer(ev, ""); + activeMenuBuffer2 = activeMenu; + activeMenuBuffer2->Hide(); + activeMenu = new cRecMenuSearchConfirmTimer(ev); + DisplayMenu(false, true); + break;} + case rmsFavoritesNow: + case rmsFavoritesNext: { + int numResults = 0; + bool nowOrNext; + string header; + if (nextState == rmsFavoritesNow) { + nowOrNext = true; + header = tr("What's on now"); + } else { + nowOrNext = false; + header = tr("What's on next"); + } + const cEvent **result = recManager->WhatsOnNow(nowOrNext, numResults); + DisplayFavoriteResults(header, result, numResults); + break; } + case rmsFavoritesUser1: { + int numResults = 0; + const cEvent **result = recManager->UserDefinedTime(1, numResults); + DisplayFavoriteResults(config.descUser1, result, numResults); + break; } + case rmsFavoritesUser2: { + int numResults = 0; + const cEvent **result = recManager->UserDefinedTime(2, numResults); + DisplayFavoriteResults(config.descUser2, result, numResults); + break; } + case rmsFavoritesUser3: { + int numResults = 0; + const cEvent **result = recManager->UserDefinedTime(3, numResults); + DisplayFavoriteResults(config.descUser3, result, numResults); + break; } + case rmsFavoritesUser4: { + int numResults = 0; + const cEvent **result = recManager->UserDefinedTime(4, numResults); + DisplayFavoriteResults(config.descUser4, result, numResults); + break; } + } + return state; +} diff --git a/recmenuview.h b/recmenuview.h index 6f1d03a..718379e 100644 --- a/recmenuview.h +++ b/recmenuview.h @@ -1,46 +1,46 @@ -#ifndef __TVGUIDE_RECMENUVIEW_H -#define __TVGUIDE_RECMENUVIEW_H - -#include "config.h" -#include -#include "recmanager.h" -#include "recmenus.h" - -class cRecMenuView { -private: - bool active; - skindesignerapi::cOsdView *recMenuView; - skindesignerapi::cOsdView *recMenuViewBuffer; - skindesignerapi::cOsdView *recMenuViewBuffer2; - const cEvent *event; - const cEvent *displayEvent; - cRecManager *recManager; - cRecMenu *activeMenu; - cRecMenu *activeMenuBuffer; - cRecMenu *activeMenuBuffer2; - cTVGuideTimerConflicts *timerConflicts; - void DrawBackground(int menuWidth, int menuHeight, bool scrolling); - void DisplayMenu(bool buffer = false, bool buffer2 = false); - void DisplaySearchTimerList(void); - bool DisplayTimerConflict(cTimer *timer); - bool DisplayTimerConflict(int timerID); - void DisplayFavoriteResults(string header, const cEvent **result, int numResults); - eOSState StateMachine(eRecMenuState nextState); -public: - cRecMenuView(void); - virtual ~cRecMenuView(void); - void Init(skindesignerapi::cOsdView *recMenuView, skindesignerapi::cOsdView *recMenuViewBuffer, skindesignerapi::cOsdView *recMenuViewBuffer2); - void DisplayRecMenu(const cEvent *event); - void DisplayFavorites(void); - void DisplayRecSearch(const cEvent *e); - void DisplaySearchEPG(const cEvent *e); - void Close(void); - void Hide(bool full = false); - void Activate(bool full = false); - eOSState ProcessKey(eKeys Key); - void Flush(void) { activeMenu->Flush(); }; - const cEvent *GetEvent(void) { return displayEvent; }; - bool Active(void) { return active; }; -}; - -#endif //__TVGUIDE_RECMENUVIEW_H +#ifndef __TVGUIDE_RECMENUVIEW_H +#define __TVGUIDE_RECMENUVIEW_H + +#include "config.h" +#include +#include "recmanager.h" +#include "recmenus.h" + +class cRecMenuView { +private: + bool active; + skindesignerapi::cOsdView *recMenuView; + skindesignerapi::cOsdView *recMenuViewBuffer; + skindesignerapi::cOsdView *recMenuViewBuffer2; + const cEvent *event; + const cEvent *displayEvent; + cRecManager *recManager; + cRecMenu *activeMenu; + cRecMenu *activeMenuBuffer; + cRecMenu *activeMenuBuffer2; + cTVGuideTimerConflicts *timerConflicts; + void DrawBackground(int menuWidth, int menuHeight, bool scrolling); + void DisplayMenu(bool buffer = false, bool buffer2 = false); + void DisplaySearchTimerList(void); + bool DisplayTimerConflict(const cTimer *timer); + bool DisplayTimerConflict(int timerID); + void DisplayFavoriteResults(string header, const cEvent **result, int numResults); + eOSState StateMachine(eRecMenuState nextState); +public: + cRecMenuView(void); + virtual ~cRecMenuView(void); + void Init(skindesignerapi::cOsdView *recMenuView, skindesignerapi::cOsdView *recMenuViewBuffer, skindesignerapi::cOsdView *recMenuViewBuffer2); + void DisplayRecMenu(const cEvent *event); + void DisplayFavorites(void); + void DisplayRecSearch(const cEvent *e); + void DisplaySearchEPG(const cEvent *e); + void Close(void); + void Hide(bool full = false); + void Activate(bool full = false); + eOSState ProcessKey(eKeys Key); + void Flush(void) { activeMenu->Flush(); }; + const cEvent *GetEvent(void) { return displayEvent; }; + bool Active(void) { return active; }; +}; + +#endif //__TVGUIDE_RECMENUVIEW_H diff --git a/searchtimer.c b/searchtimer.c index fe78f6c..22d1313 100644 --- a/searchtimer.c +++ b/searchtimer.c @@ -1,570 +1,611 @@ -#include -#include -#include -#include -#include -#include -#include "helpers.h" -#include "searchtimer.h" - -// -- cTVGuideSearchTimer ----------------------------------------------------------------- -cTVGuideSearchTimer::cTVGuideSearchTimer(void) { - strTimer = ""; - ID = -1; - searchString = ""; - useTime = false; - startTime = 0000; - stopTime = 2359; - useChannel = false; - channelMin = Channels.GetByNumber(cDevice::CurrentChannel()); - channelMax = Channels.GetByNumber(cDevice::CurrentChannel()); - channelGroup = ""; - useCase = false; - mode = 0; - useTitle = true; - useSubtitle = true; - useDescription = true; - useDuration = false; - minDuration = 0; - maxDuration = 2359; - useAsSearchTimer = true; - useDayOfWeek = false; - dayOfWeek = 0; - directory = ""; - useEpisode = 0; - priority = 99; - lifetime = 99; - marginStart = 5; - marginStop = 5; - useVPS = false; - action = 0; - useExtEPGInfo = 0; - extEPGInfoValues = ""; - avoidRepeats = 1; - allowedRepeats = 1; - compareTitle = 1; - compareSubtitle = 2; - compareSummary = 1; - catvaluesAvoidRepeat = 0; - repeatsWithinDays = 0; - delAfterDays = 0; - recordingsKeep = 0; - switchMinsBefore = 0; - pauseOnNrRecordings = 0; - blacklistMode = 0; - blacklists = ""; - fuzzyTolerance = 0; - useInFavorites = 0; - menuTemplate = 0; - delMode = 0; - delAfterCountRecs = 0; - delAfterDaysOfFirstRec = 0; - useAsSearchTimerFrom = 0; - useAsSearchTimerTil = 0; - ignoreMissingEPGCats = 0; - unmuteSoundOnSwitch = 0; - compareSummaryMatchInPercent = 0; - contentsFilter = ""; - compareDate = 0; -} - -cTVGuideSearchTimer::~cTVGuideSearchTimer(void) { -} - -bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const { - std::string searchStringOther = other.SearchString(); - searchStringOther = StrToLowerCase(searchStringOther); - std::string thisSearchString = StrToLowerCase(searchString); - int comp = thisSearchString.compare(searchStringOther); - if (comp < 0) - return true; - return false; -} - - -void cTVGuideSearchTimer::SetTemplate(std::string tmpl) { - std::stringstream searchTimerString; - searchTimerString << "0:"; - searchTimerString << tmpl; - strTimer = searchTimerString.str(); -} - -int cTVGuideSearchTimer::DayOfWeek(void) { - int vdrDayOfWeek = 0; - if (dayOfWeek >= 0) { - vdrDayOfWeek = pow(2, (dayOfWeek+6)%7); - } else if (dayOfWeek < 0) { - int absDayOfWeek = abs(dayOfWeek); - for (int i=0; i < 7; i++) { - if (absDayOfWeek & (1 << i)) { - vdrDayOfWeek += pow(2, (i+6)%7); - } - } - } - return vdrDayOfWeek; -} - -void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) { - int epgSearchDayOfWeek = 0; - for (int i=0; i < 7; i++) { - if (VDRDayOfWeek & (1 << i)) { - epgSearchDayOfWeek += pow(2, (i+1)%7); - } - } - this->dayOfWeek = epgSearchDayOfWeek * (-1); -} - -/* - 0 - unique search timer id - 1 - the search term - 2 - use time? 0/1 - 3 - start time in HHMM - 4 - stop time in HHMM - 5 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only - 6 - if 'use channel' = 1 then channel id[|channel id] in VDR format, - one entry or min/max entry separated with |, if 'use channel' = 2 - then the channel group name - 7 - match case? 0/1 - 8 - search mode: - 0 - the whole term must appear as substring - 1 - all single terms (delimiters are blank,',', ';', '|' or '~') - must exist as substrings. - 2 - at least one term (delimiters are blank, ',', ';', '|' or '~') - must exist as substring. - 3 - matches exactly - 4 - regular expression - 9 - use title? 0/1 - 10 - use subtitle? 0/1 - 11 - use description? 0/1 - 12 - use duration? 0/1 - 13 - min duration in hhmm - 14 - max duration in hhmm - 15 - use as search timer? 0/1 - 16 - use day of week? 0/1 - 17 - day of week (0 = Sunday, 1 = Monday...; - -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue) - 18 - use series recording? 0/1 - 19 - directory for recording - 20 - priority of recording - 21 - lifetime of recording - 22 - time margin for start in minutes - 23 - time margin for stop in minutes - 24 - use VPS? 0/1 - 25 - action: - 0 = create a timer - 1 = announce only via OSD (no timer) - 2 = switch only (no timer) - 3 = announce via OSD and switch (no timer) - 4 = announce via mail - 26 - use extended EPG info? 0/1 - 27 - extended EPG info values. This entry has the following format - (delimiter is '|' for each category, '#' separates id and value): - 1 - the id of the extended EPG info category as specified in - epgsearchcats.conf - 2 - the value of the extended EPG info category - (a ':' will be translated to "!^colon^!", e.g. in "16:9") - 28 - avoid repeats? 0/1 - 29 - allowed repeats - 30 - compare title when testing for a repeat? 0/1 - 31 - compare subtitle when testing for a repeat? 0/1/2 - 0 - no - 1 - yes - 2 - yes, if present - 32 - compare description when testing for a repeat? 0/1 - 33 - compare extended EPG info when testing for a repeat? - This entry is a bit field of the category IDs. - 34 - accepts repeats only within x days - 35 - delete a recording automatically after x days - 36 - but keep this number of recordings anyway - 37 - minutes before switch (if action = 2) - 38 - pause if x recordings already exist - 39 - blacklist usage mode (0 none, 1 selection, 2 all) - 40 - selected blacklist IDs separated with '|' - 41 - fuzzy tolerance value for fuzzy searching - 42 - use this search in favorites menu (0 no, 1 yes) - 43 - id of a menu search template - 44 - auto deletion mode (0 don't delete search timer, 1 delete after given - count of recordings, 2 delete after given days after first recording) - 45 - count of recordings after which to delete the search timer - 46 - count of days after the first recording after which to delete the search - timer - 47 - first day where the search timer is active (see parameter 16) - 48 - last day where the search timer is active (see parameter 16) - 49 - ignore missing EPG categories? 0/1 - 50 - unmute sound if off when used as switch timer - 51 - percentage of match when comparing the summary of two events (with 'avoid repeats') - 52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars - 53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month) -*/ -bool cTVGuideSearchTimer::Parse(bool readTemplate) { - splitstring s(strTimer.c_str()); - std::vector values = s.split(':', 1); - int numValues = values.size(); - if (numValues < 12) - return false; - for (int value = 0; value < numValues; value++) { - switch (value) { - case 0: - if (!readTemplate) - ID = atoi(values[value].c_str()); - break; - case 1: - if (!readTemplate) { - std::string searchStringMasked = values[value]; - std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':'); - searchString = searchStringMasked; - } - break; - case 2: - useTime = atoi(values[value].c_str()); - break; - case 3: - if (useTime) { - startTime = atoi(values[value].c_str()); - } - break; - case 4: - if (useTime) { - stopTime = atoi(values[value].c_str()); - } - break; - case 5: - useChannel = atoi(values[value].c_str()); - break; - case 6: - if (useChannel == 0) { - channelMin = NULL; - channelMax = NULL; - } else if (useChannel == 1) { - char *channelMinbuffer = NULL; - char *channelMaxbuffer = NULL; - int channels = sscanf(values[value].c_str(), "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); - channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); - if (!channelMin) { - channelMin = channelMax = NULL; - useChannel = 0; - } - if (channels == 1) - channelMax = channelMin; - else { - channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); - if (!channelMax) { - channelMin = channelMax = NULL; - useChannel = 0; - } - } - free(channelMinbuffer); - free(channelMaxbuffer); - } else if (useChannel == 2) { - channelGroup = values[value]; - } - break; - case 7: - useCase = atoi(values[value].c_str()); - break; - case 8: - mode = atoi(values[value].c_str()); - break; - case 9: - useTitle = atoi(values[value].c_str()); - break; - case 10: - useSubtitle = atoi(values[value].c_str()); - break; - case 11: - useDescription = atoi(values[value].c_str()); - break; - case 12: - useDuration = atoi(values[value].c_str()); - break; - case 13: - minDuration = atoi(values[value].c_str()); - break; - case 14: - maxDuration = atoi(values[value].c_str()); - break; - case 15: - useAsSearchTimer = atoi(values[value].c_str()); - break; - case 16: - useDayOfWeek = atoi(values[value].c_str()); - break; - case 17: - dayOfWeek = atoi(values[value].c_str()); - break; - case 18: - useEpisode = atoi(values[value].c_str()); - break; - case 19: - directory = values[value]; - break; - case 20: - priority = atoi(values[value].c_str()); - break; - case 21: - lifetime = atoi(values[value].c_str()); - break; - case 22: - marginStart = atoi(values[value].c_str()); - break; - case 23: - marginStop = atoi(values[value].c_str()); - break; - case 24: - useVPS = atoi(values[value].c_str()); - break; - case 25: - action = atoi(values[value].c_str()); - break; - case 26: - useExtEPGInfo = atoi(values[value].c_str()); - break; - case 27: - extEPGInfoValues = values[value]; - break; - case 28: - avoidRepeats = atoi(values[value].c_str()); - break; - case 29: - allowedRepeats = atoi(values[value].c_str()); - break; - case 30: - compareTitle = atoi(values[value].c_str()); - break; - case 31: - compareSubtitle = atoi(values[value].c_str()); - break; - case 32: - compareSummary = atoi(values[value].c_str()); - break; - case 33: - catvaluesAvoidRepeat = atol(values[value].c_str()); - break; - case 34: - repeatsWithinDays = atoi(values[value].c_str()); - break; - case 35: - delAfterDays = atoi(values[value].c_str()); - break; - case 36: - recordingsKeep = atoi(values[value].c_str()); - break; - case 37: - switchMinsBefore = atoi(values[value].c_str()); - break; - case 38: - pauseOnNrRecordings = atoi(values[value].c_str()); - break; - case 39: - blacklistMode = atoi(values[value].c_str()); - break; - case 40: - blacklists = values[value]; - break; - case 41: - fuzzyTolerance = atoi(values[value].c_str()); - break; - case 42: - useInFavorites = atoi(values[value].c_str()); - break; - case 43: - menuTemplate = atoi(values[value].c_str()); - break; - case 44: - delMode = atoi(values[value].c_str()); - break; - case 45: - delAfterCountRecs = atoi(values[value].c_str()); - break; - case 46: - delAfterDaysOfFirstRec = atoi(values[value].c_str()); - break; - case 47: - useAsSearchTimerFrom = atol(values[value].c_str()); - break; - case 48: - useAsSearchTimerTil = atol(values[value].c_str()); - break; - case 49: - ignoreMissingEPGCats = atoi(values[value].c_str()); - break; - case 50: - unmuteSoundOnSwitch = atoi(values[value].c_str()); - break; - case 51: - compareSummaryMatchInPercent = atoi(values[value].c_str()); - break; - case 52: - contentsFilter = values[value]; - break; - case 53: - compareDate = atoi(values[value].c_str()); - break; - default: - break; - } - } - return true; -} - -std::string cTVGuideSearchTimer::BuildSearchString(void) { - std::stringstream search; - // 0 - 2 - if (ID > -1) - search << ID << ":"; - else - search << ":"; - std::string searchStringMasked = searchString; - std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|'); - search << searchStringMasked << ":"; - search << useTime << ":"; - - // 3 - 6 - if (useTime) { - search << *cString::sprintf("%04d", startTime) << ":"; - search << *cString::sprintf("%04d", stopTime) << ":"; - } else { - search << "::"; - } - - search << useChannel << ":"; - if (useChannel == 1) { - if (channelMin && channelMax) { - if (channelMin->Number() < channelMax->Number()) - search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":"; - else - search << std::string(channelMin->GetChannelID().ToString()) << ":"; - } else { - search << "0:"; - } - } else if (useChannel == 2) { - search << channelGroup << ":"; - } else { - search << "0:"; - } - // 7 - 14 - search << useCase << ":"; - search << mode << ":"; - search << useTitle << ":"; - search << useSubtitle << ":"; - search << useDescription << ":"; - search << useDuration << ":"; - if (useDuration) { - search << *cString::sprintf("%04d", minDuration) << ":"; - search << *cString::sprintf("%04d", maxDuration) << ":"; - } else { - search << "::"; - } - //15 - 53 - search << useAsSearchTimer << ":"; - search << useDayOfWeek << ":"; - search << dayOfWeek << ":"; - search << useEpisode << ":"; - search << directory << ":"; - search << priority << ":"; - search << lifetime << ":"; - search << marginStart << ":"; - search << marginStop << ":"; - search << useVPS << ":"; - search << action << ":"; - search << useExtEPGInfo << ":"; - search << extEPGInfoValues << ":"; - search << avoidRepeats << ":"; - search << allowedRepeats << ":"; - search << compareTitle << ":"; - search << compareSubtitle << ":"; - search << compareSummary << ":"; - search << catvaluesAvoidRepeat << ":"; - search << repeatsWithinDays << ":"; - search << delAfterDays << ":"; - search << recordingsKeep << ":"; - search << switchMinsBefore << ":"; - search << pauseOnNrRecordings << ":"; - search << blacklistMode << ":"; - search << blacklists << ":"; - search << fuzzyTolerance << ":"; - search << useInFavorites << ":"; - search << menuTemplate << ":"; - search << delMode << ":"; - search << delAfterCountRecs << ":"; - search << delAfterDaysOfFirstRec << ":"; - search << useAsSearchTimerFrom << ":"; - search << useAsSearchTimerTil << ":"; - search << ignoreMissingEPGCats << ":"; - search << unmuteSoundOnSwitch << ":"; - search << compareSummaryMatchInPercent << ":"; - search << contentsFilter << ":"; - search << compareDate; - - strTimer = search.str(); - return strTimer; -} - -bool cTVGuideSearchTimer::Active(void) { - if (useAsSearchTimer) - return true; - return false; -} - - -int cTVGuideSearchTimer::GetNumTimers(void) { - int numTimers = 0; - if (ID < 0) - return numTimers; - for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { - char* searchID = GetAuxValue(timer, "s-id"); - if (!searchID) continue; - if (ID == atoi(searchID)) - numTimers++; - free(searchID); - } - return numTimers; -} - -int cTVGuideSearchTimer::GetNumRecordings(void) { - int numRecordings = 0; - if (ID < 0) - return numRecordings; - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { - if (recording->IsEdited()) - continue; - if (!recording->Info()) - continue; - char* searchID = GetAuxValue(recording, "s-id"); - if (!searchID) continue; - if (ID == atoi(searchID)) - numRecordings++; - free(searchID); - } - return numRecordings; -} - -void cTVGuideSearchTimer::GetSearchModes(std::vector *searchModes) { - searchModes->push_back(tr("whole term must appear")); - searchModes->push_back(tr("all terms must exist")); - searchModes->push_back(tr("one term must exist")); - searchModes->push_back(tr("exact match")); - searchModes->push_back(tr("regular expression")); -} - - -void cTVGuideSearchTimer::Dump(void) { - esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str()); - esyslog("tvguide searchtimer: ID: %d", ID); - esyslog("tvguide searchtimer: searchString: %s", searchString.c_str()); - esyslog("tvguide searchtimer: useTime: %d", useTime); - esyslog("tvguide searchtimer: startTime: %d", startTime); - esyslog("tvguide searchtimer: stopTime: %d", stopTime); - esyslog("tvguide searchtimer: useChannel: %d", useChannel); - if (channelMin) - esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name()); - if (channelMax) - esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name()); - esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str()); - esyslog("tvguide searchtimer: useCase: %d", useCase); - esyslog("tvguide searchtimer: mode: %d", mode); - esyslog("tvguide searchtimer: useTitle: %d", useTitle); - esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle); - esyslog("tvguide searchtimer: useDescription: %d", useDescription); -} - +#include +#include +#include +#include +#include +#include +#include "helpers.h" +#include "searchtimer.h" + +// -- cTVGuideSearchTimer ----------------------------------------------------------------- +cTVGuideSearchTimer::cTVGuideSearchTimer(void) { + strTimer = ""; + ID = -1; + searchString = ""; + useTime = false; + startTime = 0000; + stopTime = 2359; + useChannel = false; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + channelMin = Channels->GetByNumber(cDevice::CurrentChannel()); + channelMax = Channels->GetByNumber(cDevice::CurrentChannel()); +#else + channelMin = Channels.GetByNumber(cDevice::CurrentChannel()); + channelMax = Channels.GetByNumber(cDevice::CurrentChannel()); +#endif + channelGroup = ""; + useCase = false; + mode = 0; + useTitle = true; + useSubtitle = true; + useDescription = true; + useDuration = false; + minDuration = 0; + maxDuration = 2359; + useAsSearchTimer = true; + useDayOfWeek = false; + dayOfWeek = 0; + directory = ""; + useEpisode = 0; + priority = 99; + lifetime = 99; + marginStart = 5; + marginStop = 5; + useVPS = false; + action = 0; + useExtEPGInfo = 0; + extEPGInfoValues = ""; + avoidRepeats = 1; + allowedRepeats = 1; + compareTitle = 1; + compareSubtitle = 2; + compareSummary = 1; + catvaluesAvoidRepeat = 0; + repeatsWithinDays = 0; + delAfterDays = 0; + recordingsKeep = 0; + switchMinsBefore = 0; + pauseOnNrRecordings = 0; + blacklistMode = 0; + blacklists = ""; + fuzzyTolerance = 0; + useInFavorites = 0; + menuTemplate = 0; + delMode = 0; + delAfterCountRecs = 0; + delAfterDaysOfFirstRec = 0; + useAsSearchTimerFrom = 0; + useAsSearchTimerTil = 0; + ignoreMissingEPGCats = 0; + unmuteSoundOnSwitch = 0; + compareSummaryMatchInPercent = 0; + contentsFilter = ""; + compareDate = 0; +} + +cTVGuideSearchTimer::~cTVGuideSearchTimer(void) { +} + +bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const { + std::string searchStringOther = other.SearchString(); + searchStringOther = StrToLowerCase(searchStringOther); + std::string thisSearchString = StrToLowerCase(searchString); + int comp = thisSearchString.compare(searchStringOther); + if (comp < 0) + return true; + return false; +} + + +void cTVGuideSearchTimer::SetTemplate(std::string tmpl) { + std::stringstream searchTimerString; + searchTimerString << "0:"; + searchTimerString << tmpl; + strTimer = searchTimerString.str(); +} + +int cTVGuideSearchTimer::DayOfWeek(void) { + int vdrDayOfWeek = 0; + if (dayOfWeek >= 0) { + vdrDayOfWeek = pow(2, (dayOfWeek+6)%7); + } else if (dayOfWeek < 0) { + int absDayOfWeek = abs(dayOfWeek); + for (int i=0; i < 7; i++) { + if (absDayOfWeek & (1 << i)) { + vdrDayOfWeek += pow(2, (i+6)%7); + } + } + } + return vdrDayOfWeek; +} + +void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) { + int epgSearchDayOfWeek = 0; + for (int i=0; i < 7; i++) { + if (VDRDayOfWeek & (1 << i)) { + epgSearchDayOfWeek += pow(2, (i+1)%7); + } + } + this->dayOfWeek = epgSearchDayOfWeek * (-1); +} + +/* + 0 - unique search timer id + 1 - the search term + 2 - use time? 0/1 + 3 - start time in HHMM + 4 - stop time in HHMM + 5 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only + 6 - if 'use channel' = 1 then channel id[|channel id] in VDR format, + one entry or min/max entry separated with |, if 'use channel' = 2 + then the channel group name + 7 - match case? 0/1 + 8 - search mode: + 0 - the whole term must appear as substring + 1 - all single terms (delimiters are blank,',', ';', '|' or '~') + must exist as substrings. + 2 - at least one term (delimiters are blank, ',', ';', '|' or '~') + must exist as substring. + 3 - matches exactly + 4 - regular expression + 9 - use title? 0/1 + 10 - use subtitle? 0/1 + 11 - use description? 0/1 + 12 - use duration? 0/1 + 13 - min duration in hhmm + 14 - max duration in hhmm + 15 - use as search timer? 0/1 + 16 - use day of week? 0/1 + 17 - day of week (0 = Sunday, 1 = Monday...; + -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue) + 18 - use series recording? 0/1 + 19 - directory for recording + 20 - priority of recording + 21 - lifetime of recording + 22 - time margin for start in minutes + 23 - time margin for stop in minutes + 24 - use VPS? 0/1 + 25 - action: + 0 = create a timer + 1 = announce only via OSD (no timer) + 2 = switch only (no timer) + 3 = announce via OSD and switch (no timer) + 4 = announce via mail + 26 - use extended EPG info? 0/1 + 27 - extended EPG info values. This entry has the following format + (delimiter is '|' for each category, '#' separates id and value): + 1 - the id of the extended EPG info category as specified in + epgsearchcats.conf + 2 - the value of the extended EPG info category + (a ':' will be translated to "!^colon^!", e.g. in "16:9") + 28 - avoid repeats? 0/1 + 29 - allowed repeats + 30 - compare title when testing for a repeat? 0/1 + 31 - compare subtitle when testing for a repeat? 0/1/2 + 0 - no + 1 - yes + 2 - yes, if present + 32 - compare description when testing for a repeat? 0/1 + 33 - compare extended EPG info when testing for a repeat? + This entry is a bit field of the category IDs. + 34 - accepts repeats only within x days + 35 - delete a recording automatically after x days + 36 - but keep this number of recordings anyway + 37 - minutes before switch (if action = 2) + 38 - pause if x recordings already exist + 39 - blacklist usage mode (0 none, 1 selection, 2 all) + 40 - selected blacklist IDs separated with '|' + 41 - fuzzy tolerance value for fuzzy searching + 42 - use this search in favorites menu (0 no, 1 yes) + 43 - id of a menu search template + 44 - auto deletion mode (0 don't delete search timer, 1 delete after given + count of recordings, 2 delete after given days after first recording) + 45 - count of recordings after which to delete the search timer + 46 - count of days after the first recording after which to delete the search + timer + 47 - first day where the search timer is active (see parameter 16) + 48 - last day where the search timer is active (see parameter 16) + 49 - ignore missing EPG categories? 0/1 + 50 - unmute sound if off when used as switch timer + 51 - percentage of match when comparing the summary of two events (with 'avoid repeats') + 52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars + 53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month) +*/ +bool cTVGuideSearchTimer::Parse(bool readTemplate) { + splitstring s(strTimer.c_str()); + std::vector values = s.split(':', 1); + int numValues = values.size(); + if (numValues < 12) + return false; + for (int value = 0; value < numValues; value++) { + switch (value) { + case 0: + if (!readTemplate) + ID = atoi(values[value].c_str()); + break; + case 1: + if (!readTemplate) { + std::string searchStringMasked = values[value]; + std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':'); + searchString = searchStringMasked; + } + break; + case 2: + useTime = atoi(values[value].c_str()); + break; + case 3: + if (useTime) { + startTime = atoi(values[value].c_str()); + } + break; + case 4: + if (useTime) { + stopTime = atoi(values[value].c_str()); + } + break; + case 5: + useChannel = atoi(values[value].c_str()); + break; + case 6: + if (useChannel == 0) { + channelMin = NULL; + channelMax = NULL; + } else if (useChannel == 1) { + char *channelMinbuffer = NULL; + char *channelMaxbuffer = NULL; + int channels = sscanf(values[value].c_str(), "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channelsP = Channels; +#else + cChannels* channelsP = &Channels; +#endif + channelMin = channelsP->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); + if (!channelMin) { + channelMin = channelMax = NULL; + useChannel = 0; + } + if (channels == 1) + channelMax = channelMin; + else { + channelMax = channelsP->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); + if (!channelMax) { + channelMin = channelMax = NULL; + useChannel = 0; + } + } + free(channelMinbuffer); + free(channelMaxbuffer); + } else if (useChannel == 2) { + channelGroup = values[value]; + } + break; + case 7: + useCase = atoi(values[value].c_str()); + break; + case 8: + mode = atoi(values[value].c_str()); + break; + case 9: + useTitle = atoi(values[value].c_str()); + break; + case 10: + useSubtitle = atoi(values[value].c_str()); + break; + case 11: + useDescription = atoi(values[value].c_str()); + break; + case 12: + useDuration = atoi(values[value].c_str()); + break; + case 13: + minDuration = atoi(values[value].c_str()); + break; + case 14: + maxDuration = atoi(values[value].c_str()); + break; + case 15: + useAsSearchTimer = atoi(values[value].c_str()); + break; + case 16: + useDayOfWeek = atoi(values[value].c_str()); + break; + case 17: + dayOfWeek = atoi(values[value].c_str()); + break; + case 18: + useEpisode = atoi(values[value].c_str()); + break; + case 19: + directory = values[value]; + break; + case 20: + priority = atoi(values[value].c_str()); + break; + case 21: + lifetime = atoi(values[value].c_str()); + break; + case 22: + marginStart = atoi(values[value].c_str()); + break; + case 23: + marginStop = atoi(values[value].c_str()); + break; + case 24: + useVPS = atoi(values[value].c_str()); + break; + case 25: + action = atoi(values[value].c_str()); + break; + case 26: + useExtEPGInfo = atoi(values[value].c_str()); + break; + case 27: + extEPGInfoValues = values[value]; + break; + case 28: + avoidRepeats = atoi(values[value].c_str()); + break; + case 29: + allowedRepeats = atoi(values[value].c_str()); + break; + case 30: + compareTitle = atoi(values[value].c_str()); + break; + case 31: + compareSubtitle = atoi(values[value].c_str()); + break; + case 32: + compareSummary = atoi(values[value].c_str()); + break; + case 33: + catvaluesAvoidRepeat = atol(values[value].c_str()); + break; + case 34: + repeatsWithinDays = atoi(values[value].c_str()); + break; + case 35: + delAfterDays = atoi(values[value].c_str()); + break; + case 36: + recordingsKeep = atoi(values[value].c_str()); + break; + case 37: + switchMinsBefore = atoi(values[value].c_str()); + break; + case 38: + pauseOnNrRecordings = atoi(values[value].c_str()); + break; + case 39: + blacklistMode = atoi(values[value].c_str()); + break; + case 40: + blacklists = values[value]; + break; + case 41: + fuzzyTolerance = atoi(values[value].c_str()); + break; + case 42: + useInFavorites = atoi(values[value].c_str()); + break; + case 43: + menuTemplate = atoi(values[value].c_str()); + break; + case 44: + delMode = atoi(values[value].c_str()); + break; + case 45: + delAfterCountRecs = atoi(values[value].c_str()); + break; + case 46: + delAfterDaysOfFirstRec = atoi(values[value].c_str()); + break; + case 47: + useAsSearchTimerFrom = atol(values[value].c_str()); + break; + case 48: + useAsSearchTimerTil = atol(values[value].c_str()); + break; + case 49: + ignoreMissingEPGCats = atoi(values[value].c_str()); + break; + case 50: + unmuteSoundOnSwitch = atoi(values[value].c_str()); + break; + case 51: + compareSummaryMatchInPercent = atoi(values[value].c_str()); + break; + case 52: + contentsFilter = values[value]; + break; + case 53: + compareDate = atoi(values[value].c_str()); + break; + default: + break; + } + } + return true; +} + +std::string cTVGuideSearchTimer::BuildSearchString(void) { + std::stringstream search; + // 0 - 2 + if (ID > -1) + search << ID << ":"; + else + search << ":"; + std::string searchStringMasked = searchString; + std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|'); + search << searchStringMasked << ":"; + search << useTime << ":"; + + // 3 - 6 + if (useTime) { + search << *cString::sprintf("%04d", startTime) << ":"; + search << *cString::sprintf("%04d", stopTime) << ":"; + } else { + search << "::"; + } + + search << useChannel << ":"; + if (useChannel == 1) { + if (channelMin && channelMax) { + if (channelMin->Number() < channelMax->Number()) + search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":"; + else + search << std::string(channelMin->GetChannelID().ToString()) << ":"; + } else { + search << "0:"; + } + } else if (useChannel == 2) { + search << channelGroup << ":"; + } else { + search << "0:"; + } + // 7 - 14 + search << useCase << ":"; + search << mode << ":"; + search << useTitle << ":"; + search << useSubtitle << ":"; + search << useDescription << ":"; + search << useDuration << ":"; + if (useDuration) { + search << *cString::sprintf("%04d", minDuration) << ":"; + search << *cString::sprintf("%04d", maxDuration) << ":"; + } else { + search << "::"; + } + //15 - 53 + search << useAsSearchTimer << ":"; + search << useDayOfWeek << ":"; + search << dayOfWeek << ":"; + search << useEpisode << ":"; + search << directory << ":"; + search << priority << ":"; + search << lifetime << ":"; + search << marginStart << ":"; + search << marginStop << ":"; + search << useVPS << ":"; + search << action << ":"; + search << useExtEPGInfo << ":"; + search << extEPGInfoValues << ":"; + search << avoidRepeats << ":"; + search << allowedRepeats << ":"; + search << compareTitle << ":"; + search << compareSubtitle << ":"; + search << compareSummary << ":"; + search << catvaluesAvoidRepeat << ":"; + search << repeatsWithinDays << ":"; + search << delAfterDays << ":"; + search << recordingsKeep << ":"; + search << switchMinsBefore << ":"; + search << pauseOnNrRecordings << ":"; + search << blacklistMode << ":"; + search << blacklists << ":"; + search << fuzzyTolerance << ":"; + search << useInFavorites << ":"; + search << menuTemplate << ":"; + search << delMode << ":"; + search << delAfterCountRecs << ":"; + search << delAfterDaysOfFirstRec << ":"; + search << useAsSearchTimerFrom << ":"; + search << useAsSearchTimerTil << ":"; + search << ignoreMissingEPGCats << ":"; + search << unmuteSoundOnSwitch << ":"; + search << compareSummaryMatchInPercent << ":"; + search << contentsFilter << ":"; + search << compareDate; + + strTimer = search.str(); + return strTimer; +} + +bool cTVGuideSearchTimer::Active(void) { + if (useAsSearchTimer) + return true; + return false; +} + +void cTVGuideSearchTimer::SetStartChannel(int startChannel) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + channelMin = Channels->GetByNumber(startChannel); +#else + channelMin = Channels.GetByNumber(startChannel); +#endif +} + +void cTVGuideSearchTimer::SetStopChannel(int stopChannel) { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + channelMax = Channels->GetByNumber(stopChannel); +#else + channelMax = Channels.GetByNumber(stopChannel); +#endif +} + +int cTVGuideSearchTimer::GetNumTimers(void) { + int numTimers = 0; + if (ID < 0) + return numTimers; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + for (const cTimer *timer = timers->First(); timer; timer = timers->Next(timer)) { + char* searchID = GetAuxValue(timer, "s-id"); + if (!searchID) continue; + if (ID == atoi(searchID)) + numTimers++; + free(searchID); + } + return numTimers; +} + +int cTVGuideSearchTimer::GetNumRecordings(void) { + int numRecordings = 0; + if (ID < 0) + return numRecordings; +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_RECORDINGS_READ; + const cRecordings* recordings = Recordings; +#else + cRecordings* recordings = &Recordings; +#endif + for (const cRecording *recording = recordings->First(); recording; recording = recordings->Next(recording)) { + if (recording->IsEdited()) + continue; + if (!recording->Info()) + continue; + char* searchID = GetAuxValue(recording, "s-id"); + if (!searchID) continue; + if (ID == atoi(searchID)) + numRecordings++; + free(searchID); + } + return numRecordings; +} + +void cTVGuideSearchTimer::GetSearchModes(std::vector *searchModes) { + searchModes->push_back(tr("whole term must appear")); + searchModes->push_back(tr("all terms must exist")); + searchModes->push_back(tr("one term must exist")); + searchModes->push_back(tr("exact match")); + searchModes->push_back(tr("regular expression")); +} + + +void cTVGuideSearchTimer::Dump(void) { + esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str()); + esyslog("tvguide searchtimer: ID: %d", ID); + esyslog("tvguide searchtimer: searchString: %s", searchString.c_str()); + esyslog("tvguide searchtimer: useTime: %d", useTime); + esyslog("tvguide searchtimer: startTime: %d", startTime); + esyslog("tvguide searchtimer: stopTime: %d", stopTime); + esyslog("tvguide searchtimer: useChannel: %d", useChannel); + if (channelMin) + esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name()); + if (channelMax) + esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name()); + esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str()); + esyslog("tvguide searchtimer: useCase: %d", useCase); + esyslog("tvguide searchtimer: mode: %d", mode); + esyslog("tvguide searchtimer: useTitle: %d", useTitle); + esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle); + esyslog("tvguide searchtimer: useDescription: %d", useDescription); +} + diff --git a/searchtimer.h b/searchtimer.h index f797ebd..d0e944c 100644 --- a/searchtimer.h +++ b/searchtimer.h @@ -1,136 +1,136 @@ -#ifndef __TVGUIDE_SEARCHTIMER_H -#define __TVGUIDE_SEARCHTIMER_H - - -class cTVGuideSearchTimer { -private: - std::string strTimer; - int ID; - std::string searchString; - int useTime; - int startTime; - int stopTime; - int useChannel; - cChannel *channelMin; - cChannel *channelMax; - std::string channelGroup; - int useCase; - int mode; - int useTitle; - int useSubtitle; - int useDescription; - int useDuration; - int minDuration; - int maxDuration; - int useAsSearchTimer; - int useDayOfWeek; - int dayOfWeek; - int useEpisode; - std::string directory; - int priority; - int lifetime; - int marginStart; - int marginStop; - int useVPS; - int action; - int useExtEPGInfo; - std::string extEPGInfoValues; - int avoidRepeats; - int allowedRepeats; - int compareTitle; - int compareSubtitle; - int compareSummary; - unsigned long catvaluesAvoidRepeat; - int repeatsWithinDays; - int delAfterDays; - int recordingsKeep; - int switchMinsBefore; - int pauseOnNrRecordings; - int blacklistMode; - std::string blacklists; - int fuzzyTolerance; - int useInFavorites; - int menuTemplate; - int delMode; - int delAfterCountRecs; - int delAfterDaysOfFirstRec; - int useAsSearchTimerFrom; - int useAsSearchTimerTil; - int ignoreMissingEPGCats; - int unmuteSoundOnSwitch; - int compareSummaryMatchInPercent; - std::string contentsFilter; - int compareDate; -public: - cTVGuideSearchTimer(void); - virtual ~cTVGuideSearchTimer(void); - bool operator < (const cTVGuideSearchTimer& other) const; - void SetEPGSearchString(std::string strTimer) { this->strTimer = strTimer; }; - void SetTemplate(std::string tmpl); - bool Parse(bool readTemplate = false); - std::string BuildSearchString(void); - int GetID(void) { return ID; }; - //GETTER - std::string SearchString(void) const { return searchString; }; - bool Active(void); - bool UseTitle(void) { return useTitle; }; - bool UseSubtitle(void) { return useSubtitle; }; - bool UseDescription(void) { return useDescription; }; - int SearchMode(void) { return mode; }; - bool UseChannel(void) { return useChannel; }; - int StartChannel(void) { return (channelMin)?channelMin->Number():0; }; - int StopChannel(void) { return (channelMax)?channelMax->Number():0; }; - bool UseTime(void) { return useTime; }; - int StartTime(void) { return startTime; }; - int StopTime(void) { return stopTime; }; - bool UseDayOfWeek(void) { return useDayOfWeek; }; - int DayOfWeek(void); - int UseEpisode(void) { return useEpisode; }; - std::string Directory(void) { return directory; }; - int Priority(void) { return priority; }; - int Lifetime(void) { return lifetime; }; - int MarginStart(void) { return marginStart; }; - int MarginStop(void) { return marginStop; }; - bool UseVPS(void) { return useVPS; }; - bool AvoidRepeats(void) { return avoidRepeats; }; - int AllowedRepeats(void) { return allowedRepeats; }; - bool CompareTitle(void) { return compareTitle; }; - bool CompareSubtitle(void) { return compareSubtitle; }; - bool CompareSummary(void) { return compareSummary; }; - bool UseInFavorites(void) { return useInFavorites; }; - //SETTER - void SetSearchString(std::string searchString) { this->searchString = searchString; }; - void SetActive(bool active) { useAsSearchTimer = active; }; - void SetSearchMode(int searchMode) { mode = searchMode; }; - void SetUseTitle(bool useTitle) { this->useTitle = useTitle; }; - void SetUseSubtitle(bool useSubtitle) { this->useSubtitle = useSubtitle; }; - void SetUseDesription(bool useDescription) { this->useDescription = useDescription; }; - void SetUseChannel(bool useChannel) { this->useChannel = useChannel; }; - void SetStartChannel(int startChannel) { channelMin = Channels.GetByNumber(startChannel); }; - void SetStopChannel(int stopChannel) { channelMax = Channels.GetByNumber(stopChannel); }; - void SetUseTime(bool useTime) { this->useTime = useTime; }; - void SetStartTime(int startTime) { this->startTime = startTime; }; - void SetStopTime(int stopTime) { this->stopTime = stopTime; }; - void SetUseDayOfWeek(bool useDayOfWeek) { this->useDayOfWeek = useDayOfWeek; }; - void SetDayOfWeek(int VDRDayOfWeek); - void SetUseEpisode(int useEpisode) { this->useEpisode = useEpisode; }; - void SetDirectory(std::string directory) { this-> directory = directory; }; - void SetPriority(int priority) { this->priority = priority; }; - void SetLifetime(int lifetime) { this->lifetime = lifetime; }; - void SetMarginStart(int marginStart) { this->marginStart = marginStart; }; - void SetMarginStop(int marginStop) { this->marginStop = marginStop; }; - void SetUseVPS(bool useVPS) { this->useVPS = useVPS; }; - void SetAvoidRepeats(bool avoidRepeats) { this->avoidRepeats = avoidRepeats; }; - void SetAllowedRepeats(int allowedRepeats) { this->allowedRepeats = allowedRepeats; }; - void SetCompareTitle(bool compareTitle) { this->compareTitle = compareTitle; }; - void SetCompareSubtitle(bool compareSubtitle) { this->compareSubtitle = compareSubtitle; }; - void SetCompareSummary(bool compareSummary) { this->compareSummary = compareSummary; }; - void SetUseInFavorites(bool useInFavorites) { this->useInFavorites = useInFavorites; }; - //COMMON - int GetNumTimers(void); - int GetNumRecordings(void); - void GetSearchModes(std::vector *searchModes); - void Dump(void); -}; - -#endif //__TVGUIDE_SEARCHTIMER_H +#ifndef __TVGUIDE_SEARCHTIMER_H +#define __TVGUIDE_SEARCHTIMER_H + + +class cTVGuideSearchTimer { +private: + std::string strTimer; + int ID; + std::string searchString; + int useTime; + int startTime; + int stopTime; + int useChannel; + const cChannel *channelMin; + const cChannel *channelMax; + std::string channelGroup; + int useCase; + int mode; + int useTitle; + int useSubtitle; + int useDescription; + int useDuration; + int minDuration; + int maxDuration; + int useAsSearchTimer; + int useDayOfWeek; + int dayOfWeek; + int useEpisode; + std::string directory; + int priority; + int lifetime; + int marginStart; + int marginStop; + int useVPS; + int action; + int useExtEPGInfo; + std::string extEPGInfoValues; + int avoidRepeats; + int allowedRepeats; + int compareTitle; + int compareSubtitle; + int compareSummary; + unsigned long catvaluesAvoidRepeat; + int repeatsWithinDays; + int delAfterDays; + int recordingsKeep; + int switchMinsBefore; + int pauseOnNrRecordings; + int blacklistMode; + std::string blacklists; + int fuzzyTolerance; + int useInFavorites; + int menuTemplate; + int delMode; + int delAfterCountRecs; + int delAfterDaysOfFirstRec; + int useAsSearchTimerFrom; + int useAsSearchTimerTil; + int ignoreMissingEPGCats; + int unmuteSoundOnSwitch; + int compareSummaryMatchInPercent; + std::string contentsFilter; + int compareDate; +public: + cTVGuideSearchTimer(void); + virtual ~cTVGuideSearchTimer(void); + bool operator < (const cTVGuideSearchTimer& other) const; + void SetEPGSearchString(std::string strTimer) { this->strTimer = strTimer; }; + void SetTemplate(std::string tmpl); + bool Parse(bool readTemplate = false); + std::string BuildSearchString(void); + int GetID(void) { return ID; }; + //GETTER + std::string SearchString(void) const { return searchString; }; + bool Active(void); + bool UseTitle(void) { return useTitle; }; + bool UseSubtitle(void) { return useSubtitle; }; + bool UseDescription(void) { return useDescription; }; + int SearchMode(void) { return mode; }; + bool UseChannel(void) { return useChannel; }; + int StartChannel(void) { return (channelMin)?channelMin->Number():0; }; + int StopChannel(void) { return (channelMax)?channelMax->Number():0; }; + bool UseTime(void) { return useTime; }; + int StartTime(void) { return startTime; }; + int StopTime(void) { return stopTime; }; + bool UseDayOfWeek(void) { return useDayOfWeek; }; + int DayOfWeek(void); + int UseEpisode(void) { return useEpisode; }; + std::string Directory(void) { return directory; }; + int Priority(void) { return priority; }; + int Lifetime(void) { return lifetime; }; + int MarginStart(void) { return marginStart; }; + int MarginStop(void) { return marginStop; }; + bool UseVPS(void) { return useVPS; }; + bool AvoidRepeats(void) { return avoidRepeats; }; + int AllowedRepeats(void) { return allowedRepeats; }; + bool CompareTitle(void) { return compareTitle; }; + bool CompareSubtitle(void) { return compareSubtitle; }; + bool CompareSummary(void) { return compareSummary; }; + bool UseInFavorites(void) { return useInFavorites; }; + //SETTER + void SetSearchString(std::string searchString) { this->searchString = searchString; }; + void SetActive(bool active) { useAsSearchTimer = active; }; + void SetSearchMode(int searchMode) { mode = searchMode; }; + void SetUseTitle(bool useTitle) { this->useTitle = useTitle; }; + void SetUseSubtitle(bool useSubtitle) { this->useSubtitle = useSubtitle; }; + void SetUseDesription(bool useDescription) { this->useDescription = useDescription; }; + void SetUseChannel(bool useChannel) { this->useChannel = useChannel; }; + void SetStartChannel(int startChannel); + void SetStopChannel(int stopChannel); + void SetUseTime(bool useTime) { this->useTime = useTime; }; + void SetStartTime(int startTime) { this->startTime = startTime; }; + void SetStopTime(int stopTime) { this->stopTime = stopTime; }; + void SetUseDayOfWeek(bool useDayOfWeek) { this->useDayOfWeek = useDayOfWeek; }; + void SetDayOfWeek(int VDRDayOfWeek); + void SetUseEpisode(int useEpisode) { this->useEpisode = useEpisode; }; + void SetDirectory(std::string directory) { this-> directory = directory; }; + void SetPriority(int priority) { this->priority = priority; }; + void SetLifetime(int lifetime) { this->lifetime = lifetime; }; + void SetMarginStart(int marginStart) { this->marginStart = marginStart; }; + void SetMarginStop(int marginStop) { this->marginStop = marginStop; }; + void SetUseVPS(bool useVPS) { this->useVPS = useVPS; }; + void SetAvoidRepeats(bool avoidRepeats) { this->avoidRepeats = avoidRepeats; }; + void SetAllowedRepeats(int allowedRepeats) { this->allowedRepeats = allowedRepeats; }; + void SetCompareTitle(bool compareTitle) { this->compareTitle = compareTitle; }; + void SetCompareSubtitle(bool compareSubtitle) { this->compareSubtitle = compareSubtitle; }; + void SetCompareSummary(bool compareSummary) { this->compareSummary = compareSummary; }; + void SetUseInFavorites(bool useInFavorites) { this->useInFavorites = useInFavorites; }; + //COMMON + int GetNumTimers(void); + int GetNumRecordings(void); + void GetSearchModes(std::vector *searchModes); + void Dump(void); +}; + +#endif //__TVGUIDE_SEARCHTIMER_H diff --git a/services/remotetimers.h b/services/remotetimers.h index cd86b7a..3a01388 100644 --- a/services/remotetimers.h +++ b/services/remotetimers.h @@ -9,7 +9,7 @@ struct RemoteTimers_Event_v1_0 { //in const cEvent *event; //out - cTimer *timer; + const cTimer *timer; cString errorMsg; }; @@ -17,7 +17,7 @@ struct RemoteTimers_GetMatch_v1_0 { //in const cEvent *event; //out - cTimer *timer; + const cTimer *timer; int timerMatch; int timerType; bool isRemote; @@ -30,4 +30,4 @@ struct RemoteTimers_Timer_v1_0 { cString errorMsg; }; -#endif //REMOTETIMERSERVICES_INC \ No newline at end of file +#endif //REMOTETIMERSERVICES_INC diff --git a/timemanager.c b/timemanager.c index f6a0dd3..bb056cc 100644 --- a/timemanager.c +++ b/timemanager.c @@ -1,173 +1,173 @@ -#include -#include -#include "config.h" -#include "timemanager.h" - -cTimeManager::cTimeManager(void) { - displayHours = config.displayHours; - displaySeconds = displayHours * 3600; - timeFormat = e24Hours; -} - -cTimeManager::~cTimeManager(void) { -} - -cString cTimeManager::PrintTime(time_t displayTime) { - struct tm *ts; - ts = localtime(&displayTime); - cString strTime = cString::sprintf("%d.%d-%d:%d.%d", ts->tm_mday, ts->tm_mon+1, ts->tm_hour, ts->tm_min, ts->tm_sec); - return strTime; -} - - -void cTimeManager::Now() { - t = time(0); - tStart = t; - tStart = GetRounded(); - tEnd = tStart + displaySeconds; -} - -void cTimeManager::AddMinutes(int step) { - tStart += step*60; - tEnd += step*60; -} - -bool cTimeManager::DelMinutes(int step) { - if ((tStart - step*60)+30*60 < t) { - return true; - } - tStart -= step*60; - tEnd -= step*60; - return false; -} - -void cTimeManager::SetTime(time_t newTime) { - tStart = newTime; - tEnd = tStart + displaySeconds; -} - -time_t cTimeManager::GetPrevPrimetime(time_t current) { - tm *st = localtime(¤t); - if (st->tm_hour < 21) { - current -= 24 * 60* 60; - st = localtime(¤t); - } - st->tm_hour = 20; - st->tm_min = 0; - time_t primeTime = mktime(st); - return primeTime; -} - -time_t cTimeManager::GetNextPrimetime(time_t current){ - tm *st = localtime(¤t); - if (st->tm_hour > 19) { - current += 24 * 60* 60; - st = localtime(¤t); - } - st->tm_hour = 20; - st->tm_min = 0; - time_t primeTime = mktime(st); - return primeTime; -} - -bool cTimeManager::TooFarInPast(time_t current) { - if (current < t) { - return true; - } - return false; -} - -cString cTimeManager::GetCurrentTime() { - char buf[25]; - t = time(0); - tm *st = localtime(&t); - if (timeFormat == e12Hours) { - strftime(buf, sizeof(buf), "%I:%M %p", st); - } else if (timeFormat == e24Hours) - strftime(buf, sizeof(buf), "%H:%M", st); - return buf; - -} - -cString cTimeManager::GetDate() { - char text[6]; - tm *st = localtime(&tStart); - snprintf(text, sizeof(text), "%d.%d", st->tm_mday, st->tm_mon+1); - return text; -} - -cString cTimeManager::GetWeekday() { - return WeekDayName(tStart); -} - -bool cTimeManager::IsStart(int activeStart) { - if (tStart <= t && activeStart <= t) - return true; - return false; -} - -time_t cTimeManager::GetRounded() { - tm *rounded = localtime ( &tStart ); - rounded->tm_sec = 0; - if (rounded->tm_min > 29) - rounded->tm_min = 30; - else - rounded->tm_min = 0; - return mktime(rounded); -} - -bool cTimeManager::NowVisible(void) { - if (t > tStart) - return true; - return false; -} - -void cTimeManager::Debug() { - esyslog("tvguideng: now %s, tStart: %s, tEnd: %s", *TimeString(t), *TimeString(tStart), *TimeString(tEnd)); -} - -// --- cTimeInterval ------------------------------------------------------------- - -cTimeInterval::cTimeInterval(time_t start, time_t stop) { - this->start = start; - this->stop = stop; -} - -cTimeInterval::~cTimeInterval(void) { -} - -cTimeInterval *cTimeInterval::Intersect(cTimeInterval *interval) { - time_t startIntersect, stopIntersect; - - if ((stop <= interval->Start()) || (interval->Stop() <= start)) { - return NULL; - } - - if (start <= interval->Start()) { - startIntersect = interval->Start(); - } else { - startIntersect = start; - } - if (stop <= interval->Stop()) { - stopIntersect = stop; - } else { - stopIntersect = interval->Stop(); - } - return new cTimeInterval(startIntersect, stopIntersect); -} - -cTimeInterval *cTimeInterval::Union(cTimeInterval *interval) { - time_t startUnion, stopUnion; - - if (start <= interval->Start()) { - startUnion = start; - } else { - startUnion = interval->Start(); - } - if (stop <= interval->Stop()) { - stopUnion = interval->Stop(); - } else { - stopUnion = stop; - } - return new cTimeInterval(startUnion, stopUnion); +#include +#include +#include "config.h" +#include "timemanager.h" + +cTimeManager::cTimeManager(void) { + displayHours = config.displayHours; + displaySeconds = displayHours * 3600; + timeFormat = e24Hours; +} + +cTimeManager::~cTimeManager(void) { +} + +cString cTimeManager::PrintTime(time_t displayTime) { + struct tm *ts; + ts = localtime(&displayTime); + cString strTime = cString::sprintf("%d.%d-%d:%d.%d", ts->tm_mday, ts->tm_mon+1, ts->tm_hour, ts->tm_min, ts->tm_sec); + return strTime; +} + + +void cTimeManager::Now() { + t = time(0); + tStart = t; + tStart = GetRounded(); + tEnd = tStart + displaySeconds; +} + +void cTimeManager::AddMinutes(int step) { + tStart += step*60; + tEnd += step*60; +} + +bool cTimeManager::DelMinutes(int step) { + if ((tStart - step*60)+30*60 < t) { + return true; + } + tStart -= step*60; + tEnd -= step*60; + return false; +} + +void cTimeManager::SetTime(time_t newTime) { + tStart = newTime; + tEnd = tStart + displaySeconds; +} + +time_t cTimeManager::GetPrevPrimetime(time_t current) { + tm *st = localtime(¤t); + if (st->tm_hour < 21) { + current -= 24 * 60* 60; + st = localtime(¤t); + } + st->tm_hour = 20; + st->tm_min = 0; + time_t primeTime = mktime(st); + return primeTime; +} + +time_t cTimeManager::GetNextPrimetime(time_t current){ + tm *st = localtime(¤t); + if (st->tm_hour > 19) { + current += 24 * 60* 60; + st = localtime(¤t); + } + st->tm_hour = 20; + st->tm_min = 0; + time_t primeTime = mktime(st); + return primeTime; +} + +bool cTimeManager::TooFarInPast(time_t current) { + if (current < t) { + return true; + } + return false; +} + +cString cTimeManager::GetCurrentTime() { + char buf[25]; + t = time(0); + tm *st = localtime(&t); + if (timeFormat == e12Hours) { + strftime(buf, sizeof(buf), "%I:%M %p", st); + } else if (timeFormat == e24Hours) + strftime(buf, sizeof(buf), "%H:%M", st); + return buf; + +} + +cString cTimeManager::GetDate() { + char text[6]; + tm *st = localtime(&tStart); + snprintf(text, sizeof(text), "%d.%d", st->tm_mday, st->tm_mon+1); + return text; +} + +cString cTimeManager::GetWeekday() { + return WeekDayName(tStart); +} + +bool cTimeManager::IsStart(int activeStart) { + if (tStart <= t && activeStart <= t) + return true; + return false; +} + +time_t cTimeManager::GetRounded() { + tm *rounded = localtime ( &tStart ); + rounded->tm_sec = 0; + if (rounded->tm_min > 29) + rounded->tm_min = 30; + else + rounded->tm_min = 0; + return mktime(rounded); +} + +bool cTimeManager::NowVisible(void) { + if (t > tStart) + return true; + return false; +} + +void cTimeManager::Debug() { + esyslog("tvguideng: now %s, tStart: %s, tEnd: %s", *TimeString(t), *TimeString(tStart), *TimeString(tEnd)); +} + +// --- cTimeInterval ------------------------------------------------------------- + +cTimeInterval::cTimeInterval(time_t start, time_t stop) { + this->start = start; + this->stop = stop; +} + +cTimeInterval::~cTimeInterval(void) { +} + +cTimeInterval *cTimeInterval::Intersect(cTimeInterval *interval) { + time_t startIntersect, stopIntersect; + + if ((stop <= interval->Start()) || (interval->Stop() <= start)) { + return NULL; + } + + if (start <= interval->Start()) { + startIntersect = interval->Start(); + } else { + startIntersect = start; + } + if (stop <= interval->Stop()) { + stopIntersect = stop; + } else { + stopIntersect = interval->Stop(); + } + return new cTimeInterval(startIntersect, stopIntersect); +} + +cTimeInterval *cTimeInterval::Union(cTimeInterval *interval) { + time_t startUnion, stopUnion; + + if (start <= interval->Start()) { + startUnion = start; + } else { + startUnion = interval->Start(); + } + if (stop <= interval->Stop()) { + stopUnion = interval->Stop(); + } else { + stopUnion = stop; + } + return new cTimeInterval(startUnion, stopUnion); } \ No newline at end of file diff --git a/timemanager.h b/timemanager.h index fb6b5b2..3a70365 100644 --- a/timemanager.h +++ b/timemanager.h @@ -1,61 +1,61 @@ -#ifndef __TVGUIDE_TIMEMANAGER_H -#define __TVGUIDE_TIMEMANAGER_H - -#include - -enum eTimeFormat { - e12Hours, - e24Hours -}; - -// --- cTimeManager ------------------------------------------------------------- - -class cTimeManager { - private: - time_t t; - time_t tStart; - time_t tEnd; - int displayHours; - int displaySeconds; - eTimeFormat timeFormat; - public: - cTimeManager(void); - virtual ~cTimeManager(void); - static cString PrintTime(time_t displayTime); - void Now(); - time_t GetNow() { return t; }; - void AddMinutes(int step); - bool DelMinutes(int step); - void SetTime(time_t newTime); - time_t Get() {return t;}; - time_t GetStart() {return tStart;}; - time_t GetEnd() {return tEnd;}; - cString GetCurrentTime(); - cString GetDate(); - cString GetWeekday(); - time_t GetPrevPrimetime(time_t current); - time_t GetNextPrimetime(time_t current); - bool TooFarInPast(time_t current); - bool IsStart(int activeStart); - time_t GetRounded(); - bool NowVisible(void); - int GetDisplaySeconds(void) {return displaySeconds; }; - void Debug(); -}; - -// --- cTimeInterval ------------------------------------------------------------- - -class cTimeInterval { - private: - time_t start; - time_t stop; - public: - cTimeInterval(time_t start, time_t stop); - virtual ~cTimeInterval(void); - time_t Start(void) { return start; }; - time_t Stop(void) { return stop; }; - cTimeInterval *Intersect(cTimeInterval *interval); - cTimeInterval *Union(cTimeInterval *interval); -}; - +#ifndef __TVGUIDE_TIMEMANAGER_H +#define __TVGUIDE_TIMEMANAGER_H + +#include + +enum eTimeFormat { + e12Hours, + e24Hours +}; + +// --- cTimeManager ------------------------------------------------------------- + +class cTimeManager { + private: + time_t t; + time_t tStart; + time_t tEnd; + int displayHours; + int displaySeconds; + eTimeFormat timeFormat; + public: + cTimeManager(void); + virtual ~cTimeManager(void); + static cString PrintTime(time_t displayTime); + void Now(); + time_t GetNow() { return t; }; + void AddMinutes(int step); + bool DelMinutes(int step); + void SetTime(time_t newTime); + time_t Get() {return t;}; + time_t GetStart() {return tStart;}; + time_t GetEnd() {return tEnd;}; + cString GetCurrentTime(); + cString GetDate(); + cString GetWeekday(); + time_t GetPrevPrimetime(time_t current); + time_t GetNextPrimetime(time_t current); + bool TooFarInPast(time_t current); + bool IsStart(int activeStart); + time_t GetRounded(); + bool NowVisible(void); + int GetDisplaySeconds(void) {return displaySeconds; }; + void Debug(); +}; + +// --- cTimeInterval ------------------------------------------------------------- + +class cTimeInterval { + private: + time_t start; + time_t stop; + public: + cTimeInterval(time_t start, time_t stop); + virtual ~cTimeInterval(void); + time_t Start(void) { return start; }; + time_t Stop(void) { return stop; }; + cTimeInterval *Intersect(cTimeInterval *interval); + cTimeInterval *Union(cTimeInterval *interval); +}; + #endif //__TVGUIDE_TIMEMANAGER_H \ No newline at end of file diff --git a/timerconflict.c b/timerconflict.c index a89dc2c..9ac6a7d 100644 --- a/timerconflict.c +++ b/timerconflict.c @@ -1,175 +1,182 @@ -#include -#include -#include -#include "helpers.h" -#include "timemanager.h" -#include "timerconflict.h" - -cTVGuideTimerConflict::cTVGuideTimerConflict(void) { - time = 0; - timeStart = 0; - timeStop = 0; - overlapStart = 0; - overlapStop = 0; - percentPossible = 0; - timerID = 0; -} - -cTVGuideTimerConflict::~cTVGuideTimerConflict(void) { - -} - -bool cTVGuideTimerConflict::timerInvolved(int involvedID) { - int numConflicts = timerIDs.size(); - for (int i=0; i::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) { - cTVGuideTimerConflict *conf = *it; - delete conf; - } - conflicts.clear(); -} - -void cTVGuideTimerConflicts::AddConflict(std::string epgSearchConflictLine) { - /* TIMERCONFLICT FORMAT: - The result list looks like this for example when we have 2 timer conflicts at one time: - 1190232780:152|30|50#152#45:45|10|50#152#45 - '1190232780' is the time of the conflict in seconds since 1970-01-01. - It's followed by list of timers that have a conflict at this time: - '152|30|50#1 int editTimer(cTimer *timer, bool active, int prio, int start, int stop); - 52#45' is the description of the first conflicting timer. Here: - '152' is VDR's timer id of this timer as returned from VDR's LSTT command - '30' is the percentage of recording that would be done (0...100) - '50#152#45' is the list of concurrent timers at this conflict - '45|10|50#152#45' describes the next conflict - */ - cTVGuideTimerConflict *conflict = new cTVGuideTimerConflict(); - splitstring s(epgSearchConflictLine.c_str()); - std::vector flds = s.split(':'); - if (flds.size() < 2) - return; - conflict->time = atoi(flds[0].c_str()); - splitstring s2(flds[1].c_str()); - std::vector flds2 = s2.split('|'); - if (flds2.size() < 3) - return; - conflict->timerID = atoi(flds2[0].c_str()); - conflict->percentPossible = atoi(flds2[1].c_str()); - splitstring s3(flds2[2].c_str()); - std::vector flds3 = s3.split('#'); - std::vector timerIDs; - for (int k = 0; k < (int)flds3.size(); k++) { - timerIDs.push_back(atoi(flds3[k].c_str()) - 1); - } - conflict->timerIDs = timerIDs; - conflicts.push_back(conflict); -} - -void cTVGuideTimerConflicts::CalculateConflicts(void) { - numConflicts = conflicts.size(); - for (int i=0; i < numConflicts; i++) { - cTimeInterval *unionSet = NULL; - int numTimers = conflicts[i]->timerIDs.size(); - for (int j=0; j < numTimers; j++) { - const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]); - if (timer) { - if (!unionSet) { - unionSet = new cTimeInterval(timer->StartTime(), timer->StopTime()); - } else { - cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime()); - cTimeInterval *newUnion = unionSet->Union(timerInterval); - delete unionSet; - delete timerInterval; - unionSet = newUnion; - } - } - } - conflicts[i]->timeStart = unionSet->Start(); - conflicts[i]->timeStop = unionSet->Stop(); - delete unionSet; - - cTimeInterval *intersect = NULL; - for (int j=0; j < numTimers; j++) { - const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]); - if (timer) { - if (!intersect) { - intersect = new cTimeInterval(timer->StartTime(), timer->StopTime()); - } else { - cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime()); - cTimeInterval *newIntersect = intersect->Intersect(timerInterval); - if (newIntersect) { - delete intersect; - intersect = newIntersect; - } - delete timerInterval; - } - } - } - conflicts[i]->overlapStart = intersect->Start(); - conflicts[i]->overlapStop = intersect->Stop(); - delete intersect; - } -} - -cTVGuideTimerConflict *cTVGuideTimerConflicts::GetCurrentConflict(void) { - if (currentConflict < 0) - return NULL; - if (currentConflict > (numConflicts-1)) - return NULL; - return conflicts[currentConflict]; -} - -int cTVGuideTimerConflicts::GetCurrentConflictTimerID(int timerIndex) { - if (currentConflict < 0) - return -1; - if (currentConflict > (numConflicts-1)) - return -1; - int numTimersInConflict = conflicts[currentConflict]->timerIDs.size(); - if (timerIndex > (numTimersInConflict - 1)) - return -1; - return conflicts[currentConflict]->timerIDs[timerIndex]; -} - -int cTVGuideTimerConflicts::GetCorrespondingConflict(int timerID) { - int conflictIndex = -1; - if (numConflicts > 0) { - for (int i=0; itimerInvolved(timerID)) { - conflictIndex = i; - break; - } - } - } - return conflictIndex; -} - -cTVGuideTimerConflict *cTVGuideTimerConflicts::GetConflict(int conflictIndex) { - if (conflictIndex < 0) - return NULL; - if (conflictIndex > (numConflicts-1)) - return NULL; - return conflicts[conflictIndex]; -} - -std::vector cTVGuideTimerConflicts::GetConflictsBetween(time_t start, time_t stop) { - std::vector conflictsFound; - for (int i=0; i < numConflicts; i++) { - if ((conflicts[i]->timeStart > start) && (conflicts[i]->timeStart < stop)|| - (conflicts[i]->timeStop > start) && (conflicts[i]->timeStop < stop)) - conflictsFound.push_back(conflicts[i]); - } - return conflictsFound; -} \ No newline at end of file +#include +#include +#include +#include "helpers.h" +#include "timemanager.h" +#include "timerconflict.h" + +cTVGuideTimerConflict::cTVGuideTimerConflict(void) { + time = 0; + timeStart = 0; + timeStop = 0; + overlapStart = 0; + overlapStop = 0; + percentPossible = 0; + timerID = 0; +} + +cTVGuideTimerConflict::~cTVGuideTimerConflict(void) { + +} + +bool cTVGuideTimerConflict::timerInvolved(int involvedID) { + int numConflicts = timerIDs.size(); + for (int i=0; i::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) { + cTVGuideTimerConflict *conf = *it; + delete conf; + } + conflicts.clear(); +} + +void cTVGuideTimerConflicts::AddConflict(std::string epgSearchConflictLine) { + /* TIMERCONFLICT FORMAT: + The result list looks like this for example when we have 2 timer conflicts at one time: + 1190232780:152|30|50#152#45:45|10|50#152#45 + '1190232780' is the time of the conflict in seconds since 1970-01-01. + It's followed by list of timers that have a conflict at this time: + '152|30|50#1 int editTimer(cTimer *timer, bool active, int prio, int start, int stop); + 52#45' is the description of the first conflicting timer. Here: + '152' is VDR's timer id of this timer as returned from VDR's LSTT command + '30' is the percentage of recording that would be done (0...100) + '50#152#45' is the list of concurrent timers at this conflict + '45|10|50#152#45' describes the next conflict + */ + cTVGuideTimerConflict *conflict = new cTVGuideTimerConflict(); + splitstring s(epgSearchConflictLine.c_str()); + std::vector flds = s.split(':'); + if (flds.size() < 2) + return; + conflict->time = atoi(flds[0].c_str()); + splitstring s2(flds[1].c_str()); + std::vector flds2 = s2.split('|'); + if (flds2.size() < 3) + return; + conflict->timerID = atoi(flds2[0].c_str()); + conflict->percentPossible = atoi(flds2[1].c_str()); + splitstring s3(flds2[2].c_str()); + std::vector flds3 = s3.split('#'); + std::vector timerIDs; + for (int k = 0; k < (int)flds3.size(); k++) { + timerIDs.push_back(atoi(flds3[k].c_str()) - 1); + } + conflict->timerIDs = timerIDs; + conflicts.push_back(conflict); +} + +void cTVGuideTimerConflicts::CalculateConflicts(void) { + numConflicts = conflicts.size(); + for (int i=0; i < numConflicts; i++) { + cTimeInterval *unionSet = NULL; + int numTimers = conflicts[i]->timerIDs.size(); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_TIMERS_READ; + const cTimers* timers = Timers; +#else + const cTimers* timers = &Timers; +#endif + + for (int j=0; j < numTimers; j++) { + const cTimer *timer = timers->Get(conflicts[i]->timerIDs[j]); + if (timer) { + if (!unionSet) { + unionSet = new cTimeInterval(timer->StartTime(), timer->StopTime()); + } else { + cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime()); + cTimeInterval *newUnion = unionSet->Union(timerInterval); + delete unionSet; + delete timerInterval; + unionSet = newUnion; + } + } + } + conflicts[i]->timeStart = unionSet->Start(); + conflicts[i]->timeStop = unionSet->Stop(); + delete unionSet; + + cTimeInterval *intersect = NULL; + for (int j=0; j < numTimers; j++) { + const cTimer *timer = timers->Get(conflicts[i]->timerIDs[j]); + if (timer) { + if (!intersect) { + intersect = new cTimeInterval(timer->StartTime(), timer->StopTime()); + } else { + cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime()); + cTimeInterval *newIntersect = intersect->Intersect(timerInterval); + if (newIntersect) { + delete intersect; + intersect = newIntersect; + } + delete timerInterval; + } + } + } + conflicts[i]->overlapStart = intersect->Start(); + conflicts[i]->overlapStop = intersect->Stop(); + delete intersect; + } +} + +cTVGuideTimerConflict *cTVGuideTimerConflicts::GetCurrentConflict(void) { + if (currentConflict < 0) + return NULL; + if (currentConflict > (numConflicts-1)) + return NULL; + return conflicts[currentConflict]; +} + +int cTVGuideTimerConflicts::GetCurrentConflictTimerID(int timerIndex) { + if (currentConflict < 0) + return -1; + if (currentConflict > (numConflicts-1)) + return -1; + int numTimersInConflict = conflicts[currentConflict]->timerIDs.size(); + if (timerIndex > (numTimersInConflict - 1)) + return -1; + return conflicts[currentConflict]->timerIDs[timerIndex]; +} + +int cTVGuideTimerConflicts::GetCorrespondingConflict(int timerID) { + int conflictIndex = -1; + if (numConflicts > 0) { + for (int i=0; itimerInvolved(timerID)) { + conflictIndex = i; + break; + } + } + } + return conflictIndex; +} + +cTVGuideTimerConflict *cTVGuideTimerConflicts::GetConflict(int conflictIndex) { + if (conflictIndex < 0) + return NULL; + if (conflictIndex > (numConflicts-1)) + return NULL; + return conflicts[conflictIndex]; +} + +std::vector cTVGuideTimerConflicts::GetConflictsBetween(time_t start, time_t stop) { + std::vector conflictsFound; + for (int i=0; i < numConflicts; i++) { + if ((conflicts[i]->timeStart > start) && (conflicts[i]->timeStart < stop)|| + (conflicts[i]->timeStop > start) && (conflicts[i]->timeStop < stop)) + conflictsFound.push_back(conflicts[i]); + } + return conflictsFound; +} diff --git a/timerconflict.h b/timerconflict.h index d3def89..d26d7fd 100644 --- a/timerconflict.h +++ b/timerconflict.h @@ -1,38 +1,38 @@ -#ifndef __TVGUIDE_TIMERCONFLICT_H -#define __TVGUIDE_TIMERCONFLICT_H - -class cTVGuideTimerConflict { -public: - cTVGuideTimerConflict(void); - virtual ~cTVGuideTimerConflict(void); - time_t time; - time_t timeStart; - time_t timeStop; - time_t overlapStart; - time_t overlapStop; - int percentPossible; - int timerID; - std::vector timerIDs; - bool timerInvolved(int involvedID); -}; - -class cTVGuideTimerConflicts { -private: - std::vector conflicts; - int numConflicts; - int currentConflict; -public: - cTVGuideTimerConflicts(void); - virtual ~cTVGuideTimerConflicts(void); - void AddConflict(std::string epgSearchConflictLine); - void CalculateConflicts(void); - int NumConflicts(void) {return numConflicts; }; - void SetCurrentConflict(int current) { currentConflict = current; }; - cTVGuideTimerConflict *GetCurrentConflict(void); - int GetCurrentConflictTimerID(int timerIndex); - int GetCorrespondingConflict(int timerID); - cTVGuideTimerConflict *GetConflict(int conflictIndex); - std::vector GetConflictsBetween(time_t start, time_t stop); -}; - +#ifndef __TVGUIDE_TIMERCONFLICT_H +#define __TVGUIDE_TIMERCONFLICT_H + +class cTVGuideTimerConflict { +public: + cTVGuideTimerConflict(void); + virtual ~cTVGuideTimerConflict(void); + time_t time; + time_t timeStart; + time_t timeStop; + time_t overlapStart; + time_t overlapStop; + int percentPossible; + int timerID; + std::vector timerIDs; + bool timerInvolved(int involvedID); +}; + +class cTVGuideTimerConflicts { +private: + std::vector conflicts; + int numConflicts; + int currentConflict; +public: + cTVGuideTimerConflicts(void); + virtual ~cTVGuideTimerConflicts(void); + void AddConflict(std::string epgSearchConflictLine); + void CalculateConflicts(void); + int NumConflicts(void) {return numConflicts; }; + void SetCurrentConflict(int current) { currentConflict = current; }; + cTVGuideTimerConflict *GetCurrentConflict(void); + int GetCurrentConflictTimerID(int timerIndex); + int GetCorrespondingConflict(int timerID); + cTVGuideTimerConflict *GetConflict(int conflictIndex); + std::vector GetConflictsBetween(time_t start, time_t stop); +}; + #endif //__TVGUIDE_RECMMANAGER_H \ No newline at end of file diff --git a/tvguidengosd.c b/tvguidengosd.c index 8024672..bdb7f36 100644 --- a/tvguidengosd.c +++ b/tvguidengosd.c @@ -53,8 +53,12 @@ void cTVGuideOSD::Show(void) { timeManager->Now(); epgGrid = new cEpgGrid(rootView, timeManager); - - cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel()); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *startChannel = Channels->GetByNumber(cDevice::CurrentChannel()); +#else + const cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel()); +#endif epgGrid->Init(startChannel); epgGrid->Activate(); epgGrid->DrawHeader(); @@ -338,7 +342,13 @@ void cTVGuideOSD::CheckTimeout(void) { int newChannelNum = channelJumper->GetChannel(); delete channelJumper; channelJumper = NULL; - const cChannel *newChannel = Channels.GetByNumber(newChannelNum); +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannels* channels = Channels; +#else + cChannels* channels = &Channels; +#endif + const cChannel *newChannel = channels->GetByNumber(newChannelNum); if (!newChannel) { return; } -- cgit v1.2.3