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 "GUIWindowPVRChannels.h"
23 #include "dialogs/GUIDialogFileBrowser.h"
24 #include "dialogs/GUIDialogNumeric.h"
25 #include "dialogs/GUIDialogKaiToast.h"
26 #include "dialogs/GUIDialogOK.h"
27 #include "dialogs/GUIDialogYesNo.h"
28 #include "guilib/GUIKeyboardFactory.h"
29 #include "guilib/GUIWindowManager.h"
30 #include "guilib/Key.h"
31 #include "GUIInfoManager.h"
32 #include "profiles/ProfilesManager.h"
33 #include "pvr/PVRManager.h"
34 #include "pvr/channels/PVRChannelGroupsContainer.h"
35 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
36 #include "pvr/windows/GUIWindowPVR.h"
37 #include "pvr/addons/PVRClients.h"
38 #include "pvr/timers/PVRTimers.h"
39 #include "epg/EpgContainer.h"
40 #include "settings/Settings.h"
41 #include "storage/MediaManager.h"
42 #include "utils/log.h"
43 #include "threads/SingleLock.h"
48 CGUIWindowPVRChannels::CGUIWindowPVRChannels(CGUIWindowPVR *parent, bool bRadio) :
49 CGUIWindowPVRCommon(parent,
50 bRadio ? PVR_WINDOW_CHANNELS_RADIO : PVR_WINDOW_CHANNELS_TV,
51 bRadio ? CONTROL_BTNCHANNELS_RADIO : CONTROL_BTNCHANNELS_TV,
52 bRadio ? CONTROL_LIST_CHANNELS_RADIO: CONTROL_LIST_CHANNELS_TV)
55 m_bShowHiddenChannels = false;
58 CGUIWindowPVRChannels::~CGUIWindowPVRChannels(void)
62 void CGUIWindowPVRChannels::ResetObservers(void)
64 CSingleLock lock(m_critSection);
65 g_EpgContainer.RegisterObserver(this);
66 g_PVRTimers->RegisterObserver(this);
67 g_infoManager.RegisterObserver(this);
70 void CGUIWindowPVRChannels::UnregisterObservers(void)
72 CSingleLock lock(m_critSection);
73 g_EpgContainer.UnregisterObserver(this);
75 g_PVRTimers->UnregisterObserver(this);
76 g_infoManager.UnregisterObserver(this);
79 void CGUIWindowPVRChannels::GetContextButtons(int itemNumber, CContextButtons &buttons) const
81 if (itemNumber < 0 || itemNumber >= m_parent->m_vecItems->Size())
83 CFileItemPtr pItem = m_parent->m_vecItems->Get(itemNumber);
84 CPVRChannel *channel = pItem->GetPVRChannelInfoTag();
86 if (pItem->GetPath() == "pvr://channels/.add.channel")
88 /* If yes show only "New Channel" on context menu */
89 buttons.Add(CONTEXT_BUTTON_ADD, 19046); /* add new channel */
93 buttons.Add(CONTEXT_BUTTON_INFO, 19047); /* channel info */
94 buttons.Add(CONTEXT_BUTTON_FIND, 19003); /* find similar program */
95 buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 19000); /* switch to channel */
96 buttons.Add(CONTEXT_BUTTON_RECORD_ITEM, channel->IsRecording() ? 19256 : 19255); /* start/stop recording on channel */
97 buttons.Add(CONTEXT_BUTTON_SET_THUMB, 20019); /* change icon */
98 buttons.Add(CONTEXT_BUTTON_GROUP_MANAGER, 19048); /* group manager */
99 buttons.Add(CONTEXT_BUTTON_HIDE, m_bShowHiddenChannels ? 19049 : 19054); /* show/hide channel */
101 if (m_parent->m_vecItems->Size() > 1 && !m_bShowHiddenChannels)
102 buttons.Add(CONTEXT_BUTTON_MOVE, 116); /* move channel up or down */
104 if (m_bShowHiddenChannels || g_PVRChannelGroups->GetGroupAllTV()->GetNumHiddenChannels() > 0)
105 buttons.Add(CONTEXT_BUTTON_SHOW_HIDDEN, m_bShowHiddenChannels ? 19050 : 19051); /* show hidden/visible channels */
107 if (g_PVRClients->HasMenuHooks(pItem->GetPVRChannelInfoTag()->ClientID(), PVR_MENUHOOK_CHANNEL))
108 buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195); /* PVR client specific action */
110 CPVRChannel *channel = pItem->GetPVRChannelInfoTag();
111 buttons.Add(CONTEXT_BUTTON_ADD_LOCK, channel->IsLocked() ? 19258 : 19257); /* show lock/unlock channel */
113 buttons.Add(CONTEXT_BUTTON_FILTER, 19249); /* filter channels */
114 buttons.Add(CONTEXT_BUTTON_UPDATE_EPG, 19251); /* update EPG information */
118 bool CGUIWindowPVRChannels::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
120 if (itemNumber < 0 || itemNumber >= (int) m_parent->m_vecItems->Size())
122 CFileItemPtr pItem = m_parent->m_vecItems->Get(itemNumber);
124 return OnContextButtonPlay(pItem.get(), button) ||
125 OnContextButtonMove(pItem.get(), button) ||
126 OnContextButtonHide(pItem.get(), button) ||
127 OnContextButtonShowHidden(pItem.get(), button) ||
128 OnContextButtonSetThumb(pItem.get(), button) ||
129 OnContextButtonAdd(pItem.get(), button) ||
130 OnContextButtonInfo(pItem.get(), button) ||
131 OnContextButtonGroupManager(pItem.get(), button) ||
132 OnContextButtonFilter(pItem.get(), button) ||
133 OnContextButtonUpdateEpg(pItem.get(), button) ||
134 OnContextButtonRecord(pItem.get(), button) ||
135 OnContextButtonLock(pItem.get(), button) ||
136 CGUIWindowPVRCommon::OnContextButton(itemNumber, button);
139 CPVRChannelGroupPtr CGUIWindowPVRChannels::SelectedGroup(void)
141 if (!m_selectedGroup)
142 SetSelectedGroup(g_PVRManager.GetPlayingGroup(m_bRadio));
144 return m_selectedGroup;
147 void CGUIWindowPVRChannels::SetSelectedGroup(CPVRChannelGroupPtr group)
153 m_selectedGroup->UnregisterObserver(this);
154 m_selectedGroup = group;
155 m_selectedGroup->RegisterObserver(this);
156 g_PVRManager.SetPlayingGroup(m_selectedGroup);
159 void CGUIWindowPVRChannels::Notify(const Observable &obs, const ObservableMessage msg)
161 if (msg == ObservableMessageChannelGroup || msg == ObservableMessageTimers || msg == ObservableMessageEpgActiveItem || msg == ObservableMessageCurrentItem)
166 m_bUpdateRequired = true;
168 else if (msg == ObservableMessageChannelGroupReset)
173 m_bUpdateRequired = true;
177 CPVRChannelGroupPtr CGUIWindowPVRChannels::SelectNextGroup(void)
179 CPVRChannelGroupPtr currentGroup = SelectedGroup();
180 CPVRChannelGroupPtr nextGroup = currentGroup->GetNextGroup();
181 while (nextGroup && nextGroup->Size() == 0 &&
182 // break if the group matches
183 *nextGroup != *currentGroup &&
184 // or if we hit the first group
185 !nextGroup->IsInternalGroup())
186 nextGroup = nextGroup->GetNextGroup();
188 /* always update so users can reset the list */
191 SetSelectedGroup(nextGroup);
195 return m_selectedGroup;
198 void CGUIWindowPVRChannels::UpdateData(bool bUpdateSelectedFile /* = true */)
200 CSingleLock lock(m_critSection);
201 CLog::Log(LOGDEBUG, "CGUIWindowPVRChannels - %s - update window '%s'. set view to %d",
202 __FUNCTION__, GetName(), m_iControlList);
203 m_bUpdateRequired = false;
205 /* lock the graphics context while updating */
206 CSingleLock graphicsLock(g_graphicsContext);
208 CPVRChannelGroupPtr selectedGroup = SelectedGroup();
210 if (!bUpdateSelectedFile)
211 m_iSelected = m_parent->m_viewControl.GetSelectedItem();
213 m_parent->m_viewControl.SetSelectedItem(0);
215 m_parent->m_viewControl.SetCurrentView(m_iControlList);
217 m_parent->m_vecItems->Clear();
219 CPVRChannelGroupPtr currentGroup = g_PVRManager.GetPlayingGroup(m_bRadio);
223 SetSelectedGroup(currentGroup);
226 strPath = StringUtils::Format("pvr://channels/%s/%s/",
227 m_bRadio ? "radio" : "tv",
228 m_bShowHiddenChannels ? ".hidden" : currentGroup->GroupName().c_str());
230 m_parent->m_vecItems->SetPath(strPath);
231 m_parent->Update(m_parent->m_vecItems->GetPath());
232 m_parent->m_viewControl.SetItems(*m_parent->m_vecItems);
234 if (bUpdateSelectedFile)
236 if (!SelectPlayingFile())
237 m_parent->m_viewControl.SetSelectedItem(m_iSelected);
241 if (m_parent->m_vecItems->Size() == 0)
243 if (m_bShowHiddenChannels)
245 /* show the visible channels instead */
246 m_bShowHiddenChannels = false;
247 graphicsLock.Leave();
250 UpdateData(bUpdateSelectedFile);
253 else if (currentGroup->GroupID() > 0)
255 if (*currentGroup != *SelectNextGroup())
260 m_parent->SetLabel(CONTROL_LABELHEADER, g_localizeStrings.Get(m_bRadio ? 19024 : 19023));
261 if (m_bShowHiddenChannels)
262 m_parent->SetLabel(CONTROL_LABELGROUP, g_localizeStrings.Get(19022));
264 m_parent->SetLabel(CONTROL_LABELGROUP, currentGroup->GroupName());
267 bool CGUIWindowPVRChannels::OnClickButton(CGUIMessage &message)
269 bool bReturn = false;
271 if (IsSelectedButton(message))
280 bool CGUIWindowPVRChannels::OnClickList(CGUIMessage &message)
282 bool bReturn = false;
284 if (IsSelectedList(message))
287 int iAction = message.GetParam1();
288 int iItem = m_parent->m_viewControl.GetSelectedItem();
290 if (iItem < 0 || iItem >= (int) m_parent->m_vecItems->Size())
292 CFileItemPtr pItem = m_parent->m_vecItems->Get(iItem);
294 /* process actions */
295 if (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK || iAction == ACTION_PLAY)
296 ActionPlayChannel(pItem.get());
297 else if (iAction == ACTION_SHOW_INFO)
298 ShowEPGInfo(pItem.get());
299 else if (iAction == ACTION_DELETE_ITEM)
300 ActionDeleteChannel(pItem.get());
301 else if (iAction == ACTION_CONTEXT_MENU || iAction == ACTION_MOUSE_RIGHT_CLICK)
302 m_parent->OnPopupMenu(iItem);
310 bool CGUIWindowPVRChannels::OnContextButtonAdd(CFileItem *item, CONTEXT_BUTTON button)
312 bool bReturn = false;
314 if (button == CONTEXT_BUTTON_ADD)
316 CGUIDialogOK::ShowAndGetInput(19033,0,19038,0);
323 bool CGUIWindowPVRChannels::OnContextButtonGroupManager(CFileItem *item, CONTEXT_BUTTON button)
325 bool bReturn = false;
327 if (button == CONTEXT_BUTTON_GROUP_MANAGER)
336 bool CGUIWindowPVRChannels::OnContextButtonHide(CFileItem *item, CONTEXT_BUTTON button)
338 bool bReturn = false;
340 if (button == CONTEXT_BUTTON_HIDE)
342 CPVRChannel *channel = item->GetPVRChannelInfoTag();
343 if (!channel || channel->IsRadio() != m_bRadio)
346 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
350 pDialog->SetHeading(19039);
351 pDialog->SetLine(0, "");
352 pDialog->SetLine(1, channel->ChannelName());
353 pDialog->SetLine(2, "");
356 if (!pDialog->IsConfirmed())
359 g_PVRManager.GetPlayingGroup(m_bRadio)->RemoveFromGroup(*channel);
368 bool CGUIWindowPVRChannels::OnContextButtonLock(CFileItem *item, CONTEXT_BUTTON button)
370 bool bReturn = false;
372 if (button == CONTEXT_BUTTON_ADD_LOCK)
375 if (!g_PVRManager.CheckParentalPIN(g_localizeStrings.Get(19262).c_str()))
378 CPVRChannelGroupPtr group = g_PVRChannelGroups->GetGroupAll(m_bRadio);
382 group->ToggleChannelLocked(*item);
391 bool CGUIWindowPVRChannels::OnContextButtonInfo(CFileItem *item, CONTEXT_BUTTON button)
393 bool bReturn = false;
395 if (button == CONTEXT_BUTTON_INFO)
404 bool CGUIWindowPVRChannels::OnContextButtonMove(CFileItem *item, CONTEXT_BUTTON button)
406 bool bReturn = false;
408 if (button == CONTEXT_BUTTON_MOVE)
410 CPVRChannel *channel = item->GetPVRChannelInfoTag();
411 if (!channel || channel->IsRadio() != m_bRadio)
415 strIndex = StringUtils::Format("%i", channel->ChannelNumber());
416 CGUIDialogNumeric::ShowAndGetNumber(strIndex, g_localizeStrings.Get(19052));
417 int newIndex = atoi(strIndex.c_str());
419 if (newIndex != channel->ChannelNumber())
421 g_PVRManager.GetPlayingGroup()->MoveChannel(channel->ChannelNumber(), newIndex);
431 bool CGUIWindowPVRChannels::OnContextButtonPlay(CFileItem *item, CONTEXT_BUTTON button)
433 bool bReturn = false;
435 if (button == CONTEXT_BUTTON_PLAY_ITEM)
438 bReturn = PlayFile(item, CSettings::Get().GetBool("pvrplayback.playminimized"));
444 bool CGUIWindowPVRChannels::OnContextButtonSetThumb(CFileItem *item, CONTEXT_BUTTON button)
446 bool bReturn = false;
448 if (button == CONTEXT_BUTTON_SET_THUMB)
450 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
452 else if (!g_passwordManager.IsMasterLockUnlocked(true))
455 /* setup our thumb list */
457 CPVRChannel *channel = item->GetPVRChannelInfoTag();
459 if (!channel->IconPath().IsEmpty())
461 /* add the current thumb, if available */
462 CFileItemPtr current(new CFileItem("thumb://Current", false));
463 current->SetArt("thumb", channel->IconPath());
464 current->SetLabel(g_localizeStrings.Get(20016));
467 else if (item->HasArt("thumb"))
469 /* already have a thumb that the share doesn't know about - must be a local one, so we may as well reuse it */
470 CFileItemPtr current(new CFileItem("thumb://Current", false));
471 current->SetArt("thumb", item->GetArt("thumb"));
472 current->SetLabel(g_localizeStrings.Get(20016));
476 /* and add a "no thumb" entry as well */
477 CFileItemPtr nothumb(new CFileItem("thumb://None", false));
478 nothumb->SetIconImage(item->GetIconImage());
479 nothumb->SetLabel(g_localizeStrings.Get(20018));
484 if (CSettings::Get().GetString("pvrmenu.iconpath") != "")
487 share1.strPath = CSettings::Get().GetString("pvrmenu.iconpath");
488 share1.strName = g_localizeStrings.Get(19018);
489 shares.push_back(share1);
491 g_mediaManager.GetLocalDrives(shares);
492 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, shares, g_localizeStrings.Get(1030), strThumb))
495 if (strThumb != "thumb://Current")
497 if (strThumb == "thumb://None")
500 channel->SetIconPath(strThumb, true);
511 bool CGUIWindowPVRChannels::OnContextButtonShowHidden(CFileItem *item, CONTEXT_BUTTON button)
513 bool bReturn = false;
515 if (button == CONTEXT_BUTTON_SHOW_HIDDEN)
517 m_bShowHiddenChannels = !m_bShowHiddenChannels;
525 bool CGUIWindowPVRChannels::OnContextButtonFilter(CFileItem *item, CONTEXT_BUTTON button)
527 bool bReturn = false;
529 if (button == CONTEXT_BUTTON_FILTER)
531 CStdString filter = m_parent->GetProperty("filter").asString();
532 CGUIKeyboardFactory::ShowAndGetFilter(filter, false);
533 m_parent->OnFilterItems(filter);
541 bool CGUIWindowPVRChannels::OnContextButtonRecord(CFileItem *item, CONTEXT_BUTTON button)
545 if (button == CONTEXT_BUTTON_RECORD_ITEM)
547 CPVRChannel *channel = item->GetPVRChannelInfoTag();
550 return g_PVRManager.ToggleRecordingOnChannel(channel->ChannelID());
556 bool CGUIWindowPVRChannels::OnContextButtonUpdateEpg(CFileItem *item, CONTEXT_BUTTON button)
558 bool bReturn = false;
560 if (button == CONTEXT_BUTTON_UPDATE_EPG)
562 CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
566 CPVRChannel *channel = item->GetPVRChannelInfoTag();
567 pDialog->SetHeading(19251);
568 pDialog->SetLine(0, g_localizeStrings.Get(19252));
569 pDialog->SetLine(1, channel->ChannelName());
570 pDialog->SetLine(2, "");
573 if (!pDialog->IsConfirmed())
576 bReturn = UpdateEpgForChannel(item);
578 CStdString strMessage = StringUtils::Format("%s: '%s'", g_localizeStrings.Get(bReturn ? 19253 : 19254).c_str(), channel->ChannelName().c_str());
579 CGUIDialogKaiToast::QueueNotification(bReturn ? CGUIDialogKaiToast::Info : CGUIDialogKaiToast::Error,
580 g_localizeStrings.Get(19166),
587 void CGUIWindowPVRChannels::ShowGroupManager(void)
589 /* Load group manager dialog */
590 CGUIDialogPVRGroupManager* pDlgInfo = (CGUIDialogPVRGroupManager*)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_GROUP_MANAGER);
594 pDlgInfo->SetRadio(m_bRadio);