f5d2d6e4d2a761eb90583a88508bc02b672ca5ba
[vuplus_xbmc] / xbmc / pvr / windows / GUIWindowPVRCommon.cpp
1 /*
2  *      Copyright (C) 2012-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "GUIWindowPVRCommon.h"
22
23 #include "Application.h"
24 #include "ApplicationMessenger.h"
25 #include "dialogs/GUIDialogKaiToast.h"
26 #include "dialogs/GUIDialogOK.h"
27 #include "dialogs/GUIDialogYesNo.h"
28 #include "filesystem/StackDirectory.h"
29 #include "guilib/GUIMessage.h"
30 #include "guilib/GUIWindowManager.h"
31 #include "guilib/Key.h"
32 #include "guilib/LocalizeStrings.h"
33 #include "pvr/PVRManager.h"
34 #include "pvr/channels/PVRChannelGroupsContainer.h"
35 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
36 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
37 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
38 #include "epg/Epg.h"
39 #include "pvr/timers/PVRTimers.h"
40 #include "pvr/addons/PVRClients.h"
41 #include "pvr/windows/GUIWindowPVR.h"
42 #include "pvr/windows/GUIWindowPVRSearch.h"
43 #include "pvr/recordings/PVRRecordings.h"
44 #include "settings/MediaSettings.h"
45 #include "settings/Settings.h"
46 #include "utils/log.h"
47 #include "utils/URIUtils.h"
48 #include "GUIUserMessages.h"
49 #include "cores/IPlayer.h"
50
51 using namespace std;
52 using namespace PVR;
53 using namespace EPG;
54
55 CGUIWindowPVRCommon::CGUIWindowPVRCommon(CGUIWindowPVR *parent, PVRWindow window,
56     unsigned int iControlButton, unsigned int iControlList)
57 {
58   m_parent          = parent;
59   m_window          = window;
60   m_iControlButton  = iControlButton;
61   m_iControlList    = iControlList;
62   m_bUpdateRequired = false;
63   m_iSelected       = 0;
64   m_iSortOrder      = SortOrderAscending;
65   m_iSortMethod     = SortByDate;
66   m_iSortAttributes = SortAttributeNone;
67   if( m_parent->GetViewState() )
68   {
69     SortDescription sorting = m_parent->GetViewState()->GetSortMethod();
70     m_iSortOrder      = sorting.sortOrder;
71     m_iSortMethod     = sorting.sortBy;
72     m_iSortAttributes = sorting.sortAttributes;
73   }
74 }
75
76 bool CGUIWindowPVRCommon::operator ==(const CGUIWindowPVRCommon &right) const
77 {
78   return (this == &right || m_window == right.m_window);
79 }
80
81 bool CGUIWindowPVRCommon::operator !=(const CGUIWindowPVRCommon &right) const
82 {
83   return !(*this == right);
84 }
85
86 const char *CGUIWindowPVRCommon::GetName(void) const
87 {
88   switch(m_window)
89   {
90   case PVR_WINDOW_EPG:
91     return "epg";
92   case PVR_WINDOW_CHANNELS_RADIO:
93     return "radio";
94   case PVR_WINDOW_CHANNELS_TV:
95     return "tv";
96   case PVR_WINDOW_RECORDINGS:
97     return "recordings";
98   case PVR_WINDOW_SEARCH:
99     return "search";
100   case PVR_WINDOW_TIMERS:
101     return "timers";
102   default:
103     return "unknown";
104   }
105 }
106
107 bool CGUIWindowPVRCommon::IsFocused(void) const
108 {
109   return !g_application.IsPlayingFullScreenVideo() &&
110       g_windowManager.GetFocusedWindow() == WINDOW_PVR &&
111       IsActive();
112 }
113
114 bool CGUIWindowPVRCommon::IsVisible(void) const
115 {
116   return !g_application.IsPlayingFullScreenVideo() &&
117       g_windowManager.GetActiveWindow() == WINDOW_PVR &&
118       IsActive();
119 }
120
121 bool CGUIWindowPVRCommon::IsActive(void) const
122 {
123   CGUIWindowPVRCommon *window = m_parent->GetActiveView();
124   return (window && *window == *this);
125 }
126
127 bool CGUIWindowPVRCommon::IsSavedView(void) const
128 {
129   CGUIWindowPVRCommon *window = m_parent->GetSavedView();
130   return (window && *window == *this);
131 }
132
133 bool CGUIWindowPVRCommon::IsSelectedButton(CGUIMessage &message) const
134 {
135   return (message.GetSenderId() == (int) m_iControlButton);
136 }
137
138 bool CGUIWindowPVRCommon::IsSelectedControl(CGUIMessage &message) const
139 {
140   return (message.GetControlId() == (int) m_iControlButton);
141 }
142
143 bool CGUIWindowPVRCommon::IsSelectedList(CGUIMessage &message) const
144 {
145   return (message.GetSenderId() == (int) m_iControlList);
146 }
147
148 void CGUIWindowPVRCommon::SetInvalid()
149 {
150   for (int iItemPtr = 0; iItemPtr < m_parent->m_vecItems->Size(); iItemPtr++)
151     m_parent->m_vecItems->Get(iItemPtr)->SetInvalid();
152   m_parent->SetInvalid();
153 }
154
155 void CGUIWindowPVRCommon::OnInitWindow()
156 {
157   m_parent->m_viewControl.SetCurrentView(m_iControlList);
158 }
159
160 bool CGUIWindowPVRCommon::SelectPlayingFile(void)
161 {
162   bool bReturn(false);
163
164   if (g_PVRManager.IsPlaying())
165   {
166     m_parent->m_viewControl.SetSelectedItem(g_application.CurrentFile());
167     bReturn = true;
168   }
169
170   return bReturn;
171 }
172
173 bool CGUIWindowPVRCommon::OnMessageFocus(CGUIMessage &message)
174 {
175   bool bReturn = false;
176
177   if (message.GetMessage() == GUI_MSG_FOCUSED &&
178       (IsSelectedControl(message) || IsSavedView()))
179   {
180     CLog::Log(LOGDEBUG, "CGUIWindowPVRCommon - %s - focus set to window '%s'", __FUNCTION__, GetName());
181     bool bIsActive = IsActive();
182     m_parent->SetActiveView(this);
183
184     if (!bIsActive || m_bUpdateRequired)
185       UpdateData();
186
187     bReturn = true;
188   }
189
190   return bReturn;
191 }
192
193 void CGUIWindowPVRCommon::OnWindowUnload(void)
194 {
195   m_iSelected = m_parent->m_viewControl.GetSelectedItem();
196   m_history = m_parent->m_history;
197 }
198
199 bool CGUIWindowPVRCommon::OnAction(const CAction &action)
200 {
201   bool bReturn = false;
202
203   if (action.GetID() == ACTION_NAV_BACK ||
204       action.GetID() == ACTION_PREVIOUS_MENU)
205   {
206     g_windowManager.PreviousWindow();
207     bReturn = true;
208   }
209
210   return bReturn;
211 }
212
213 bool CGUIWindowPVRCommon::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
214 {
215   if (itemNumber < 0 || itemNumber >= (int) m_parent->m_vecItems->Size())
216     return false;
217   CFileItemPtr pItem = m_parent->m_vecItems->Get(itemNumber);
218
219   return (OnContextButtonSortAsc(pItem.get(), button) ||
220       OnContextButtonSortBy(pItem.get(), button) ||
221       OnContextButtonSortByChannel(pItem.get(), button) ||
222       OnContextButtonSortByName(pItem.get(), button) ||
223       OnContextButtonSortByDate(pItem.get(), button) ||
224       OnContextButtonFind(pItem.get(), button) ||
225       OnContextButtonMenuHooks(pItem.get(), button));
226 }
227
228 bool CGUIWindowPVRCommon::OnContextButtonSortByDate(CFileItem *item, CONTEXT_BUTTON button)
229 {
230   bool bReturn = false;
231
232   if (button == CONTEXT_BUTTON_SORTBY_DATE)
233   {
234     bReturn = true;
235
236     if (m_iSortMethod != SortByDate)
237     {
238       m_iSortMethod = SortByDate;
239       m_iSortOrder  = SortOrderAscending;
240       CGUIMessage message(GUI_MSG_CHANGE_SORT_METHOD, m_parent->GetID(), 0, m_iSortMethod, 0); 
241       m_parent->OnMessage(message);
242     }
243     else
244     {
245       m_iSortOrder = m_iSortOrder == SortOrderAscending ? SortOrderDescending : SortOrderAscending;
246     }
247     CGUIMessage message(GUI_MSG_CHANGE_SORT_DIRECTION, m_parent->GetID(), 0, m_iSortOrder, 0); 
248     m_parent->OnMessage(message);
249     UpdateData();
250   }
251
252   return bReturn;
253 }
254
255 bool CGUIWindowPVRCommon::OnContextButtonSortByName(CFileItem *item, CONTEXT_BUTTON button)
256 {
257   bool bReturn = false;
258
259   if (button == CONTEXT_BUTTON_SORTBY_NAME)
260   {
261     bReturn = true;
262
263     if (m_iSortMethod != SortByLabel)
264     {
265       m_iSortMethod = SortByLabel;
266       m_iSortOrder  = SortOrderAscending;
267       CGUIMessage message(GUI_MSG_CHANGE_SORT_METHOD, m_parent->GetID(), 0, m_iSortMethod, 0); 
268       m_parent->OnMessage(message);
269     }
270     else
271     {
272       m_iSortOrder = m_iSortOrder == SortOrderAscending ? SortOrderDescending : SortOrderAscending;
273     }
274     CGUIMessage message(GUI_MSG_CHANGE_SORT_DIRECTION, m_parent->GetID(), 0, m_iSortOrder, 0); 
275     m_parent->OnMessage(message);
276     UpdateData();
277   }
278
279   return bReturn;
280 }
281
282 bool CGUIWindowPVRCommon::OnContextButtonSortByChannel(CFileItem *item, CONTEXT_BUTTON button)
283 {
284   bool bReturn = false;
285
286   if (button == CONTEXT_BUTTON_SORTBY_CHANNEL)
287   {
288     bReturn = true;
289
290     if (m_iSortMethod != SortByChannel)
291     {
292       m_iSortMethod = SortByChannel;
293       m_iSortOrder  = SortOrderAscending;
294     }
295     else
296     {
297       m_iSortOrder = m_iSortOrder == SortOrderAscending ? SortOrderDescending : SortOrderAscending;
298     }
299
300     UpdateData();
301   }
302
303   return bReturn;
304 }
305
306 bool CGUIWindowPVRCommon::OnContextButtonSortAsc(CFileItem *item, CONTEXT_BUTTON button)
307 {
308   bool bReturn = false;
309
310   if (button == CONTEXT_BUTTON_SORTASC)
311   {
312     bReturn = true;
313
314     if (m_parent->m_guiState.get())
315       m_parent->m_guiState->SetNextSortOrder();
316     m_parent->UpdateFileList();
317   }
318
319   return bReturn;
320 }
321
322 bool CGUIWindowPVRCommon::OnContextButtonSortBy(CFileItem *item, CONTEXT_BUTTON button)
323 {
324   bool bReturn = false;
325
326   if (button == CONTEXT_BUTTON_SORTBY)
327   {
328     bReturn = true;
329
330     if (m_parent->m_guiState.get())
331       m_parent->m_guiState->SetNextSortMethod();
332
333     m_parent->UpdateFileList();
334   }
335
336   return bReturn;
337 }
338
339 bool CGUIWindowPVRCommon::OnContextButtonMenuHooks(CFileItem *item, CONTEXT_BUTTON button)
340 {
341   bool bReturn = false;
342
343   if (button == CONTEXT_BUTTON_MENU_HOOKS)
344   {
345     bReturn = true;
346
347     if (item->IsEPG() && item->GetEPGInfoTag()->HasPVRChannel())
348       g_PVRClients->ProcessMenuHooks(item->GetEPGInfoTag()->ChannelTag()->ClientID(), PVR_MENUHOOK_EPG, item);
349     else if (item->IsPVRChannel())
350       g_PVRClients->ProcessMenuHooks(item->GetPVRChannelInfoTag()->ClientID(), PVR_MENUHOOK_CHANNEL, item);
351     else if (item->IsPVRRecording())
352       g_PVRClients->ProcessMenuHooks(item->GetPVRRecordingInfoTag()->m_iClientId, PVR_MENUHOOK_RECORDING, item);
353     else if (item->IsPVRTimer())
354       g_PVRClients->ProcessMenuHooks(item->GetPVRTimerInfoTag()->m_iClientId, PVR_MENUHOOK_TIMER, item);
355   }
356
357   return bReturn;
358 }
359
360 bool CGUIWindowPVRCommon::ActionDeleteTimer(CFileItem *item)
361 {
362   /* check if the timer tag is valid */
363   CPVRTimerInfoTag *timerTag = item->GetPVRTimerInfoTag();
364   if (!timerTag || timerTag->m_iClientIndex < 0)
365     return false;
366
367   /* show a confirmation dialog */
368   CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
369   if (!pDialog)
370     return false;
371   pDialog->SetHeading(122);
372   pDialog->SetLine(0, 19040);
373   pDialog->SetLine(1, "");
374   pDialog->SetLine(2, timerTag->m_strTitle);
375   pDialog->DoModal();
376
377   /* prompt for the user's confirmation */
378   if (!pDialog->IsConfirmed())
379     return false;
380
381   /* delete the timer */
382   return g_PVRTimers->DeleteTimer(*item);
383 }
384
385 bool CGUIWindowPVRCommon::ShowNewTimerDialog(void)
386 {
387   bool bReturn(false);
388
389   CPVRTimerInfoTag *newTimer = new CPVRTimerInfoTag;
390   CFileItem *newItem = new CFileItem(*newTimer);
391   if (ShowTimerSettings(newItem))
392   {
393     /* Add timer to backend */
394     bReturn = g_PVRTimers->AddTimer(*newItem->GetPVRTimerInfoTag());
395   }
396
397   delete newItem;
398   delete newTimer;
399
400   return bReturn;
401 }
402
403 bool CGUIWindowPVRCommon::ActionShowTimer(CFileItem *item)
404 {
405   bool bReturn = false;
406
407   /* Check if "Add timer..." entry is pressed by OK, if yes
408      create a new timer and open settings dialog, otherwise
409      open settings for selected timer entry */
410   if (item->GetPath() == "pvr://timers/add.timer")
411   {
412     bReturn = ShowNewTimerDialog();
413   }
414   else
415   {
416     if (ShowTimerSettings(item))
417     {
418       /* Update timer on pvr backend */
419       bReturn = g_PVRTimers->UpdateTimer(*item);
420     }
421   }
422
423   return bReturn;
424 }
425
426 bool CGUIWindowPVRCommon::ActionRecord(CFileItem *item)
427 {
428   bool bReturn = false;
429
430   CEpgInfoTag *epgTag = item->GetEPGInfoTag();
431   if (!epgTag)
432     return bReturn;
433
434   CPVRChannelPtr channel = epgTag->ChannelTag();
435   if (!channel || !g_PVRManager.CheckParentalLock(*channel))
436     return bReturn;
437
438   if (epgTag->Timer() == NULL)
439   {
440     /* create a confirmation dialog */
441     CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*) g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
442     if (!pDialog)
443       return bReturn;
444
445     pDialog->SetHeading(264);
446     pDialog->SetLine(0, "");
447     pDialog->SetLine(1, epgTag->Title());
448     pDialog->SetLine(2, "");
449     pDialog->DoModal();
450
451     /* prompt for the user's confirmation */
452     if (!pDialog->IsConfirmed())
453       return bReturn;
454
455     CPVRTimerInfoTag *newTimer = CPVRTimerInfoTag::CreateFromEpg(*epgTag);
456     if (newTimer)
457     {
458       bReturn = g_PVRTimers->AddTimer(*newTimer);
459       delete newTimer;
460     }
461     else
462     {
463       bReturn = false;
464     }
465   }
466   else
467   {
468     CGUIDialogOK::ShowAndGetInput(19033,19034,0,0);
469     bReturn = true;
470   }
471
472   return bReturn;
473 }
474
475
476 bool CGUIWindowPVRCommon::ActionDeleteRecording(CFileItem *item)
477 {
478   bool bReturn = false;
479
480   /* check if the recording tag is valid */
481   CPVRRecording *recTag = (CPVRRecording *) item->GetPVRRecordingInfoTag();
482   if (!recTag || recTag->m_strRecordingId.IsEmpty())
483     return bReturn;
484
485   /* show a confirmation dialog */
486   CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
487   if (!pDialog)
488     return bReturn;
489   pDialog->SetHeading(122);
490   pDialog->SetLine(0, 19043);
491   pDialog->SetLine(1, "");
492   pDialog->SetLine(2, recTag->m_strTitle);
493   pDialog->DoModal();
494
495   /* prompt for the user's confirmation */
496   if (!pDialog->IsConfirmed())
497     return bReturn;
498
499   /* delete the recording */
500   if (g_PVRRecordings->DeleteRecording(*item))
501   {
502     g_PVRManager.TriggerRecordingsUpdate();
503     bReturn = true;
504   }
505
506   return bReturn;
507 }
508
509 bool CGUIWindowPVRCommon::ActionPlayChannel(CFileItem *item)
510 {
511   bool bReturn = false;
512
513   if (item->GetPath() == "pvr://channels/.add.channel")
514   {
515     /* show "add channel" dialog */
516     CGUIDialogOK::ShowAndGetInput(19033,0,19038,0);
517     bReturn = true;
518   }
519   else
520   {
521     /* open channel */
522     bReturn = PlayFile(item, CSettings::Get().GetBool("pvrplayback.playminimized"));
523   }
524
525   return bReturn;
526 }
527
528 bool CGUIWindowPVRCommon::ActionPlayEpg(CFileItem *item)
529 {
530   CEpgInfoTag *epgTag = item->GetEPGInfoTag();
531   if (!epgTag)
532     return false;
533
534   CPVRChannelPtr channel = epgTag->ChannelTag();
535   if (!channel || channel->ChannelNumber() > 0 ||
536       !g_PVRManager.CheckParentalLock(*channel))
537     return false;
538
539   PlayBackRet ret = g_application.PlayFile(CFileItem(*channel));
540
541   if (ret == PLAYBACK_FAIL)
542   {
543     CStdString msg;
544     msg.Format(g_localizeStrings.Get(19035).c_str(), channel->ChannelName().c_str()); // CHANNELNAME could not be played. Check the log for details.
545     CGUIDialogOK::ShowAndGetInput(19033, 0, msg, 0);
546   }
547
548   return ret == PLAYBACK_OK;
549 }
550
551 bool CGUIWindowPVRCommon::ActionDeleteChannel(CFileItem *item)
552 {
553   CPVRChannel *channel = item->GetPVRChannelInfoTag();
554
555   /* check if the channel tag is valid */
556   if (!channel || channel->ChannelNumber() <= 0)
557     return false;
558
559   /* show a confirmation dialog */
560   CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*) g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
561   if (!pDialog)
562     return false;
563   pDialog->SetHeading(19039);
564   pDialog->SetLine(0, "");
565   pDialog->SetLine(1, channel->ChannelName());
566   pDialog->SetLine(2, "");
567   pDialog->DoModal();
568
569   /* prompt for the user's confirmation */
570   if (!pDialog->IsConfirmed())
571     return false;
572
573   g_PVRChannelGroups->GetGroupAll(channel->IsRadio())->RemoveFromGroup(*channel);
574   UpdateData();
575
576   return true;
577 }
578
579 bool CGUIWindowPVRCommon::UpdateEpgForChannel(CFileItem *item)
580 {
581   CPVRChannel *channel = item->GetPVRChannelInfoTag();
582   CEpg *epg = channel->GetEPG();
583   if (!epg)
584     return false;
585
586   epg->ForceUpdate();
587   return true;
588 }
589
590 bool CGUIWindowPVRCommon::ShowTimerSettings(CFileItem *item)
591 {
592   /* Check item is TV timer information tag */
593   if (!item->IsPVRTimer())
594   {
595     CLog::Log(LOGERROR, "CGUIWindowPVRTimers: Can't open timer settings dialog, no timer info tag!");
596     return false;
597   }
598
599   /* Load timer settings dialog */
600   CGUIDialogPVRTimerSettings* pDlgInfo = (CGUIDialogPVRTimerSettings*)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_TIMER_SETTING);
601
602   if (!pDlgInfo)
603     return false;
604
605   /* inform dialog about the file item */
606   pDlgInfo->SetTimer(item);
607
608   /* Open dialog window */
609   pDlgInfo->DoModal();
610
611   /* Get modify flag from window and return it to caller */
612   return pDlgInfo->GetOK();
613 }
614
615
616 bool CGUIWindowPVRCommon::PlayRecording(CFileItem *item, bool bPlayMinimized /* = false */)
617 {
618   if (!item->HasPVRRecordingInfoTag())
619     return false;
620
621   CStdString stream = item->GetPVRRecordingInfoTag()->m_strStreamURL;
622   if (stream == "")
623   {
624     CApplicationMessenger::Get().PlayFile(*item, false);
625     return true;
626   }
627
628   /* Isolate the folder from the filename */
629   size_t found = stream.find_last_of("/");
630   if (found == CStdString::npos)
631     found = stream.find_last_of("\\");
632
633   if (found != CStdString::npos)
634   {
635     /* Check here for asterisk at the begin of the filename */
636     if (stream[found+1] == '*')
637     {
638       /* Create a "stack://" url with all files matching the extension */
639       CStdString ext = URIUtils::GetExtension(stream);
640       CStdString dir = stream.substr(0, found).c_str();
641
642       CFileItemList items;
643       CDirectory::GetDirectory(dir, items);
644       items.Sort(SortByFile, SortOrderAscending);
645
646       vector<int> stack;
647       for (int i = 0; i < items.Size(); ++i)
648       {
649         if (URIUtils::HasExtension(items[i]->GetPath(), ext))
650           stack.push_back(i);
651       }
652
653       if (stack.size() > 0)
654       {
655         /* If we have a stack change the path of the item to it */
656         CStackDirectory dir;
657         CStdString stackPath = dir.ConstructStackPath(items, stack);
658         item->SetPath(stackPath);
659       }
660     }
661     else
662     {
663       /* If no asterisk is present play only the given stream URL */
664       item->SetPath(stream);
665     }
666   }
667   else
668   {
669     CLog::Log(LOGERROR, "PVRManager - %s - can't open recording: no valid filename", __FUNCTION__);
670     CGUIDialogOK::ShowAndGetInput(19033,0,19036,0);
671     return false;
672   }
673
674   CApplicationMessenger::Get().PlayFile(*item, false);
675
676   return true;
677 }
678
679 bool CGUIWindowPVRCommon::PlayFile(CFileItem *item, bool bPlayMinimized /* = false */)
680 {
681   if (item->m_bIsFolder)
682   {
683     return false;
684   }
685
686   if (item->GetPath() == g_application.CurrentFile())
687   {
688     CGUIMessage msg(GUI_MSG_FULLSCREEN, 0, m_parent->GetID());
689     g_windowManager.SendMessage(msg);
690     return true;
691   }
692
693   CMediaSettings::Get().SetVideoStartWindowed(bPlayMinimized);
694
695   if (item->HasPVRRecordingInfoTag())
696   {
697     return PlayRecording(item, bPlayMinimized);
698   }
699   else
700   {
701     bool bSwitchSuccessful(false);
702
703     CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL;
704
705     if (channel && g_PVRManager.CheckParentalLock(*channel))
706     {
707       /* try a fast switch */
708       if (channel && (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) &&
709          (channel->IsRadio() == g_PVRManager.IsPlayingRadio()))
710       {
711         if (channel->StreamURL().IsEmpty())
712           bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(*channel);
713       }
714
715       if (!bSwitchSuccessful)
716       {
717         CApplicationMessenger::Get().PlayFile(*item, false);
718         return true;
719       }
720     }
721
722     if (!bSwitchSuccessful)
723     {
724       CStdString msg;
725       CStdString channelName = g_localizeStrings.Get(19029); // Channel
726       if (channel)
727         channelName = channel->ChannelName();
728       msg.Format(g_localizeStrings.Get(19035).c_str(), channelName.c_str()); // CHANNELNAME could not be played. Check the log for details.
729
730       CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error,
731               g_localizeStrings.Get(19166), // PVR information
732               msg);
733       return false;
734     }
735   }
736
737   return true;
738 }
739
740 bool CGUIWindowPVRCommon::StartRecordFile(CFileItem *item)
741 {
742   if (!item->HasEPGInfoTag())
743     return false;
744
745   CEpgInfoTag *tag = item->GetEPGInfoTag();
746   CPVRChannelPtr channel;
747   if (tag)
748     channel = tag->ChannelTag();
749
750   if (!channel || !g_PVRManager.CheckParentalLock(*channel))
751     return false;
752
753   CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(item);
754   if (timer && timer->HasPVRTimerInfoTag())
755   {
756     CGUIDialogOK::ShowAndGetInput(19033,19034,0,0);
757     return false;
758   }
759
760   CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
761   if (!pDialog)
762     return false;
763   pDialog->SetHeading(264);
764   pDialog->SetLine(0, tag->PVRChannelName());
765   pDialog->SetLine(1, "");
766   pDialog->SetLine(2, tag->Title());
767   pDialog->DoModal();
768
769   if (!pDialog->IsConfirmed())
770     return false;
771
772   CPVRTimerInfoTag *newTimer = CPVRTimerInfoTag::CreateFromEpg(*tag);
773   bool bReturn(false);
774   if (newTimer)
775   {
776     bReturn = g_PVRTimers->AddTimer(*newTimer);
777     delete newTimer;
778   }
779   return bReturn;
780 }
781
782 bool CGUIWindowPVRCommon::StopRecordFile(CFileItem *item)
783 {
784   if (!item->HasEPGInfoTag())
785     return false;
786
787   CEpgInfoTag *tag = item->GetEPGInfoTag();
788   if (!tag || !tag->HasPVRChannel())
789     return false;
790
791   CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(item);
792   if (!timer || !timer->HasPVRTimerInfoTag() || timer->GetPVRTimerInfoTag()->m_bIsRepeating)
793     return false;
794
795   return g_PVRTimers->DeleteTimer(*timer);
796 }
797
798 void CGUIWindowPVRCommon::ShowEPGInfo(CFileItem *item)
799 {
800   CFileItem *tag = NULL;
801   bool bHasChannel(false);
802   CPVRChannel channel;
803   if (item->IsEPG())
804   {
805     tag = new CFileItem(*item);
806     if (item->GetEPGInfoTag()->HasPVRChannel())
807     {
808       channel = *item->GetEPGInfoTag()->ChannelTag();
809       bHasChannel = true;
810     }
811   }
812   else if (item->IsPVRChannel())
813   {
814     CEpgInfoTag epgnow;
815     channel = *item->GetPVRChannelInfoTag();
816     bHasChannel = true;
817     if (!item->GetPVRChannelInfoTag()->GetEPGNow(epgnow))
818     {
819       CGUIDialogOK::ShowAndGetInput(19033,0,19055,0);
820       return;
821     }
822     tag = new CFileItem(epgnow);
823   }
824
825   if (tag)
826   {
827     if (!bHasChannel || g_PVRManager.CheckParentalLock(channel))
828     {
829       CGUIDialogPVRGuideInfo* pDlgInfo = (CGUIDialogPVRGuideInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_GUIDE_INFO);
830       if (pDlgInfo)
831       {
832         pDlgInfo->SetProgInfo(tag);
833         pDlgInfo->DoModal();
834       }
835     }
836     delete tag;
837   }
838 }
839
840 void CGUIWindowPVRCommon::ShowRecordingInfo(CFileItem *item)
841 {
842   if (!item->IsPVRRecording())
843     return;
844
845   CGUIDialogPVRRecordingInfo* pDlgInfo = (CGUIDialogPVRRecordingInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_RECORDING_INFO);
846   if (!pDlgInfo)
847     return;
848
849   pDlgInfo->SetRecording(item);
850   pDlgInfo->DoModal();
851 }
852
853 bool CGUIWindowPVRCommon::OnContextButtonFind(CFileItem *item, CONTEXT_BUTTON button)
854 {
855   bool bReturn = false;
856
857   if (button == CONTEXT_BUTTON_FIND)
858   {
859     bReturn = true;
860     if (m_parent->m_windowSearch)
861     {
862       CEpgInfoTag tag;
863       m_parent->m_windowSearch->m_searchfilter.Reset();
864       if (item->IsEPG())
865         m_parent->m_windowSearch->m_searchfilter.m_strSearchTerm = "\"" + item->GetEPGInfoTag()->Title() + "\"";
866       else if (item->IsPVRChannel() && item->GetPVRChannelInfoTag()->GetEPGNow(tag))
867         m_parent->m_windowSearch->m_searchfilter.m_strSearchTerm = "\"" + tag.Title() + "\"";
868       else if (item->IsPVRRecording())
869         m_parent->m_windowSearch->m_searchfilter.m_strSearchTerm = "\"" + item->GetPVRRecordingInfoTag()->m_strTitle + "\"";
870       else if (item->IsPVRTimer())
871         m_parent->m_windowSearch->m_searchfilter.m_strSearchTerm = "\"" + item->GetPVRTimerInfoTag()->m_strTitle + "\"";
872
873       m_parent->m_windowSearch->m_bSearchConfirmed = true;
874       m_parent->SetLabel(m_iControlButton, 0);
875       m_parent->SetActiveView(m_parent->m_windowSearch);
876       m_parent->m_windowSearch->UpdateData();
877       m_parent->SetLabel(m_iControlList, 0);
878       m_parent->m_viewControl.SetFocused();
879     }
880   }
881
882   return bReturn;
883 }
884
885 void CGUIWindowPVRCommon::ShowBusyItem(void)
886 {
887   // FIXME: display a temporary entry so that the list can keep its focus
888   // busy_items has to be static, because m_viewControl holds the pointer to it
889   static CFileItemList busy_items;
890   if (busy_items.IsEmpty())
891   {
892     CFileItemPtr pItem(new CFileItem(g_localizeStrings.Get(1040)));
893     busy_items.AddFront(pItem, 0);
894   }
895   m_parent->m_viewControl.SetItems(busy_items);
896 }