Bug Summary

File:menu_whatson.c
Location:line 492, column 13
Description:Value stored to 'nextShowMode' during its initialization is never read

Annotated Source Code

1/* -*- c++ -*-
2Copyright (C) 2004-2013 Christian Wieninger
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18
19The author can be reached at cwieninger@gmx.de
20
21The project's page is at http://winni.vdr-developer.org/epgsearch
22*/
23
24#include <vector>
25#include <iostream>
26#include <sstream>
27#include <string>
28#include "uservars.h"
29#include "menu_whatson.h"
30#include "epgsearchext.h"
31#include "menu_event.h"
32#include "menu_myedittimer.h"
33#include "menu_searchresults.h"
34#include "menu_search.h"
35#include "menu_commands.h"
36#include "epgsearchcfg.h"
37#include "switchtimer.h"
38#include "epgsearchcats.h"
39#include "conflictcheck.h"
40#include <math.h>
41#include <vdr/menu.h>
42#include "menu_conflictcheck.h"
43#include "templatefile.h"
44#include "menu_deftimercheckmethod.h"
45#include "timerstatus.h"
46
47#define HOURS(x)((x)/100) ((x)/100)
48#define MINUTES(x)((x)%100) ((x)%100)
49
50#define SKIPHOURS20 20
51#define HOURS2SECS(x)(x*60*60) (x*60*60)
52
53extern int exitToMainMenu;
54extern bool isUTF8;
55int gl_InfoConflict = 0;
56
57// --- cMenuMyScheduleItem ------------------------------------------------------
58cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate)
59{
60 event = Event;
61 channel = Channel;
62 mode = Mode;
63 timerMatch = tmNone;
64 inSwitchList = false;
65 menuTemplate = MenuTemplate;
66 Update(true);
67}
68
69bool cMenuMyScheduleItem::Update(bool Force)
70{
71 if (!menuTemplate)
72 return false;
73
74 const char* menutemplate = menuTemplate->MenuTemplate();
75 if (!menutemplate || strlen(menutemplate) == 0)
76 return false;
77
78 bool result = false;
79
80 eTimerMatch OldTimerMatch = timerMatch;
81 bool OldInSwitchList = inSwitchList;
82 bool hasMatch = false;
83 cTimer* timer = NULL__null;
84 if (event) timer = Timers.GetMatch(event, &timerMatch);
85 if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL__null);
86 if (timer) hasMatch = true;
87
88 if (Force || timerMatch != OldTimerMatch || inSwitchList != OldInSwitchList)
89 {
90 char szProgressPart[Utf8BufSize(12)((12) * 4)] = "";
91 char szProgressPartT2S[12] = "";
92 time_t now = time(NULL__null);
93 if (channel)
94 {
95 if (event)
96 {
97 time_t startTime = event->StartTime();
98 if ((now - event->StartTime()) >= 0 || strstr(menutemplate, "%time%") != NULL__null)
99 {
100 int frac = 0;
101 if (mode == showNow)
102 {
103 int dur = event->Duration();
104 if (dur != 0)
105 frac = ((now - startTime) * 8 + (dur >> 1)) / dur;
106 }
107 if (mode == showNext)
108 frac = ( ( 30*60 - min((time_t)30*60, startTime - now) ) * 8 + 15*60 ) / (30*60);
109
110 frac = min(8,max(0, frac));
111
112 szProgressPartT2S[0] = '[';
113 memset(szProgressPartT2S + 1,'|',frac);
114 memset(szProgressPartT2S + 1 + frac ,' ', 8 - frac);
115 szProgressPartT2S[9] = ']';
116 szProgressPartT2S[10] = 0;
117
118 if (!isUTF8)
119 {
120 szProgressPart[0] = ICON_BAR_OPEN0x87;
121 memset(szProgressPart + 1, ICON_BAR_EMPTY0x89, 6);
122 szProgressPart[7] = ICON_BAR_CLOSE0x8A;
123 szProgressPart[8] = 0;
124 memset(szProgressPart, ICON_BAR_FULL0x88, frac?frac:sizeof(szProgressPart));
125 }
126 else
127 {
128#if defined(__GNUC__4) && __GNUC__4 < 3 && __GNUC_MINOR__2 < 96
129#else
130 std::stringstream buffer;
131 buffer << ICON_BAR_OPEN_UTF8"\uE007";
132 for(int i=0;i<8;i++) buffer << (i<frac?ICON_BAR_FULL_UTF8"\uE008":ICON_BAR_EMPTY_UTF8"\uE009");
133 buffer << ICON_BAR_CLOSE_UTF8"\uE00A";
134 char* temp = strdup(buffer.str().c_str());
135 sprintf(szProgressPart, "%s", temp);
136 free(temp);
137#endif
138 }
139 }
140 else
141 {
142 strncpy(szProgressPart, *event->GetTimeString(), 12);
143 szProgressPart[11] = 0;
144 memcpy(szProgressPartT2S, szProgressPart, 12);
145 }
146 }
147 }
148
149 char t[Utf8BufSize(2)((2) * 4)],v[Utf8BufSize(2)((2) * 4)],r[Utf8BufSize(2)((2) * 4)];
150 char szStatus[Utf8BufSize(4)((4) * 4)];
151 szStatus[3] = 0;
152 t[1]=v[1]=r[1] = 0;
153
154 if (EPGSearchConfig.WarEagle)
155 {
156 if (!isUTF8)
157 {
158 t[0] = event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording())?ICON_REC0x8B:ICON_CLOCK0x8C) : ICON_CLOCK_HALF0x94 : ' ';
159 v[0] = event && event->Vps() && (event->Vps() - event->StartTime()) ? ICON_VPS0x93 : ' ';
160 r[0] = event && event->IsRunning() ? ICON_RUNNING0x92 : ' ';
161 }
162 else
163 {
164#if defined(__GNUC__4) && __GNUC__4 < 3 && __GNUC_MINOR__2 < 96
165#else
166 sprintf(t, "%s", (event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording())?ICON_REC_UTF8"\uE00B":ICON_CLOCK_UTF8"\uE00C") : ICON_CLOCK_HALF_UTF8"\uE014" : " "));
167 sprintf(v, "%s", event && event->Vps() && (event->Vps() - event->StartTime()) ? ICON_VPS_UTF8"\uE013" : " ");
168 sprintf(r, "%s", (event && event->IsRunning() ? ICON_RUNNING_UTF8"\uE012" : " "));
169#endif
170 }
171 }
172 else
173 {
174 t[0] = event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording())?'R':'T') : 't' : ' ';
175 v[0] = event && event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
176 r[0] = event && event->IsRunning() ? '*' : ' ';
177 }
178
179 if (event && inSwitchList)
180 {
181 cSwitchTimer* s = SwitchTimers.InSwitchList(event);
182 t[0] = (s && s->mode==1)?'s':'S';
183 }
184 if (EPGSearchConfig.WarEagle && isUTF8)
185 {
186 std::stringstream buffer;
187 buffer << t << v << r;
188 char* temp = strdup(buffer.str().c_str());
189 sprintf(szStatus, "%s", temp);
190 free(temp);
191 }
192 else
193 {
194 szStatus[0] = t[0];
195 szStatus[1] = v[0];
196 szStatus[2] = r[0];
197 }
198
199 char* buffer = strdup(menutemplate);
200 strreplace(buffer, '|', '\t');
201
202 char* title;
203 title = strdup(event?event->Title():tr(">>> no info! <<<")I18nTranslate(">>> no info! <<<", "vdr-" "epgsearch"
)
);
204
205 title = strreplacei(title, ":", "%colon%"); // assume a title has the form "a?b:c",
206 // we need to replace the colon to avoid misinterpretation of the expression as a condition
207 buffer = strreplacei(buffer, "%title%", title);
208 free(title);
209
210 if (channel)
211 {
212 char szChannelNr[6] = "";
213 snprintf(szChannelNr, 6, "%d", channel->Number());
214 buffer = strreplacei(buffer, "%chnr%", szChannelNr);
215 buffer = strreplacei(buffer, "%chsh%", channel->ShortName(true));
216 buffer = strreplacei(buffer, "%chlng%", channel->Name());
217 buffer = strreplacei(buffer, "%progr%", szProgressPart);
218 buffer = strreplacei(buffer, "%progrT2S%", szProgressPartT2S);
219 }
220
221 // parse the epxression and evaluate it
222 cVarExpr varExpr(buffer);
223 char* tmp = strdup(varExpr.Evaluate(event).c_str());
224 free(buffer);
225 buffer = tmp;
226
227 buffer = strreplacei(buffer, "$status$", szStatus);
228 buffer = strreplacei(buffer, "$t_status$", t);
229 buffer = strreplacei(buffer, "$v_status$", v);
230 buffer = strreplacei(buffer, "$r_status$", r);
231
232 buffer = FixSeparators(buffer, '~');
233 buffer = FixSeparators(buffer, ':');
234 buffer = FixSeparators(buffer, '-');
235
236 SetText(buffer, false);
237
238 if (gl_InfoConflict == 0 && EPGSearchConfig.checkTimerConflAfterTimerProg && !Force && timer && timerMatch && timerMatch != OldTimerMatch)
239 {
240 cConflictCheck C;
241 C.Check();
242 if (C.TimerInConflict(timer))
243 gl_InfoConflict = 1;
244 }
245 return true;
246 }
247 return result;
248}
249
250void cMenuMyScheduleItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable)
251{
252#if APIVERSNUM20000 >= 10733
253 bool withDate = (channel == NULL__null); // search for a better way to determine this
254 if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, withDate, timerMatch))
255 DisplayMenu->SetItem(Text(), Index, Current, Selectable);
256#endif
257}
258
259// --- cMenuMyScheduleSepItem ------------------------------------------------------
260cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cEvent *Event, cChannel *Channel)
261 : cMenuMyScheduleItem(Event, Channel, showNow, NULL__null)
262{
263 event = Event;
264 channel = Channel;
265 dummyEvent = NULL__null;
266 SetSelectable(false);
267 Update(true);
268}
269
270cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem()
271{
272 if (dummyEvent)
273 delete dummyEvent;
274}
275
276bool cMenuMyScheduleSepItem::Update(bool Force)
277{
278 if (channel)
279 SetText(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS"----------------------------------------", channel->Name(), MENU_SEPARATOR_ITEMS"----------------------------------------"));
280 else if (event)
281 {
282 dummyEvent = new cEvent(0);
283 dummyEvent->SetTitle(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS"----------------------------------------", GETDATESTRING(event)*(event->GetDateString()), MENU_SEPARATOR_ITEMS"----------------------------------------"));
284 SetText(dummyEvent->Title());
285 }
286 return true;
287}
288
289void cMenuMyScheduleSepItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable)
290{
291#if APIVERSNUM20000 >= 10733
292 bool withDate = (channel == NULL__null); // search for a better way to determine this
293 if (!DisplayMenu->SetItemEvent(dummyEvent, Index, Current, Selectable, channel, withDate, timerMatch))
294 DisplayMenu->SetItem(Text(), Index, Current, Selectable);
295#endif
296}
297
298
299// --- cMenuWhatsOnSearch ----------------------------------------------------------
300
301int cMenuWhatsOnSearch::currentChannel = 0;
302showMode cMenuWhatsOnSearch::currentShowMode = showNow;
303cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL__null;
304extern const char *ShowModes[];
305cList<cShowMode> cMenuWhatsOnSearch::showModes;
306time_t cMenuWhatsOnSearch::seekTime = 0;
307int cMenuWhatsOnSearch::shiftTime = 0;
308
309cMenuWhatsOnSearch::cMenuWhatsOnSearch(const cSchedules *Schedules, int CurrentChannelNr)
310 :cOsdMenu("", GetTab(1), GetTab(2), GetTab(3), GetTab(4), GetTab(5))
311{
312#if VDRVERSNUM20005 >= 10734
313 if (currentShowMode == showNow)
314 SetMenuCategory(mcScheduleNow);
315 else if (currentShowMode == showNext)
316 SetMenuCategory(mcScheduleNext);
317 else
318 SetMenuCategory(mcSchedule);
319#endif
320
321 helpKeys = -1;
322 shiftTime = 0;
323 schedules = Schedules;
324
325 CreateShowModes();
326
327 LoadSchedules();
328
329 currentChannel = CurrentChannelNr;
330
331 SetHelpKeys();
332}
333
334cMenuWhatsOnSearch::~cMenuWhatsOnSearch()
335{
336}
337
338#ifdef USE_GRAPHTFT
339const char* cMenuWhatsOnSearch::MenuKind()
340{
341 if (currentShowMode == showNow) return "MenuEpgsWhatsOnNow";
342 if (currentShowMode == showNext) return "MenuEpgsWhatsOnNext";
343 if (currentShowMode > showNext) return "MenuEpgsWhatsOnElse";
344 else return "MenuWhatsOnElse";
345}
346
347void cMenuWhatsOnSearch::Display(void)
348{
349 cOsdMenu::Display();
350
351 if (Count() > 0)
352 {
353 int i = 0;
354
355 for (cOsdItem *item = First(); item; item = Next(item))
356 cStatus::MsgOsdEventItem(!item->Selectable() ? 0 :
357 ((cMenuMyScheduleItem*)item)->event,
358 item->Text(), i++, Count());
359 }
360}
361#endif /* GRAPHTFT */
362
363int cMenuWhatsOnSearch::GetTab(int Tab)
364{
365 if (currentShowMode == showNow)
366 return cTemplFile::GetTemplateByName("MenuWhatsOnNow")->Tab(Tab-1);
367 if (currentShowMode == showNext)
368 return cTemplFile::GetTemplateByName("MenuWhatsOnNext")->Tab(Tab-1);
369 if (currentShowMode > showNext)
370 return cTemplFile::GetTemplateByName("MenuWhatsOnElse")->Tab(Tab-1);
371 else
372 return 0;
373}
374
375void cMenuWhatsOnSearch::LoadSchedules()
376{
377 Clear();
378 eventObjects.Clear();
379
380 // time_t SeekTime;
381 cString szTitle;
382 cShowMode* mode = GetShowMode(currentShowMode);
383 if (!mode) return;
384
385 if (shiftTime != 0)
386 {
387 if (currentShowMode == showNow || currentShowMode == showNext)
388 seekTime = time(NULL__null);
389 else
390 {
391 if (mode)
392 seekTime = GetTimeT(mode->GetTime());
393 if (seekTime < time(NULL__null)) seekTime += HOURS2SECS(24)(24*60*60);
394 }
395 seekTime += shiftTime*60;
396
397 struct tm tm_r;
398 time_t now = time(NULL__null);
399
400 tm tm_seek = *localtime_r(&seekTime, &tm_r);
401 tm tm_now = *localtime_r(&now, &tm_r);
402 if (tm_seek.tm_mday != tm_now.tm_mday)
403 szTitle = cString::sprintf("%s - %s", tr("Overview")I18nTranslate("Overview", "vdr-" "epgsearch"), DAYDATETIME(seekTime)*DayDateTime(seekTime));
404 else
405 szTitle = cString::sprintf("%s - %02d:%02d", tr("Overview")I18nTranslate("Overview", "vdr-" "epgsearch"), tm_seek.tm_hour, tm_seek.tm_min);
406 }
407 else
408 {
409 seekTime = GetTimeT(mode->GetTime());
410 if (seekTime < time(NULL__null) && currentShowMode != showNow && currentShowMode != showNext)
411 {
412 seekTime += HOURS2SECS(24)(24*60*60);
413 szTitle = cString::sprintf("%s - %s (%s)", tr("Overview")I18nTranslate("Overview", "vdr-" "epgsearch"), mode->GetDescription(), *WeekDayName(seekTime));
414 }
415 else
416 szTitle = cString::sprintf("%s - %s", tr("Overview")I18nTranslate("Overview", "vdr-" "epgsearch"), mode->GetDescription());
417 }
418 SetTitle(szTitle);
419
420 cMenuTemplate* currentTemplate = NULL__null;
421 if (currentShowMode == showNow)
422 currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnNow");
423 if (currentShowMode == showNext)
424 currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnNext");
425 if (currentShowMode > showNext)
426 currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnElse");
427
428 int maxChannel = EPGSearchConfig.maxChannelMenuNow;
429 if (currentChannel > maxChannel)
430 maxChannel = 0;
431
432 for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel))
433 {
434 if (!Channel->GroupSep())
435 {
436 if (maxChannel && Channel->Number() > maxChannel) break;
437 if (EPGSearchConfig.showRadioChannels == 0 && ISRADIO(Channel)((Channel)->Vpid()==0||(Channel)->Vpid()==1||(Channel)->
Vpid()==0x1fff)
)
438 continue;
439
440 const cSchedule *Schedule = schedules->GetSchedule(Channel);
441 const cEvent *Event = NULL__null;
442 if (Schedule)
443 {
444 if (shiftTime != 0)
445 Event = Schedule->GetEventAround(seekTime);
446 else
447 {
448 switch(currentShowMode)
449 {
450 default:
451 case showNow:
452 Event = Schedule->GetPresentEvent();
453 break;
454 case showNext:
455 Event = Schedule->GetFollowingEvent();
456 break;
457 case showUserMode1:
458 case showUserMode2:
459 case showUserMode3:
460 case showUserMode4:
461 Event = Schedule->GetEventAround(seekTime);
462 break;
463 }
464 }
465 }
466 if (!EPGSearchConfig.showEmptyChannels && !Event)
467 continue;
468
469 Add(new cMenuMyScheduleItem(Event, Channel, currentShowMode, currentTemplate), Channel->Number() == currentChannel);
470 if (Event) eventObjects.Add(Event);
471 }
472 else
473 {
474 if (EPGSearchConfig.showChannelGroups && strlen(Channel->Name()))
475 Add(new cMenuMyScheduleSepItem(NULL__null, Channel));
476 }
477 }
478}
479
480time_t cMenuWhatsOnSearch::GetTimeT(int iTime)
481{
482 struct tm tm_r;
483 time_t t = time(NULL__null);
484 tm* tmnow = localtime_r(&t, &tm_r);
485 tmnow->tm_hour = HOURS(iTime)((iTime)/100);
486 tmnow->tm_min = MINUTES(iTime)((iTime)%100);
487 return mktime(tmnow);
488}
489
490showMode cMenuWhatsOnSearch::GetNextMode()
491{
492 showMode nextShowMode = currentShowMode;
Value stored to 'nextShowMode' during its initialization is never read
493 cShowMode* Mode = GetShowMode(currentShowMode);
494 if (Mode)
495 {
496 cShowMode* ModeNext = showModes.Next(Mode);
497 if (ModeNext == NULL__null)
498 nextShowMode = showNow;
499 else
500 nextShowMode = ModeNext->GetMode();
501 }
502 else // no mode found? fall back to 'now'
503 nextShowMode = showNow;
504 return nextShowMode;
505}
506
507void cMenuWhatsOnSearch::CreateShowModes()
508{
509 showModes.Clear();
510
511 cShowMode* ModeNow = new cShowMode(showNow, trVDR("Button$Now")I18nTranslate("Button$Now"));
512 showModes.Add(ModeNow);
513 cShowMode* ModeNext = new cShowMode(showNext, trVDR("Button$Next")I18nTranslate("Button$Next"));
514 showModes.Add(ModeNext);
515
516 time_t now = time(NULL__null);
517 for(int i=showUserMode1; i<showModeMax; i++)
518 {
519 if (!EPGSearchConfig.ShowModes[i].GetUsage())
520 continue;
521
522 time_t SeekTime = GetTimeT(EPGSearchConfig.ShowModes[i].GetTime());
523 if (SeekTime < now)
524 SeekTime += HOURS2SECS(24)(24*60*60);
525 if (SeekTime - now > HOURS2SECS(SKIPHOURS)(20*60*60))
526 continue;
527 cShowMode* Mode = new cShowMode((showMode)i, EPGSearchConfig.ShowModes[i].GetDescription(),
528 1, EPGSearchConfig.ShowModes[i].GetTime(), SeekTime);
529 showModes.Add(Mode);
530 }
531 if (EPGSearchConfig.showFavoritesMenu)
532 {
533 cShowMode* ModeFav = new cShowMode(showFavorites, tr("Button$Favorites")I18nTranslate("Button$Favorites", "vdr-" "epgsearch"));
534 showModes.Add(ModeFav);
535 }
536 showModes.Sort();
537}
538
539cShowMode* cMenuWhatsOnSearch::GetShowMode(showMode mode)
540{
541 for (cShowMode *showMode = showModes.First(); showMode; showMode = showModes.Next(showMode))
542 if (mode == showMode->GetMode())
543 return showMode;
544 return NULL__null;
545}
546
547cChannel *cMenuWhatsOnSearch::ScheduleChannel(cChannel *force_channel)
548{
549 cChannel *ch = force_channel?force_channel:scheduleChannel;
550 scheduleChannel = NULL__null;
551 return ch;
552}
553
554
555eOSState cMenuWhatsOnSearch::Switch(void)
556{
557 cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
558 if (item && item->channel) {
559 if (cDevice::PrimaryDevice()->SwitchChannel(item->channel, true))
560 return osEnd;
561 }
562 INFO(trVDR("Can't switch channel!"))Skins.Message(mtInfo, I18nTranslate("Can't switch channel!"));
563 return osContinue;
564}
565
566eOSState cMenuWhatsOnSearch::Record(void)
567{
568 cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
569 if (item)
570 {
571 if (item->timerMatch == tmFull)
572 {
573 eTimerMatch tm = tmNone;
574 cTimer *timer = Timers.GetMatch(item->event, &tm);
575 if (timer)
576 {
577 if (EPGSearchConfig.useVDRTimerEditMenu)
578 return AddSubMenu(new cMenuEditTimer(timer));
579 else
580 return AddSubMenu(new cMenuMyEditTimer(timer, false, item->event, item->channel));
581 }
582 }
583
584 cTimer *timer = NULL__null;
585 if (item->event)
586 {
587 timer = new cTimer(item->event);
588 PrepareTimerFile(item->event, timer);
589 }
590 else
591 timer = new cTimer(false, false, item->channel);
592
593 cTimer *t = Timers.GetTimer(timer);
594 if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL__null)))
595 {
596 if (t)
597 {
598 delete timer;
599 timer = t;
600 }
601 timer->SetFlags(tfActive);
602 if (EPGSearchConfig.useVDRTimerEditMenu)
603 return AddSubMenu(new cMenuEditTimer(timer, !t));
604 else
605 return AddSubMenu(new cMenuMyEditTimer(timer, !t, item->event, item->channel));
606 }
607 else
608 {
609 string fullaux = "";
610 string aux = "";
611 if (item->event)
612 {
613 const cEvent* event = item->event;
614 int bstart = event->StartTime() - timer->StartTime();
615 int bstop = timer->StopTime() - event->EndTime();
616 int checkmode = DefTimerCheckModes.GetMode(timer->Channel());
617 aux = UpdateAuxValue(aux, "channel", NumToString(timer->Channel()->Number()) + " - " + CHANNELNAME(timer->Channel())(timer->Channel() ? timer->Channel()->ShortName(true
) : "")
);
618 aux = UpdateAuxValue(aux, "update", checkmode);
619 aux = UpdateAuxValue(aux, "eventid", event->EventID());
620 aux = UpdateAuxValue(aux, "bstart", bstart);
621 aux = UpdateAuxValue(aux, "bstop", bstop);
622 fullaux = UpdateAuxValue(fullaux, "epgsearch", aux);
623 }
624#ifdef USE_PINPLUGIN
625 aux = "";
626 aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no");
627 fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux);
628#endif
629 SetAux(timer, fullaux);
630 Timers.Add(timer);
631 gl_timerStatusMonitor->SetConflictCheckAdvised();
632 timer->Matches();
633 Timers.SetModified();
634 LogFile.iSysLog("timer %s added (active)", *timer->ToDescr());
635
636 if (HasSubMenu())
637 CloseSubMenu();
638 if (Update())
639 Display();
640 SetHelpKeys();
641 }
642 }
643 return osContinue;
644}
645
646bool cMenuWhatsOnSearch::Update(void)
647{
648 bool result = false;
649 for (cOsdItem *item = First(); item; item = Next(item)) {
650 if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update())
651 result = true;
652 }
653 return result;
654}
655
656eOSState cMenuWhatsOnSearch::Commands(eKeys Key)
657{
658 if (HasSubMenu() || Count() == 0)
659 return osContinue;
660
661 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
662 if (mi)
663 {
664 if (!mi->event)
665 {
666 if (Key == k3)
667 return Switch();
668 else if (Key == k2)
669 return Record();
670 else
671 return osContinue;
672 }
673 cMenuSearchCommands *menu;
674 eOSState state = AddSubMenu(menu = new cMenuSearchCommands(tr("EPG Commands")I18nTranslate("EPG Commands", "vdr-" "epgsearch"), mi->event, true));
675 if (Key != kNone)
676 state = menu->ProcessKey(Key);
677 return state;
678 }
679 return osContinue;
680}
681
682eOSState cMenuWhatsOnSearch::ExtendedSearch(void)
683{
684 return AddSubMenu(new cMenuEPGSearchExt());
685}
686
687void cMenuWhatsOnSearch::SetHelpKeys(bool Force)
688{
689 cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
690 int NewHelpKeys = 0;
691 if (item) {
692 if (item->Selectable() && item->timerMatch == tmFull)
693 NewHelpKeys = 2;
694 else
695 NewHelpKeys = 1;
696 }
697
698 bool hasTimer = (NewHelpKeys == 2);
699 if (NewHelpKeys != helpKeys || Force)
700 {
701 showMode nextShowMode = GetNextMode();
702 cShowMode* mode = GetShowMode(nextShowMode);
703 const char* szButtonGreen = NULL__null;
704 if (mode)
705 szButtonGreen = mode->GetDescription();
706 if (toggleKeys==0)
707 SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer")I18nTranslate("Button$Timer"):trVDR("Button$Record")I18nTranslate("Button$Record")):tr("Button$Commands")I18nTranslate("Button$Commands", "vdr-" "epgsearch")),
708 szButtonGreen,
709 trVDR("Button$Schedule")I18nTranslate("Button$Schedule"),
710 EPGSearchConfig.bluekeymode==0?(EPGSearchConfig.useOkForSwitch?trVDR("Button$Info")I18nTranslate("Button$Info"):trVDR("Button$Switch")I18nTranslate("Button$Switch")):tr("Button$Search")I18nTranslate("Button$Search", "vdr-" "epgsearch"));
711 else
712 SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer")I18nTranslate("Button$Timer"):trVDR("Button$Record")I18nTranslate("Button$Record")):tr("Button$Commands")I18nTranslate("Button$Commands", "vdr-" "epgsearch")),
713 (EPGSearchConfig.toggleGreenYellow==0?szButtonGreen:"<<"),
714 (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Schedule")I18nTranslate("Button$Schedule"):">>"),
715 EPGSearchConfig.bluekeymode==1?(EPGSearchConfig.useOkForSwitch?trVDR("Button$Info")I18nTranslate("Button$Info"):trVDR("Button$Switch")I18nTranslate("Button$Switch")):tr("Button$Search")I18nTranslate("Button$Search", "vdr-" "epgsearch"));
716 helpKeys = NewHelpKeys;
717 }
718}
719
720eOSState cMenuWhatsOnSearch::Shift(int iMinutes)
721{
722 shiftTime += iMinutes;
723 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
724 int TempChannel = currentChannel;
725 if (mi)
726 {
727 currentChannel = mi->channel->Number();
728 scheduleChannel = Channels.GetByNumber(currentChannel);
729 }
730 LoadSchedules();
731 Display();
732 currentChannel = TempChannel;
733 SetHelpKeys();
734 return osContinue;
735}
736
737eOSState cMenuWhatsOnSearch::ShowSummary()
738{
739 if (Count())
740 {
741 const cEvent *ei = ((cMenuMyScheduleItem *)Get(Current()))->event;
742 if (ei)
743 {
744 cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true);
745 if (channel)
746 return AddSubMenu(new cMenuEventSearch(ei, eventObjects, SurfModeChannel));
747 }
748 }
749 return osContinue;
750}
751
752void cMenuWhatsOnSearch::UpdateCurrent()
753{
754 // navigation in summary could have changed current item, so update it
755 cEventObj* cureventObj = eventObjects.GetCurrent();
756 if (cureventObj && cureventObj->Event())
757 for (cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)First(); item; item = (cMenuMyScheduleItem *)Next(item))
758 if (item->Selectable() && item->event == cureventObj->Event())
759 {
760 cureventObj->Select(false);
761 SetCurrent(item);
762 Display();
763 break;
764 }
765}
766
767eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key)
768{
769 exitToMainMenu = 0;
770 if (!HasSubMenu() && Key == kBack)
771 {
772 exitToMainMenu = 1;
773 return osBack;
774 }
775
776 bool HadSubMenu = HasSubMenu();
777 eOSState state = cOsdMenu::ProcessKey(Key);
778
779 if (!HasSubMenu() && HadSubMenu) // navigation in summary could have changed current item, so update it
780 UpdateCurrent();
781
782 if (state == osUnknown) {
783 switch (Key) {
784 case kFastRew:
785 if(!HasSubMenu())
786 return Shift(-EPGSearchConfig.timeShiftValue);
787 break;
788 case kFastFwd:
789 if(!HasSubMenu())
790 return Shift(EPGSearchConfig.timeShiftValue);
791 break;
792 case kRecord:
793 case kRed:
794 if(HasSubMenu()) {
795 UpdateCurrent();
796 state = Record();
797 break;
798 }
799 if (Count())
800 {
801 if (EPGSearchConfig.redkeymode==toggleKeys)
802 state = Record();
803 else
804 {
805 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
806 if (mi && mi->Selectable()) {
807 if (mi->event)
808 return AddSubMenu(new cMenuSearchCommands(tr("EPG Commands")I18nTranslate("EPG Commands", "vdr-" "epgsearch"),mi->event));
809 else
810 return osContinue;
811 }
812 }
813 }
814 break;
815
816 case k0:
817 if(!HasSubMenu())
818 {
819 toggleKeys = 1 - toggleKeys;
820 SetHelpKeys(true);
821 }
822 state = osContinue;
823 break;
824 case k1...k9: return Commands(Key);
825 case kYellow:
826 if(!HasSubMenu())
827 {
828 if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0))
829 {
830 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
831 if (mi && mi->Selectable() && mi->channel)
832 {
833 const cSchedule *Schedule = schedules->GetSchedule(mi->channel);
834 if (Schedule)
835 {
836 time_t now = time(NULL__null);
837 bool hasFutureEvents = false;
838 for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e))
839 if (e->StartTime() > now)
840 {
841 hasFutureEvents = true;
842 break;
843 }
844 if (!hasFutureEvents)
845 return osContinue;
846 }
847 else
848 return osContinue;
849 }
850 state = osBack;
851 // continue with kGreen
852 }
853 else
854 return Shift(EPGSearchConfig.timeShiftValue);
855 }
856 case kGreen:
857 if(!HasSubMenu())
858 {
859 if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0))
860 {
861 if (Key == kYellow)
862 currentShowMode = showNow;
863 else
864 currentShowMode = GetNextMode();
865 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
866 if (mi && mi->Selectable())
867 {
868 currentChannel = mi->channel->Number();
869 scheduleChannel = Channels.GetByNumber(currentChannel);
870 }
871 }
872 else
873 return Shift(-EPGSearchConfig.timeShiftValue);
874 }
875 break;
876 case kBlue:
877 if (HasSubMenu())
878 {
879 UpdateCurrent();
880 return Switch();
881 }
882 if (EPGSearchConfig.bluekeymode==toggleKeys)
883 return EPGSearchConfig.useOkForSwitch?ShowSummary():Switch();
884 else
885 return ExtendedSearch();
886 break;
887 case kOk:
888 {
889 cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current());
890 if (mi && mi->Selectable())
891 {
892 if (!mi->event) // no EPG, so simply switch to channel
893 return Switch();
894 else
895 return EPGSearchConfig.useOkForSwitch?Switch():ShowSummary();
896 }
897 }
898 break;
899 case kInfo:
900 return ShowSummary();
901 break;
902 default: break;
903 }
904 }
905 if (!HasSubMenu())
906 {
907 if ((HadSubMenu || gl_TimerProgged) && Update())
908 {
909 if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP
910 {
911 gl_TimerProgged = 0;
912 SetHelpKeys();
913 }
914 Display();
915 }
916 if (Key != kNone)
917 SetHelpKeys();
918 if (gl_InfoConflict)
919 {
920 gl_InfoConflict = 0;
921 if (Interface->Confirm(tr("Timer conflict! Show?")I18nTranslate("Timer conflict! Show?", "vdr-" "epgsearch")))
922 return AddSubMenu(new cMenuConflictCheck());
923 }
924 }
925
926 return state;
927}
928
929