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)
58 bool CPVRChannelGroupInternal::Load(void)
60 if (CPVRChannelGroup::Load())
63 g_PVRManager.TriggerEpgsCreate();
67 CLog::Log(LOGERROR, "PVRChannelGroupInternal - %s - failed to load channels", __FUNCTION__);
71 void CPVRChannelGroupInternal::CheckGroupName(void)
73 CSingleLock lock(m_critSection);
75 /* check whether the group name is still correct, or channels will fail to load after the language setting changed */
76 CStdString strNewGroupName = g_localizeStrings.Get(m_bRadio ? 19216 : 19217);
77 if (!m_strGroupName.Equals(strNewGroupName))
79 SetGroupName(strNewGroupName, true);
84 void CPVRChannelGroupInternal::UpdateChannelPaths(void)
86 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
88 PVRChannelGroupMember member = m_members.at(iChannelPtr);
89 member.channel->UpdatePath(this, iChannelPtr);
93 void CPVRChannelGroupInternal::UpdateFromClient(const CPVRChannel &channel, unsigned int iChannelNumber /* = 0 */)
95 CSingleLock lock(m_critSection);
96 CPVRChannelPtr realChannel = GetByClient(channel.UniqueID(), channel.ClientID());
98 realChannel->UpdateFromClient(channel);
101 PVRChannelGroupMember newMember = { CPVRChannelPtr(new CPVRChannel(channel)), iChannelNumber > 0l ? iChannelNumber : (int)m_members.size() + 1 };
102 m_members.push_back(newMember);
109 bool CPVRChannelGroupInternal::InsertInGroup(CPVRChannel &channel, int iChannelNumber /* = 0 */)
111 CSingleLock lock(m_critSection);
112 return CPVRChannelGroup::AddToGroup(channel, iChannelNumber);
115 bool CPVRChannelGroupInternal::Update(void)
117 CPVRChannelGroupInternal PVRChannels_tmp(m_bRadio);
118 PVRChannels_tmp.SetPreventSortAndRenumber();
119 return PVRChannels_tmp.LoadFromClients() && UpdateGroupEntries(PVRChannels_tmp);
122 bool CPVRChannelGroupInternal::AddToGroup(CPVRChannel &channel, int iChannelNumber /* = 0 */)
124 CSingleLock lock(m_critSection);
128 /* get the actual channel since this is called from a fileitemlist copy */
129 CPVRChannelPtr realChannel = GetByChannelID(channel.ChannelID());
133 /* switch the hidden flag */
134 if (realChannel->IsHidden())
136 realChannel->SetHidden(false);
142 /* move this channel and persist */
143 bReturn = (iChannelNumber > 0l) ?
144 MoveChannel(realChannel->ChannelNumber(), iChannelNumber, true) :
145 MoveChannel(realChannel->ChannelNumber(), m_members.size() - m_iHiddenChannels, true);
148 realChannel->Persist();
152 bool CPVRChannelGroupInternal::RemoveFromGroup(const CPVRChannel &channel)
154 CSingleLock lock(m_critSection);
156 /* check if this channel is currently playing if we are hiding it */
157 CPVRChannelPtr currentChannel;
158 if (g_PVRManager.GetCurrentChannel(currentChannel) && *currentChannel == channel)
160 CGUIDialogOK::ShowAndGetInput(19098,19101,0,19102);
164 /* get the actual channel since this is called from a fileitemlist copy */
165 CPVRChannelPtr realChannel = GetByChannelID(channel.ChannelID());
169 /* switch the hidden flag */
170 if (!realChannel->IsHidden())
172 realChannel->SetHidden(true);
177 realChannel->SetHidden(false);
181 /* renumber this list */
185 return realChannel->Persist() &&
189 bool CPVRChannelGroupInternal::MoveChannel(unsigned int iOldChannelNumber, unsigned int iNewChannelNumber, bool bSaveInDb /* = true */)
191 CSingleLock lock(m_critSection);
192 /* new channel number out of range */
193 if (iNewChannelNumber > m_members.size() - m_iHiddenChannels)
194 iNewChannelNumber = m_members.size() - m_iHiddenChannels;
196 return CPVRChannelGroup::MoveChannel(iOldChannelNumber, iNewChannelNumber, bSaveInDb);
199 int CPVRChannelGroupInternal::GetMembers(CFileItemList &results, bool bGroupMembers /* = true */) const
201 int iOrigSize = results.Size();
202 CSingleLock lock(m_critSection);
204 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
206 CPVRChannelPtr channel = m_members.at(iChannelPtr).channel;
210 if (bGroupMembers != channel->IsHidden())
212 CFileItemPtr pFileItem(new CFileItem(*channel));
213 results.Add(pFileItem);
217 return results.Size() - iOrigSize;
220 int CPVRChannelGroupInternal::LoadFromDb(bool bCompress /* = false */)
222 CPVRDatabase *database = GetPVRDatabase();
226 int iChannelCount = Size();
228 if (database->Get(*this) > 0)
231 database->Compress(true);
235 CLog::Log(LOGINFO, "PVRChannelGroupInternal - %s - no channels in the database",
239 SortByChannelNumber();
241 return Size() - iChannelCount;
244 bool CPVRChannelGroupInternal::LoadFromClients(void)
246 /* get the channels from the backends */
247 return g_PVRClients->GetChannels(this) == PVR_ERROR_NO_ERROR;
250 bool CPVRChannelGroupInternal::Renumber(void)
252 CSingleLock lock(m_critSection);
253 bool bReturn(CPVRChannelGroup::Renumber());
255 m_iHiddenChannels = 0;
256 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
258 if (m_members.at(iChannelPtr).channel->IsHidden())
261 m_members.at(iChannelPtr).channel->UpdatePath(this, iChannelPtr);
267 bool CPVRChannelGroupInternal::IsGroupMember(const CPVRChannel &channel) const
269 return !channel.IsHidden();
272 bool CPVRChannelGroupInternal::UpdateChannel(const CPVRChannel &channel)
274 CSingleLock lock(m_critSection);
275 CPVRChannelPtr updateChannel = GetByUniqueID(channel.UniqueID());
279 updateChannel = CPVRChannelPtr(new CPVRChannel(channel.IsRadio()));
280 PVRChannelGroupMember newMember = { updateChannel, 0 };
281 m_members.push_back(newMember);
282 updateChannel->SetUniqueID(channel.UniqueID());
284 updateChannel->UpdateFromClient(channel);
286 return updateChannel->Persist(!m_bLoaded);
289 bool CPVRChannelGroupInternal::AddAndUpdateChannels(const CPVRChannelGroup &channels, bool bUseBackendChannelNumbers)
292 SetPreventSortAndRenumber();
294 CSingleLock lock(m_critSection);
296 /* go through the channel list and check for updated or new channels */
297 for (unsigned int iChannelPtr = 0; iChannelPtr < channels.m_members.size(); iChannelPtr++)
299 PVRChannelGroupMember member = channels.m_members.at(iChannelPtr);
303 /* check whether this channel is present in this container */
304 CPVRChannelPtr existingChannel = GetByClient(member.channel->UniqueID(), member.channel->ClientID());
307 /* if it's present, update the current tag */
308 if (existingChannel->UpdateFromClient(*member.channel))
311 CLog::Log(LOGINFO,"PVRChannelGroupInternal - %s - updated %s channel '%s'", __FUNCTION__, m_bRadio ? "radio" : "TV", member.channel->ChannelName().c_str());
317 UpdateFromClient(*member.channel, bUseBackendChannelNumbers ? member.channel->ClientChannelNumber() : 0);
319 CLog::Log(LOGINFO,"PVRChannelGroupInternal - %s - added %s channel '%s'", __FUNCTION__, m_bRadio ? "radio" : "TV", member.channel->ChannelName().c_str());
323 SetPreventSortAndRenumber(false);
330 bool CPVRChannelGroupInternal::UpdateGroupEntries(const CPVRChannelGroup &channels)
334 if (CPVRChannelGroup::UpdateGroupEntries(channels))
336 /* try to find channel icons */
337 if (g_advancedSettings.m_bPVRChannelIconsAutoScan)
338 SearchAndSetChannelIcons();
340 g_PVRTimers->UpdateChannels();
349 void CPVRChannelGroupInternal::CreateChannelEpg(CPVRChannelPtr channel, bool bForce /* = false */)
354 CSingleLock lock(channel->m_critSection);
355 if (!channel->m_bEPGCreated || bForce)
357 CEpg *epg = g_EpgContainer.CreateChannelEpg(channel);
360 channel->m_bEPGCreated = true;
361 if (epg->EpgID() != channel->m_iEpgId)
363 channel->m_iEpgId = epg->EpgID();
364 channel->m_bChanged = true;
370 bool CPVRChannelGroupInternal::CreateChannelEpgs(bool bForce /* = false */)
372 if (!g_EpgContainer.IsStarted())
375 CSingleLock lock(m_critSection);
376 for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
377 CreateChannelEpg(m_members.at(iChannelPtr).channel);
380 if (HasChangedChannels())
382 g_EpgContainer.PersistTables();