2 * Copyright (C) 2012-2013 Team XBMC
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)
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.
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/>.
21 #include "GUIWindowPVRGuide.h"
23 #include "Application.h"
24 #include "dialogs/GUIDialogOK.h"
25 #include "guilib/GUIWindowManager.h"
26 #include "pvr/PVRManager.h"
27 #include "pvr/channels/PVRChannelGroupsContainer.h"
28 #include "epg/EpgContainer.h"
29 #include "pvr/windows/GUIWindowPVR.h"
30 #include "settings/AdvancedSettings.h"
31 #include "settings/GUISettings.h"
32 #include "settings/Settings.h"
33 #include "threads/SingleLock.h"
34 #include "utils/log.h"
35 #include "pvr/addons/PVRClients.h"
36 #include "pvr/timers/PVRTimers.h"
41 CGUIWindowPVRGuide::CGUIWindowPVRGuide(CGUIWindowPVR *parent) :
42 CGUIWindowPVRCommon(parent, PVR_WINDOW_EPG, CONTROL_BTNGUIDE, CONTROL_LIST_GUIDE_NOW_NEXT),
44 m_iGuideView(g_guiSettings.GetInt("epg.defaultguideview"))
46 m_cachedTimeline = new CFileItemList;
47 m_cachedChannelGroup = CPVRChannelGroupPtr(new CPVRChannelGroup);
50 CGUIWindowPVRGuide::~CGUIWindowPVRGuide(void)
52 delete m_cachedTimeline;
55 void CGUIWindowPVRGuide::UnregisterObservers(void)
57 g_EpgContainer.UnregisterObserver(this);
60 void CGUIWindowPVRGuide::ResetObservers(void)
62 g_EpgContainer.RegisterObserver(this);
65 void CGUIWindowPVRGuide::Notify(const Observable &obs, const ObservableMessage msg)
67 if (msg == ObservableMessageEpg || msg == ObservableMessageEpgContainer)
69 m_bUpdateRequired = true;
71 /* update the current window if the EPG timeline view is visible */
72 if (IsFocused() && m_iGuideView == GUIDE_VIEW_TIMELINE)
75 else if (msg == ObservableMessageEpgActiveItem)
77 if (IsVisible() && m_iGuideView != GUIDE_VIEW_TIMELINE)
80 m_bUpdateRequired = true;
84 void CGUIWindowPVRGuide::GetContextButtons(int itemNumber, CContextButtons &buttons) const
86 if (itemNumber < 0 || itemNumber >= m_parent->m_vecItems->Size())
88 CFileItemPtr pItem = m_parent->m_vecItems->Get(itemNumber);
90 CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(pItem.get());
91 if (timer && timer->HasPVRTimerInfoTag())
93 if (timer->GetPVRTimerInfoTag()->IsRecording())
94 buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19059); /* stop recording */
96 buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19060); /* delete timer */
98 else if (pItem->GetEPGInfoTag()->EndAsLocalTime() > CDateTime::GetCurrentDateTime())
100 if (pItem->GetEPGInfoTag()->StartAsLocalTime() < CDateTime::GetCurrentDateTime())
101 buttons.Add(CONTEXT_BUTTON_START_RECORD, 264); /* record */
103 buttons.Add(CONTEXT_BUTTON_START_RECORD, 19061); /* add timer */
106 buttons.Add(CONTEXT_BUTTON_INFO, 19047); /* epg info */
107 buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 19000); /* switch channel */
108 buttons.Add(CONTEXT_BUTTON_FIND, 19003); /* find similar program */
109 if (m_iGuideView == GUIDE_VIEW_TIMELINE)
111 buttons.Add(CONTEXT_BUTTON_BEGIN, 19063); /* go to begin */
112 buttons.Add(CONTEXT_BUTTON_END, 19064); /* go to end */
114 if (pItem->GetEPGInfoTag()->HasPVRChannel() &&
115 g_PVRClients->HasMenuHooks(pItem->GetEPGInfoTag()->ChannelTag()->ClientID(), PVR_MENUHOOK_EPG))
116 buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195); /* PVR client specific action */
120 bool CGUIWindowPVRGuide::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
122 if (itemNumber < 0 || itemNumber >= (int) m_parent->m_vecItems->Size())
124 CFileItemPtr pItem = m_parent->m_vecItems->Get(itemNumber);
126 return OnContextButtonPlay(pItem.get(), button) ||
127 OnContextButtonInfo(pItem.get(), button) ||
128 OnContextButtonStartRecord(pItem.get(), button) ||
129 OnContextButtonStopRecord(pItem.get(), button) ||
130 OnContextButtonBegin(pItem.get(), button) ||
131 OnContextButtonEnd(pItem.get(), button) ||
132 CGUIWindowPVRCommon::OnContextButton(itemNumber, button);
135 void CGUIWindowPVRGuide::UpdateViewChannel(bool bUpdateSelectedFile)
137 CPVRChannelPtr CurrentChannel;
138 bool bGotCurrentChannel = g_PVRManager.GetCurrentChannel(CurrentChannel);
140 m_parent->m_guideGrid = NULL;
141 m_parent->m_viewControl.SetCurrentView(CONTROL_LIST_GUIDE_CHANNEL);
143 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19029));
144 if (bGotCurrentChannel && CurrentChannel.get())
145 m_parent->SetLabel(CONTROL_LABELGROUP, CurrentChannel->ChannelName().c_str());
147 if ((!bGotCurrentChannel || g_PVRManager.GetCurrentEpg(*m_parent->m_vecItems) == 0) && CurrentChannel.get())
150 item.reset(new CFileItem("pvr://guide/" + CurrentChannel->ChannelName() + "/empty.epg", false));
151 item->SetLabel(g_localizeStrings.Get(19028));
152 item->SetLabelPreformated(true);
153 m_parent->m_vecItems->Add(item);
155 m_parent->m_viewControl.SetItems(*m_parent->m_vecItems);
158 void CGUIWindowPVRGuide::UpdateViewNow(bool bUpdateSelectedFile)
160 CPVRChannelPtr CurrentChannel;
161 bool bGotCurrentChannel = g_PVRManager.GetCurrentChannel(CurrentChannel);
162 bool bRadio = bGotCurrentChannel ? CurrentChannel->IsRadio() : false;
164 m_parent->m_guideGrid = NULL;
165 m_parent->m_viewControl.SetCurrentView(CONTROL_LIST_GUIDE_NOW_NEXT);
167 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19030));
168 m_parent->SetLabel(CONTROL_LABELGROUP, g_localizeStrings.Get(19030));
170 int iEpgItems = g_PVRManager.GetPlayingGroup(bRadio)->GetEPGNow(*m_parent->m_vecItems);
171 if (iEpgItems == 0 && bRadio)
172 // if we didn't get any events for radio, get tv instead
173 iEpgItems = g_PVRManager.GetPlayingGroup(false)->GetEPGNow(*m_parent->m_vecItems);
178 item.reset(new CFileItem("pvr://guide/now/empty.epg", false));
179 item->SetLabel(g_localizeStrings.Get(19028));
180 item->SetLabelPreformated(true);
181 m_parent->m_vecItems->Add(item);
183 m_parent->m_viewControl.SetItems(*m_parent->m_vecItems);
186 void CGUIWindowPVRGuide::UpdateViewNext(bool bUpdateSelectedFile)
188 CPVRChannelPtr CurrentChannel;
189 bool bGotCurrentChannel = g_PVRManager.GetCurrentChannel(CurrentChannel);
190 bool bRadio = bGotCurrentChannel ? CurrentChannel->IsRadio() : false;
192 m_parent->m_guideGrid = NULL;
193 m_parent->m_viewControl.SetCurrentView(CONTROL_LIST_GUIDE_NOW_NEXT);
195 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19031));
196 m_parent->SetLabel(CONTROL_LABELGROUP, g_localizeStrings.Get(19031));
198 int iEpgItems = g_PVRManager.GetPlayingGroup(bRadio)->GetEPGNext(*m_parent->m_vecItems);
199 if (iEpgItems == 0 && bRadio)
200 // if we didn't get any events for radio, get tv instead
201 iEpgItems = g_PVRManager.GetPlayingGroup(false)->GetEPGNext(*m_parent->m_vecItems);
206 item.reset(new CFileItem("pvr://guide/next/empty.epg", false));
207 item->SetLabel(g_localizeStrings.Get(19028));
208 item->SetLabelPreformated(true);
209 m_parent->m_vecItems->Add(item);
211 m_parent->m_viewControl.SetItems(*m_parent->m_vecItems);
214 void CGUIWindowPVRGuide::UpdateViewTimeline(bool bUpdateSelectedFile)
216 m_parent->m_guideGrid = (CGUIEPGGridContainer*) m_parent->GetControl(CONTROL_LIST_TIMELINE);
217 if (!m_parent->m_guideGrid)
220 CPVRChannelPtr CurrentChannel;
221 bool bGotCurrentChannel = g_PVRManager.GetCurrentChannel(CurrentChannel);
222 bool bRadio = bGotCurrentChannel ? CurrentChannel->IsRadio() : false;
224 if (m_bUpdateRequired || m_cachedTimeline->IsEmpty() ||
225 *m_cachedChannelGroup != *g_PVRManager.GetPlayingGroup(bRadio))
227 m_bUpdateRequired = false;
229 m_cachedTimeline->Clear();
230 m_cachedChannelGroup = g_PVRManager.GetPlayingGroup(bRadio);
231 if (m_cachedChannelGroup->GetEPGAll(*m_cachedTimeline) == 0 && bRadio)
233 // if we didn't get any events for radio, get tv instead
234 m_cachedChannelGroup = g_PVRManager.GetPlayingGroup(false);
235 m_cachedChannelGroup->GetEPGAll(*m_cachedTimeline);
239 m_parent->m_vecItems->RemoveDiscCache(m_parent->GetID());
240 m_parent->m_vecItems->Assign(*m_cachedTimeline, false);
242 CDateTime gridStart = CDateTime::GetCurrentDateTime().GetAsUTCDateTime();
243 CDateTime firstDate(g_EpgContainer.GetFirstEPGDate());
244 CDateTime lastDate(g_EpgContainer.GetLastEPGDate());
245 m_parent->m_guideGrid->SetStartEnd(firstDate > gridStart ? firstDate : gridStart, lastDate);
247 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19032));
248 m_parent->SetLabel(CONTROL_LABELGROUP, g_localizeStrings.Get(19032));
249 m_parent->m_viewControl.SetCurrentView(CONTROL_LIST_TIMELINE, true);
251 if (bUpdateSelectedFile)
255 bool CGUIWindowPVRGuide::SelectPlayingFile(void)
257 if (m_iGuideView == GUIDE_VIEW_TIMELINE)
259 if (m_parent->m_guideGrid && g_PVRManager.IsPlaying())
260 m_parent->m_guideGrid->SetChannel(g_application.CurrentFile());
266 void CGUIWindowPVRGuide::UpdateData(bool bUpdateSelectedFile /* = true */)
268 CSingleLock lock(m_critSection);
269 CLog::Log(LOGDEBUG, "CGUIWindowPVRGuide - %s - update window '%s'. set view to %d", __FUNCTION__, GetName(), m_iControlList);
271 /* lock the graphics context while updating */
272 CSingleLock graphicsLock(g_graphicsContext);
273 m_parent->m_viewControl.Clear();
274 m_parent->m_vecItems->Clear();
276 if (m_iGuideView == GUIDE_VIEW_CHANNEL)
277 UpdateViewChannel(bUpdateSelectedFile);
278 else if (m_iGuideView == GUIDE_VIEW_NOW)
279 UpdateViewNow(bUpdateSelectedFile);
280 else if (m_iGuideView == GUIDE_VIEW_NEXT)
281 UpdateViewNext(bUpdateSelectedFile);
282 else if (m_iGuideView == GUIDE_VIEW_TIMELINE)
283 UpdateViewTimeline(bUpdateSelectedFile);
285 m_bUpdateRequired = false;
286 m_parent->SetLabel(CONTROL_LABELHEADER, g_localizeStrings.Get(19222));
290 bool CGUIWindowPVRGuide::IsSelectedButton(CGUIMessage &message) const
292 unsigned int iControl = message.GetSenderId();
293 return (iControl == CONTROL_BTNGUIDE ||
294 iControl == CONTROL_BTNGUIDE_CHANNEL ||
295 iControl == CONTROL_BTNGUIDE_NOW ||
296 iControl == CONTROL_BTNGUIDE_NEXT ||
297 iControl == CONTROL_BTNGUIDE_TIMELINE);
300 bool CGUIWindowPVRGuide::IsSelectedList(CGUIMessage &message) const
302 return ((message.GetSenderId() == CONTROL_LIST_TIMELINE && m_iGuideView == GUIDE_VIEW_TIMELINE) ||
303 (message.GetSenderId() == CONTROL_LIST_GUIDE_CHANNEL && m_iGuideView == GUIDE_VIEW_CHANNEL) ||
304 (message.GetSenderId() == CONTROL_LIST_GUIDE_NOW_NEXT && (m_iGuideView == GUIDE_VIEW_NOW || m_iGuideView == GUIDE_VIEW_NEXT)));
307 bool CGUIWindowPVRGuide::OnClickButton(CGUIMessage &message)
309 bool bReturn = false;
311 if (IsSelectedButton(message))
313 unsigned int iControl = message.GetSenderId();
316 if (iControl == CONTROL_BTNGUIDE)
318 if (++m_iGuideView > GUIDE_VIEW_TIMELINE)
319 m_iGuideView = GUIDE_VIEW_CHANNEL;
321 else if (iControl == CONTROL_BTNGUIDE_CHANNEL)
322 m_iGuideView = GUIDE_VIEW_CHANNEL;
323 else if (iControl == CONTROL_BTNGUIDE_NOW)
324 m_iGuideView = GUIDE_VIEW_NOW;
325 else if (iControl == CONTROL_BTNGUIDE_NEXT)
326 m_iGuideView = GUIDE_VIEW_NEXT;
327 else if (iControl == CONTROL_BTNGUIDE_TIMELINE)
328 m_iGuideView = GUIDE_VIEW_TIMELINE;
339 bool CGUIWindowPVRGuide::OnClickList(CGUIMessage &message)
341 bool bReturn = false;
343 if (IsSelectedList(message))
345 int iAction = message.GetParam1();
346 int iItem = m_parent->m_viewControl.GetSelectedItem();
348 /* get the fileitem pointer */
349 if (iItem < 0 || iItem >= (int) m_parent->m_vecItems->Size())
351 CFileItemPtr pItem = m_parent->m_vecItems->Get(iItem);
353 /* process actions */
355 if (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK)
357 if (g_advancedSettings.m_bPVRShowEpgInfoOnEpgItemSelect)
358 ShowEPGInfo(pItem.get());
360 PlayEpgItem(pItem.get());
362 else if (iAction == ACTION_SHOW_INFO)
363 ShowEPGInfo(pItem.get());
364 else if (iAction == ACTION_RECORD)
365 ActionRecord(pItem.get());
366 else if (iAction == ACTION_PLAY)
367 ActionPlayEpg(pItem.get());
368 else if (iAction == ACTION_CONTEXT_MENU || iAction == ACTION_MOUSE_RIGHT_CLICK)
369 m_parent->OnPopupMenu(iItem);
377 bool CGUIWindowPVRGuide::OnContextButtonBegin(CFileItem *item, CONTEXT_BUTTON button)
379 bool bReturn = false;
381 if (button == CONTEXT_BUTTON_BEGIN)
383 CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR);
385 pWindow->m_guideGrid->GoToBegin();
392 bool CGUIWindowPVRGuide::OnContextButtonEnd(CFileItem *item, CONTEXT_BUTTON button)
394 bool bReturn = false;
396 if (button == CONTEXT_BUTTON_END)
398 CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR);
400 pWindow->m_guideGrid->GoToEnd();
407 bool CGUIWindowPVRGuide::OnContextButtonInfo(CFileItem *item, CONTEXT_BUTTON button)
409 bool bReturn = false;
411 if (button == CONTEXT_BUTTON_INFO)
420 bool CGUIWindowPVRGuide::PlayEpgItem(CFileItem *item)
422 CPVRChannelPtr channel;
423 if (item && item->HasEPGInfoTag() && item->GetEPGInfoTag()->HasPVRChannel())
424 channel = item->GetEPGInfoTag()->ChannelTag();
426 if (!channel || !g_PVRManager.CheckParentalLock(*channel))
429 CLog::Log(LOGDEBUG, "play channel '%s'", channel->ChannelName().c_str());
430 bool bReturn = g_application.PlayFile(CFileItem(*channel));
432 CGUIDialogOK::ShowAndGetInput(19033,0,19035,0);
437 bool CGUIWindowPVRGuide::OnContextButtonPlay(CFileItem *item, CONTEXT_BUTTON button)
439 bool bReturn = false;
441 if (button == CONTEXT_BUTTON_PLAY_ITEM)
443 bReturn = PlayEpgItem(item);
449 bool CGUIWindowPVRGuide::OnContextButtonStartRecord(CFileItem *item, CONTEXT_BUTTON button)
451 bool bReturn = false;
453 if (button == CONTEXT_BUTTON_START_RECORD)
455 StartRecordFile(item);
462 bool CGUIWindowPVRGuide::OnContextButtonStopRecord(CFileItem *item, CONTEXT_BUTTON button)
464 bool bReturn = false;
466 if (button == CONTEXT_BUTTON_STOP_RECORD)
468 StopRecordFile(item);
475 void CGUIWindowPVRGuide::UpdateButtons(void)
477 if (m_iGuideView == GUIDE_VIEW_CHANNEL)
478 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19029));
479 else if (m_iGuideView == GUIDE_VIEW_NOW)
480 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19030));
481 else if (m_iGuideView == GUIDE_VIEW_NEXT)
482 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19031));
483 else if (m_iGuideView == GUIDE_VIEW_TIMELINE)
484 m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19032));