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 "PVRChannelGroupInternal.h"
23 #include "guilib/GUIWindowManager.h"
24 #include "dialogs/GUIDialogYesNo.h"
25 #include "dialogs/GUIDialogOK.h"
26 #include "settings/AdvancedSettings.h"
27 #include "utils/log.h"
29 #include "PVRChannelGroupsContainer.h"
30 #include "pvr/PVRDatabase.h"
31 #include "pvr/PVRManager.h"
32 #include "epg/EpgContainer.h"
33 #include "pvr/timers/PVRTimers.h"
34 #include "pvr/addons/PVRClients.h"
40 CPVRChannelGroupInternal::CPVRChannelGroupInternal(bool bRadio) :
41 CPVRChannelGroup(bRadio, bRadio ? XBMC_INTERNAL_GROUP_RADIO : XBMC_INTERNAL_GROUP_TV, g_localizeStrings.Get(bRadio ? 19216 : 19217))
43 m_iHiddenChannels = 0;
44 m_iGroupType = PVR_GROUP_TYPE_INTERNAL;
47 CPVRChannelGroupInternal::CPVRChannelGroupInternal(const CPVRChannelGroup &group) :
48 CPVRChannelGroup(group)
50 m_iHiddenChannels = group.GetNumHiddenChannels();
53 CPVRChannelGroupInternal::~CPVRChannelGroupInternal(void)
56 g_PVRManager.UnregisterObserver(this);
59 bool CPVRChannelGroupInternal::Load(void)
61 if (CPVRChannelGroup::Load())
64 g_PVRManager.RegisterObserver(this);
69 CLog::Log(LOGERROR, "PVRChannelGroupInternal - %s - failed to load channels", __FUNCTION__);
73 void CPVRChannelGroupInternal::CheckGroupName(void)
75 CSingleLock lock(m_critSection);
77 /* check whether the group name is still correct, or channels will fail to load after the language setting changed */
78 CStdString strNewGroupName = g_localizeStrings.Get(m_bRadio ? 19216 : 19217);
79 if (!m_strGroupName.Equals(strNewGroupName))
81 SetGroupName(strNewGroupName, true);
86 void CPVRChannelGroupInternal::UpdateChannelPaths(void)
88 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
90 PVRChannelGroupMember member = m_members.at(iChannelPtr);
91 member.channel->UpdatePath(this, iChannelPtr);
95 void CPVRChannelGroupInternal::UpdateFromClient(const CPVRChannel &channel, unsigned int iChannelNumber /* = 0 */)
97 CSingleLock lock(m_critSection);
98 CPVRChannelPtr realChannel = GetByClient(channel.UniqueID(), channel.ClientID());
100 realChannel->UpdateFromClient(channel);
103 PVRChannelGroupMember newMember = { CPVRChannelPtr(new CPVRChannel(channel)), iChannelNumber > 0l ? iChannelNumber : (int)m_members.size() + 1 };
104 m_members.push_back(newMember);
111 bool CPVRChannelGroupInternal::InsertInGroup(CPVRChannel &channel, int iChannelNumber /* = 0 */)
113 CSingleLock lock(m_critSection);
114 return CPVRChannelGroup::AddToGroup(channel, iChannelNumber);
117 bool CPVRChannelGroupInternal::Update(void)
119 CPVRChannelGroupInternal PVRChannels_tmp(m_bRadio);
120 PVRChannels_tmp.SetPreventSortAndRenumber();
121 return PVRChannels_tmp.LoadFromClients() && UpdateGroupEntries(PVRChannels_tmp);
124 bool CPVRChannelGroupInternal::AddToGroup(CPVRChannel &channel, int iChannelNumber /* = 0 */)
126 CSingleLock lock(m_critSection);
130 /* get the actual channel since this is called from a fileitemlist copy */
131 CPVRChannelPtr realChannel = GetByChannelID(channel.ChannelID());
135 /* switch the hidden flag */
136 if (realChannel->IsHidden())
138 realChannel->SetHidden(false);
144 /* move this channel and persist */
145 bReturn = (iChannelNumber > 0l) ?
146 MoveChannel(realChannel->ChannelNumber(), iChannelNumber, true) :
147 MoveChannel(realChannel->ChannelNumber(), m_members.size() - m_iHiddenChannels, true);
150 realChannel->Persist();
154 bool CPVRChannelGroupInternal::RemoveFromGroup(const CPVRChannel &channel)
156 CSingleLock lock(m_critSection);
158 /* check if this channel is currently playing if we are hiding it */
159 CPVRChannelPtr currentChannel;
160 if (g_PVRManager.GetCurrentChannel(currentChannel) && *currentChannel == channel)
162 CGUIDialogOK::ShowAndGetInput(19098,19101,0,19102);
166 /* get the actual channel since this is called from a fileitemlist copy */
167 CPVRChannelPtr realChannel = GetByChannelID(channel.ChannelID());
171 /* switch the hidden flag */
172 if (!realChannel->IsHidden())
174 realChannel->SetHidden(true);
179 realChannel->SetHidden(false);
183 /* renumber this list */
187 return realChannel->Persist() &&
191 bool CPVRChannelGroupInternal::MoveChannel(unsigned int iOldChannelNumber, unsigned int iNewChannelNumber, bool bSaveInDb /* = true */)
193 CSingleLock lock(m_critSection);
194 /* new channel number out of range */
195 if (iNewChannelNumber > m_members.size() - m_iHiddenChannels)
196 iNewChannelNumber = m_members.size() - m_iHiddenChannels;
198 return CPVRChannelGroup::MoveChannel(iOldChannelNumber, iNewChannelNumber, bSaveInDb);
201 int CPVRChannelGroupInternal::GetMembers(CFileItemList &results, bool bGroupMembers /* = true */) const
203 int iOrigSize = results.Size();
204 CSingleLock lock(m_critSection);
206 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
208 CPVRChannelPtr channel = m_members.at(iChannelPtr).channel;
212 if (bGroupMembers != channel->IsHidden())
214 CFileItemPtr pFileItem(new CFileItem(*channel));
215 results.Add(pFileItem);
219 return results.Size() - iOrigSize;
222 int CPVRChannelGroupInternal::LoadFromDb(bool bCompress /* = false */)
224 CPVRDatabase *database = GetPVRDatabase();
228 int iChannelCount = Size();
230 if (database->Get(*this) > 0)
233 database->Compress(true);
237 CLog::Log(LOGINFO, "PVRChannelGroupInternal - %s - no channels in the database",
241 SortByChannelNumber();
243 return Size() - iChannelCount;
246 bool CPVRChannelGroupInternal::LoadFromClients(void)
248 /* get the channels from the backends */
249 return g_PVRClients->GetChannels(this) == PVR_ERROR_NO_ERROR;
252 bool CPVRChannelGroupInternal::Renumber(void)
254 CSingleLock lock(m_critSection);
255 bool bReturn(CPVRChannelGroup::Renumber());
257 m_iHiddenChannels = 0;
258 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
260 if (m_members.at(iChannelPtr).channel->IsHidden())
263 m_members.at(iChannelPtr).channel->UpdatePath(this, iChannelPtr);
269 bool CPVRChannelGroupInternal::IsGroupMember(const CPVRChannel &channel) const
271 return !channel.IsHidden();
274 bool CPVRChannelGroupInternal::UpdateChannel(const CPVRChannel &channel)
276 CSingleLock lock(m_critSection);
277 CPVRChannelPtr updateChannel = GetByUniqueID(channel.UniqueID());
281 updateChannel = CPVRChannelPtr(new CPVRChannel(channel.IsRadio()));
282 PVRChannelGroupMember newMember = { updateChannel, 0 };
283 m_members.push_back(newMember);
284 updateChannel->SetUniqueID(channel.UniqueID());
286 updateChannel->UpdateFromClient(channel);
288 return updateChannel->Persist(!m_bLoaded);
291 bool CPVRChannelGroupInternal::AddAndUpdateChannels(const CPVRChannelGroup &channels, bool bUseBackendChannelNumbers)
294 SetPreventSortAndRenumber();
296 CSingleLock lock(m_critSection);
298 /* go through the channel list and check for updated or new channels */
299 for (unsigned int iChannelPtr = 0; iChannelPtr < channels.m_members.size(); iChannelPtr++)
301 PVRChannelGroupMember member = channels.m_members.at(iChannelPtr);
305 /* check whether this channel is present in this container */
306 CPVRChannelPtr existingChannel = GetByClient(member.channel->UniqueID(), member.channel->ClientID());
309 /* if it's present, update the current tag */
310 if (existingChannel->UpdateFromClient(*member.channel))
313 CLog::Log(LOGINFO,"PVRChannelGroupInternal - %s - updated %s channel '%s'", __FUNCTION__, m_bRadio ? "radio" : "TV", member.channel->ChannelName().c_str());
319 UpdateFromClient(*member.channel, bUseBackendChannelNumbers ? member.channel->ClientChannelNumber() : 0);
321 CLog::Log(LOGINFO,"PVRChannelGroupInternal - %s - added %s channel '%s'", __FUNCTION__, m_bRadio ? "radio" : "TV", member.channel->ChannelName().c_str());
325 SetPreventSortAndRenumber(false);
332 bool CPVRChannelGroupInternal::UpdateGroupEntries(const CPVRChannelGroup &channels)
336 if (CPVRChannelGroup::UpdateGroupEntries(channels))
338 /* try to find channel icons */
339 if (g_advancedSettings.m_bPVRChannelIconsAutoScan)
340 SearchAndSetChannelIcons();
342 g_PVRTimers->UpdateChannels();
351 void CPVRChannelGroupInternal::CreateChannelEpg(CPVRChannelPtr channel, bool bForce /* = false */)
356 CSingleLock lock(channel->m_critSection);
357 if (!channel->m_bEPGCreated || bForce)
359 CEpg *epg = g_EpgContainer.CreateChannelEpg(channel);
362 channel->m_bEPGCreated = true;
363 if (epg->EpgID() != channel->m_iEpgId)
365 channel->m_iEpgId = epg->EpgID();
366 channel->m_bChanged = true;
372 bool CPVRChannelGroupInternal::CreateChannelEpgs(bool bForce /* = false */)
374 if (!g_EpgContainer.IsStarted())
377 CSingleLock lock(m_critSection);
378 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
379 CreateChannelEpg(m_members.at(iChannelPtr).channel);
382 if (HasChangedChannels())
384 g_EpgContainer.PersistTables();
391 void CPVRChannelGroupInternal::Notify(const Observable &obs, const ObservableMessage msg)
393 if (msg == ObservableMessageManagerStateChanged)
395 g_PVRManager.TriggerEpgsCreate();