fixed: Improved DVDPlayer to fix problem with switch channels
[xbmc:xbmc-antiquated.git] / XBMC / xbmc / pvrclients / PVRClient.cpp
1 /*
2  *      Copyright (C) 2005-2009 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 /*
23  * Description:
24  *
25  * Class CPVRClient is used as a specific interface between the PVR-Client
26  * library and the PVRManager. Every loaded Client have his own CPVRClient
27  * Class, it handle default data for the Manager in the case the Client
28  * can't provide the data and it act as exception handler for all function
29  * called inside client. Further it translate the "C" compatible data
30  * strucures to classes that can easily used by the PVRManager.
31  *
32  * It generate also a callback table with pointers to useful helper
33  * functions, that can be used inside the client to access XBMC
34  * internals.
35  */
36
37 #include <vector>
38 #include "../utils/SingleLock.h"
39 #include "Application.h"
40 #include "LocalizeStrings.h"
41 #include "StringUtils.h"
42 #include "FileItem.h"
43 #include "PVRClient.h"
44 #include "PVRManager.h"
45 #include "URL.h"
46 #include "../utils/log.h"
47 #include "../utils/AddonHelpers.h"
48 #include "../cores/dvdplayer/DVDDemuxers/DVDDemuxPVRManager.h"
49
50 using namespace std;
51 using namespace ADDON;
52
53 CPVRClient::CPVRClient(long clientID, struct PVRClient* pClient, DllPVRClient* pDll,
54                        const ADDON::CAddon& addon, IPVRClientCallback* pvrCB)
55                               : IPVRClient(clientID, addon, pvrCB)
56                               , m_clientID(clientID)
57                               , m_pClient(pClient)
58                               , m_pDll(pDll)
59                               , m_manager(pvrCB)
60                               , m_ReadyToUse(false)
61                               , m_hostName("unknown")
62                               , m_callbacks(NULL)
63 {
64
65 }
66
67 CPVRClient::~CPVRClient()
68 {
69   /* tell the AddOn to deinitialize */
70   DeInit();
71   /* Unload library file */
72   m_pDll->Unload();
73 }
74
75 bool CPVRClient::Init()
76 {
77   CLog::Log(LOGDEBUG, "PVR: %s - Initializing PVR-Client AddOn", m_strName.c_str());
78
79   /* Allocate the callback table to save all the pointers
80      to the helper callback functions */
81   m_callbacks = new AddonCB;
82
83   /* PVR Helper functions */
84   m_callbacks->userData     = this;
85   m_callbacks->addonData    = (CAddon*) this;
86
87   /* Write XBMC Global Add-on function addresses to callback table */
88   CAddonUtils::CreateAddOnCallbacks(m_callbacks);
89
90   /* Write XBMC PVR specific Add-on function addresses to callback table */
91   m_callbacks->PVR.ResetPlayer            = PVRResetPlayer;
92   m_callbacks->PVR.EventCallback          = PVREventCallback;
93   m_callbacks->PVR.TransferEpgEntry       = PVRTransferEpgEntry;
94   m_callbacks->PVR.TransferChannelEntry   = PVRTransferChannelEntry;
95   m_callbacks->PVR.TransferTimerEntry     = PVRTransferTimerEntry;
96   m_callbacks->PVR.TransferRecordingEntry = PVRTransferRecordingEntry;
97   m_callbacks->PVR.AddDemuxStream         = CDVDDemuxPVRManager::AddDemuxStream;
98   m_callbacks->PVR.DeleteDemuxStream      = CDVDDemuxPVRManager::DeleteDemuxStream;
99   m_callbacks->PVR.DeleteDemuxStreams     = CDVDDemuxPVRManager::DeleteDemuxStreams;
100   m_callbacks->PVR.FreeDemuxPacket        = CAddonUtils::FreeDemuxPacket;
101   m_callbacks->PVR.AllocateDemuxPacket    = CAddonUtils::AllocateDemuxPacket;
102
103   /* Call Create to make connections, initializing data or whatever is
104      needed to become the AddOn running */
105   try
106   {
107     ADDON_STATUS status = m_pClient->Create(m_callbacks, m_clientID);
108     if (status != STATUS_OK)
109       throw status;
110     m_ReadyToUse = true;
111     m_hostName   = m_pClient->GetConnectionString();
112   }
113   catch (std::exception &e)
114   {
115     CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during Create occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
116     m_ReadyToUse = false;
117   }
118   catch (ADDON_STATUS status)
119   {
120     CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad status (%i) after Create and is not usable", m_strName.c_str(), m_hostName.c_str(), status);
121     m_ReadyToUse = false;
122
123     /* Delete is performed by the calling class */
124     new CAddonStatusHandler(this, status, "", false);
125   }
126
127   return m_ReadyToUse;
128 }
129
130 void CPVRClient::DeInit()
131 {
132   /* tell the AddOn to disconnect and prepare for destruction */
133   try
134   {
135     CLog::Log(LOGDEBUG, "PVR: %s/%s - Destroying PVR-Client AddOn", m_strName.c_str(), m_hostName.c_str());
136     m_ReadyToUse = false;
137
138     /* Tell the client to destroy */
139     m_pDll->Destroy();
140
141     /* Release Callback table in memory */
142     delete m_callbacks;
143     m_callbacks = NULL;
144   }
145   catch (std::exception &e)
146   {
147     CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during destruction of AddOn occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
148   }
149 }
150
151 bool CPVRClient::ReInit()
152 {
153   DeInit();
154   return Init();
155 }
156
157 ADDON_STATUS CPVRClient::GetStatus()
158 {
159   CSingleLock lock(m_critSection);
160
161   try
162   {
163     return m_pDll->GetStatus();
164   }
165   catch (std::exception &e)
166   {
167     CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetStatus occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
168   }
169   return STATUS_UNKNOWN;
170 }
171
172 long CPVRClient::GetID()
173 {
174   return m_clientID;
175 }
176
177 PVR_ERROR CPVRClient::GetProperties(PVR_SERVERPROPS *props)
178 {
179   CSingleLock lock(m_critSection);
180
181   try
182   {
183     return m_pClient->GetProperties(props);
184   }
185   catch (std::exception &e)
186   {
187     CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetProperties occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
188
189     /* Set all properties in a case of exception to not supported */
190     props->SupportChannelLogo        = false;
191     props->SupportTimeShift          = false;
192     props->SupportEPG                = false;
193     props->SupportRecordings         = false;
194     props->SupportTimers             = false;
195     props->SupportRadio              = false;
196     props->SupportChannelSettings    = false;
197     props->SupportDirector           = false;
198     props->SupportBouquets           = false;
199   }
200   return PVR_ERROR_UNKOWN;
201 }
202
203 /**********************************************************
204  * General PVR Functions
205  */
206
207 const std::string CPVRClient::GetBackendName()
208 {
209   CSingleLock lock(m_critSection);
210
211   if (m_ReadyToUse)
212   {
213     try
214     {
215       return m_pClient->GetBackendName();
216     }
217     catch (std::exception &e)
218     {
219       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetBackendName occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
220     }
221   }
222   /* return string "Unavailable" as fallback */
223   return g_localizeStrings.Get(161);
224 }
225
226 const std::string CPVRClient::GetBackendVersion()
227 {
228   CSingleLock lock(m_critSection);
229
230   if (m_ReadyToUse)
231   {
232     try
233     {
234       return m_pClient->GetBackendVersion();
235     }
236     catch (std::exception &e)
237     {
238       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetBackendVersion occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
239     }
240   }
241   /* return string "Unavailable" as fallback */
242   return g_localizeStrings.Get(161);
243 }
244
245 const std::string CPVRClient::GetConnectionString()
246 {
247   CSingleLock lock(m_critSection);
248
249   if (m_ReadyToUse)
250   {
251     try
252     {
253       return m_pClient->GetConnectionString();
254     }
255     catch (std::exception &e)
256     {
257       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetConnectionString occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
258     }
259   }
260   /* return string "Unavailable" as fallback */
261   return g_localizeStrings.Get(161);
262 }
263
264 PVR_ERROR CPVRClient::GetDriveSpace(long long *total, long long *used)
265 {
266   CSingleLock lock(m_critSection);
267
268   if (m_ReadyToUse)
269   {
270     try
271     {
272       return m_pClient->GetDriveSpace(total, used);
273     }
274     catch (std::exception &e)
275     {
276       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetDriveSpace occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
277     }
278   }
279   *total = 0;
280   *used  = 0;
281   return PVR_ERROR_NOT_IMPLEMENTED;
282 }
283
284
285 /**********************************************************
286  * EPG PVR Functions
287  */
288
289 PVR_ERROR CPVRClient::GetEPGForChannel(const cPVRChannelInfoTag &channelinfo, cPVREpg *epg, time_t start, time_t end)
290 {
291   CSingleLock lock(m_critSection);
292
293   PVR_ERROR ret = PVR_ERROR_UNKOWN;
294
295   if (m_ReadyToUse)
296   {
297     try
298     {
299       PVR_CHANNEL tag;
300       const PVRHANDLE handle = (cPVREpg*) epg;
301       WriteClientChannelInfo(channelinfo, tag);
302       ret = m_pClient->RequestEPGForChannel(handle, tag, start, end);
303       if (ret != PVR_ERROR_NO_ERROR)
304         throw ret;
305
306       return PVR_ERROR_NO_ERROR;
307     }
308     catch (std::exception &e)
309     {
310       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetEPGForChannel occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
311     }
312     catch (PVR_ERROR ret)
313     {
314       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after GetEPGForChannel", m_strName.c_str(), m_hostName.c_str(), ret);
315     }
316   }
317   return ret;
318 }
319
320 void CPVRClient::PVRTransferEpgEntry(void *userData, const PVRHANDLE handle, const PVR_PROGINFO *epgentry)
321 {
322   CPVRClient* client = (CPVRClient*) userData;
323   if (client == NULL || handle == NULL || epgentry == NULL)
324   {
325     CLog::Log(LOGERROR, "PVR: PVRTransferEpgEntry is called with NULL-Pointer!!!");
326     return;
327   }
328
329   cPVREpg *xbmcEpg = (cPVREpg*) handle;
330   cPVREpg::Add(epgentry, xbmcEpg);
331   return;
332 }
333
334 /**********************************************************
335  * Channels PVR Functions
336  */
337
338 int CPVRClient::GetNumChannels()
339 {
340   CSingleLock lock(m_critSection);
341
342   if (m_ReadyToUse)
343   {
344     try
345     {
346       return m_pClient->GetNumChannels();
347     }
348     catch (std::exception &e)
349     {
350       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetNumChannels occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
351     }
352   }
353   return -1;
354 }
355
356 PVR_ERROR CPVRClient::GetChannelList(cPVRChannels &channels, bool radio)
357 {
358   CSingleLock lock(m_critSection);
359
360   PVR_ERROR ret = PVR_ERROR_UNKOWN;
361
362   if (m_ReadyToUse)
363   {
364     try
365     {
366       const PVRHANDLE handle = (cPVRChannels*) &channels;
367       ret = m_pClient->RequestChannelList(handle, radio);
368       if (ret != PVR_ERROR_NO_ERROR)
369         throw ret;
370
371       return PVR_ERROR_NO_ERROR;
372     }
373     catch (std::exception &e)
374     {
375       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetChannelList occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
376     }
377     catch (PVR_ERROR ret)
378     {
379       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after GetChannelList", m_strName.c_str(), m_hostName.c_str(), ret);
380     }
381   }
382   return ret;
383 }
384
385 void CPVRClient::PVRTransferChannelEntry(void *userData, const PVRHANDLE handle, const PVR_CHANNEL *channel)
386 {
387   CPVRClient* client = (CPVRClient*) userData;
388   if (client == NULL || handle == NULL || channel == NULL)
389   {
390     CLog::Log(LOGERROR, "PVR: PVRTransferChannelEntry is called with NULL-Pointer!!!");
391     return;
392   }
393
394   cPVRChannels *xbmcChannels = (cPVRChannels*) handle;
395   cPVRChannelInfoTag tag;
396
397   tag.SetChannelID(-1);
398   tag.SetNumber(-1);
399   tag.SetClientNumber(channel->number);
400   tag.SetGroupID(0);
401   tag.SetClientID(client->m_clientID);
402   tag.SetUniqueID(channel->uid);
403   tag.SetName(channel->name);
404   tag.SetClientName(channel->callsign);
405   tag.SetIcon(channel->iconpath);
406   tag.SetEncryptionSystem(channel->encryption);
407   tag.SetRadio(channel->radio);
408   tag.SetHidden(channel->hide);
409   tag.SetRecording(channel->recording);
410   tag.SetStream(channel->stream_url);
411
412   xbmcChannels->push_back(tag);
413   return;
414 }
415
416 PVR_ERROR CPVRClient::GetChannelSettings(cPVRChannelInfoTag *result)
417 {
418   CSingleLock lock(m_critSection);
419
420   PVR_ERROR ret = PVR_ERROR_UNKOWN;
421
422   if (m_ReadyToUse)
423   {
424     try
425     {
426 //      ret = m_pClient->GetChannelSettings(result);
427       if (ret != PVR_ERROR_NO_ERROR)
428         throw ret;
429
430       return PVR_ERROR_NO_ERROR;
431     }
432     catch (std::exception &e)
433     {
434       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetChannelSettings occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
435     }
436     catch (PVR_ERROR ret)
437     {
438       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after GetChannelSettings", m_strName.c_str(), m_hostName.c_str(), ret);
439     }
440   }
441   return ret;
442 }
443
444 PVR_ERROR CPVRClient::UpdateChannelSettings(const cPVRChannelInfoTag &chaninfo)
445 {
446   CSingleLock lock(m_critSection);
447
448   PVR_ERROR ret = PVR_ERROR_UNKOWN;
449
450   if (m_ReadyToUse)
451   {
452     try
453     {
454 //      ret = m_pClient->UpdateChannelSettings(chaninfo);
455       if (ret != PVR_ERROR_NO_ERROR)
456         throw ret;
457
458       return PVR_ERROR_NO_ERROR;
459     }
460     catch (std::exception &e)
461     {
462       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during UpdateChannelSettings occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
463     }
464     catch (PVR_ERROR ret)
465     {
466       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after UpdateChannelSettings", m_strName.c_str(), m_hostName.c_str(), ret);
467     }
468   }
469   return ret;
470 }
471
472 PVR_ERROR CPVRClient::AddChannel(const cPVRChannelInfoTag &info)
473 {
474   CSingleLock lock(m_critSection);
475
476   PVR_ERROR ret = PVR_ERROR_UNKOWN;
477
478   if (m_ReadyToUse)
479   {
480     try
481     {
482 //      ret = m_pClient->AddChannel(info);
483       if (ret != PVR_ERROR_NO_ERROR)
484         throw ret;
485
486       return PVR_ERROR_NO_ERROR;
487     }
488     catch (std::exception &e)
489     {
490       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during AddChannel occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
491     }
492     catch (PVR_ERROR ret)
493     {
494       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after AddChannel", m_strName.c_str(), m_hostName.c_str(), ret);
495     }
496   }
497   return ret;
498 }
499
500 PVR_ERROR CPVRClient::DeleteChannel(unsigned int number)
501 {
502   CSingleLock lock(m_critSection);
503
504   PVR_ERROR ret = PVR_ERROR_UNKOWN;
505
506   if (m_ReadyToUse)
507   {
508     try
509     {
510 //      ret = m_pClient->DeleteChannel(number);
511       if (ret != PVR_ERROR_NO_ERROR)
512         throw ret;
513
514       return PVR_ERROR_NO_ERROR;
515     }
516     catch (std::exception &e)
517     {
518       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during DeleteChannel occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
519     }
520     catch (PVR_ERROR ret)
521     {
522       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after DeleteChannel", m_strName.c_str(), m_hostName.c_str(), ret);
523     }
524   }
525   return ret;
526 }
527
528 PVR_ERROR CPVRClient::RenameChannel(unsigned int number, CStdString &newname)
529 {
530   CSingleLock lock(m_critSection);
531
532   PVR_ERROR ret = PVR_ERROR_UNKOWN;
533
534   if (m_ReadyToUse)
535   {
536     try
537     {
538 //      ret = m_pClient->RenameChannel(number, newname);
539       if (ret != PVR_ERROR_NO_ERROR)
540         throw ret;
541
542       return PVR_ERROR_NO_ERROR;
543     }
544     catch (std::exception &e)
545     {
546       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during RenameChannel occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
547     }
548     catch (PVR_ERROR ret)
549     {
550       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after RenameChannel", m_strName.c_str(), m_hostName.c_str(), ret);
551     }
552   }
553   return ret;
554 }
555
556 PVR_ERROR CPVRClient::MoveChannel(unsigned int number, unsigned int newnumber)
557 {
558   CSingleLock lock(m_critSection);
559
560   PVR_ERROR ret = PVR_ERROR_UNKOWN;
561
562   if (m_ReadyToUse)
563   {
564     try
565     {
566 //      ret = m_pClient->MoveChannel(number, newnumber);
567       if (ret != PVR_ERROR_NO_ERROR)
568         throw ret;
569
570       return PVR_ERROR_NO_ERROR;
571     }
572     catch (std::exception &e)
573     {
574       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during MoveChannel occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
575     }
576     catch (PVR_ERROR ret)
577     {
578       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after MoveChannel", m_strName.c_str(), m_hostName.c_str(), ret);
579     }
580   }
581   return ret;
582 }
583
584
585 /**********************************************************
586  * Recordings PVR Functions
587  */
588
589 int CPVRClient::GetNumRecordings(void)
590 {
591   CSingleLock lock(m_critSection);
592
593   if (m_ReadyToUse)
594   {
595     try
596     {
597       return m_pClient->GetNumRecordings();
598     }
599     catch (std::exception &e)
600     {
601       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetNumRecordings occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
602     }
603   }
604   return -1;
605 }
606
607 PVR_ERROR CPVRClient::GetAllRecordings(cPVRRecordings *results)
608 {
609   CSingleLock lock(m_critSection);
610
611   PVR_ERROR ret = PVR_ERROR_UNKOWN;
612
613   if (m_ReadyToUse)
614   {
615     try
616     {
617       const PVRHANDLE handle = (cPVRRecordings*) results;
618       ret = m_pClient->RequestRecordingsList(handle);
619       if (ret != PVR_ERROR_NO_ERROR)
620         throw ret;
621
622       return PVR_ERROR_NO_ERROR;
623     }
624     catch (std::exception &e)
625     {
626       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetAllRecordings occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
627     }
628     catch (PVR_ERROR ret)
629     {
630       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after GetAllRecordings", m_strName.c_str(), m_hostName.c_str(), ret);
631     }
632   }
633   return ret;
634 }
635
636 void CPVRClient::PVRTransferRecordingEntry(void *userData, const PVRHANDLE handle, const PVR_RECORDINGINFO *recording)
637 {
638   CPVRClient* client = (CPVRClient*) userData;
639   if (client == NULL || handle == NULL || recording == NULL)
640   {
641     CLog::Log(LOGERROR, "PVR: PVRTransferRecordingEntry is called with NULL-Pointer!!!");
642     return;
643   }
644
645   cPVRRecordings *xbmcRecordings = (cPVRRecordings*) handle;
646
647   cPVRRecordingInfoTag tag;
648
649   tag.SetClientIndex(recording->index);
650   tag.SetClientID(client->m_clientID);
651   tag.SetChannelName(recording->channelName);
652   tag.SetRecordingTime(recording->starttime);
653   tag.SetDuration(CDateTimeSpan(0, 0, recording->duration / 60, recording->duration % 60));
654   tag.SetPriority(recording->priority);
655   tag.SetLifetime(recording->lifetime);
656   tag.SetTitle(recording->title);
657   tag.SetPlot(recording->description);
658   tag.SetPlotOutline(recording->subtitle);
659
660   xbmcRecordings->push_back(tag);
661   return;
662 }
663
664 PVR_ERROR CPVRClient::DeleteRecording(const cPVRRecordingInfoTag &recinfo)
665 {
666   CSingleLock lock(m_critSection);
667
668   PVR_ERROR ret = PVR_ERROR_UNKOWN;
669
670   if (m_ReadyToUse)
671   {
672     try
673     {
674       PVR_RECORDINGINFO tag;
675       WriteClientRecordingInfo(recinfo, tag);
676
677       ret = m_pClient->DeleteRecording(tag);
678       if (ret != PVR_ERROR_NO_ERROR)
679         throw ret;
680
681       return PVR_ERROR_NO_ERROR;
682     }
683     catch (std::exception &e)
684     {
685       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during DeleteRecording occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
686     }
687     catch (PVR_ERROR ret)
688     {
689       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after DeleteRecording", m_strName.c_str(), m_hostName.c_str(), ret);
690     }
691   }
692   return ret;
693 }
694
695 PVR_ERROR CPVRClient::RenameRecording(const cPVRRecordingInfoTag &recinfo, CStdString &newname)
696 {
697   CSingleLock lock(m_critSection);
698
699   PVR_ERROR ret = PVR_ERROR_UNKOWN;
700
701   if (m_ReadyToUse)
702   {
703     try
704     {
705       PVR_RECORDINGINFO tag;
706       WriteClientRecordingInfo(recinfo, tag);
707
708       ret = m_pClient->RenameRecording(tag, newname);
709       if (ret != PVR_ERROR_NO_ERROR)
710         throw ret;
711
712       return PVR_ERROR_NO_ERROR;
713     }
714     catch (std::exception &e)
715     {
716       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during RenameRecording occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
717     }
718     catch (PVR_ERROR ret)
719     {
720       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after RenameRecording", m_strName.c_str(), m_hostName.c_str(), ret);
721     }
722   }
723   return ret;
724 }
725
726 void CPVRClient::WriteClientRecordingInfo(const cPVRRecordingInfoTag &recordinginfo, PVR_RECORDINGINFO &tag)
727 {
728   tag.index         = recordinginfo.ClientIndex();
729   tag.title         = recordinginfo.Title();
730   tag.subtitle      = recordinginfo.PlotOutline();
731   tag.description   = recordinginfo.Plot();
732   tag.channelName   = recordinginfo.ChannelName();
733   tag.duration      = recordinginfo.GetDuration();
734   tag.priority      = recordinginfo.Priority();
735   tag.lifetime      = recordinginfo.Lifetime();
736   time_t recTime    = tag.starttime;
737   recordinginfo.RecordingTime().GetAsTime(recTime);
738   return;
739 }
740
741
742 /**********************************************************
743  * Timers PVR Functions
744  */
745
746 int CPVRClient::GetNumTimers(void)
747 {
748   CSingleLock lock(m_critSection);
749
750   if (m_ReadyToUse)
751   {
752     try
753     {
754       return m_pClient->GetNumTimers();
755     }
756     catch (std::exception &e)
757     {
758       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetNumTimers occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
759     }
760   }
761   return -1;
762 }
763
764 PVR_ERROR CPVRClient::GetAllTimers(cPVRTimers *results)
765 {
766   CSingleLock lock(m_critSection);
767
768   PVR_ERROR ret = PVR_ERROR_UNKOWN;
769
770   if (m_ReadyToUse)
771   {
772     try
773     {
774       const PVRHANDLE handle = (cPVRTimers*) results;
775       ret = m_pClient->RequestTimerList(handle);
776       if (ret != PVR_ERROR_NO_ERROR)
777         throw ret;
778
779       return PVR_ERROR_NO_ERROR;
780     }
781     catch (std::exception &e)
782     {
783       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetAllTimers occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
784     }
785     catch (PVR_ERROR ret)
786     {
787       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after GetAllTimers", m_strName.c_str(), m_hostName.c_str(), ret);
788     }
789   }
790   return ret;
791 }
792
793 void CPVRClient::PVRTransferTimerEntry(void *userData, const PVRHANDLE handle, const PVR_TIMERINFO *timer)
794 {
795   CPVRClient* client = (CPVRClient*) userData;
796   if (client == NULL || handle == NULL || timer == NULL)
797   {
798     CLog::Log(LOGERROR, "PVR: PVRTransferTimerEntry is called with NULL-Pointer!!!");
799     return;
800   }
801
802   cPVRTimers *xbmcTimers     = (cPVRTimers*) handle;
803   cPVRChannelInfoTag *channel  = cPVRChannels::GetByClientFromAll(timer->channelNum, client->m_clientID);
804
805   if (channel == NULL)
806   {
807     CLog::Log(LOGERROR, "PVR: PVRTransferTimerEntry is called with not present channel");
808     return;
809   }
810
811   cPVRTimerInfoTag tag;
812   tag.SetClientID(client->m_clientID);
813   tag.SetClientIndex(timer->index);
814   tag.SetActive(timer->active);
815   tag.SetTitle(timer->title);
816   tag.SetClientNumber(timer->channelNum);
817   tag.SetStart((time_t) timer->starttime);
818   tag.SetStop((time_t) timer->endtime);
819   tag.SetFirstDay((time_t) timer->firstday);
820   tag.SetPriority(timer->priority);
821   tag.SetLifetime(timer->lifetime);
822   tag.SetRecording(timer->recording);
823   tag.SetRepeating(timer->repeat);
824   tag.SetWeekdays(timer->repeatflags);
825   tag.SetNumber(channel->Number());
826   tag.SetRadio(channel->IsRadio());
827   CStdString path;
828   path.Format("pvr://client%i/timers/%i", tag.ClientID(), tag.ClientIndex());
829   tag.SetPath(path);
830
831   CStdString summary;
832   if (!tag.IsRepeating())
833   {
834     summary.Format("%s %s %s %s %s", tag.Start().GetAsLocalizedDate()
835                    , g_localizeStrings.Get(18078)
836                    , tag.Start().GetAsLocalizedTime("", false)
837                    , g_localizeStrings.Get(18079)
838                    , tag.Stop().GetAsLocalizedTime("", false));
839   }
840   else if (tag.FirstDay() != NULL)
841   {
842     summary.Format("%s-%s-%s-%s-%s-%s-%s %s %s %s %s %s %s"
843                    , timer->repeatflags & 0x01 ? g_localizeStrings.Get(18080) : "__"
844                    , timer->repeatflags & 0x02 ? g_localizeStrings.Get(18081) : "__"
845                    , timer->repeatflags & 0x04 ? g_localizeStrings.Get(18082) : "__"
846                    , timer->repeatflags & 0x08 ? g_localizeStrings.Get(18083) : "__"
847                    , timer->repeatflags & 0x10 ? g_localizeStrings.Get(18084) : "__"
848                    , timer->repeatflags & 0x20 ? g_localizeStrings.Get(18085) : "__"
849                    , timer->repeatflags & 0x40 ? g_localizeStrings.Get(18086) : "__"
850                    , g_localizeStrings.Get(18087)
851                    , tag.FirstDay().GetAsLocalizedDate(false)
852                    , g_localizeStrings.Get(18078)
853                    , tag.Start().GetAsLocalizedTime("", false)
854                    , g_localizeStrings.Get(18079)
855                    , tag.Stop().GetAsLocalizedTime("", false));
856   }
857   else
858   {
859     summary.Format("%s-%s-%s-%s-%s-%s-%s %s %s %s %s"
860                    , timer->repeatflags & 0x01 ? g_localizeStrings.Get(18080) : "__"
861                    , timer->repeatflags & 0x02 ? g_localizeStrings.Get(18081) : "__"
862                    , timer->repeatflags & 0x04 ? g_localizeStrings.Get(18082) : "__"
863                    , timer->repeatflags & 0x08 ? g_localizeStrings.Get(18083) : "__"
864                    , timer->repeatflags & 0x10 ? g_localizeStrings.Get(18084) : "__"
865                    , timer->repeatflags & 0x20 ? g_localizeStrings.Get(18085) : "__"
866                    , timer->repeatflags & 0x40 ? g_localizeStrings.Get(18086) : "__"
867                    , g_localizeStrings.Get(18078)
868                    , tag.Start().GetAsLocalizedTime("", false)
869                    , g_localizeStrings.Get(18079)
870                    , tag.Stop().GetAsLocalizedTime("", false));
871   }
872   tag.SetSummary(summary);
873
874   xbmcTimers->push_back(tag);
875   return;
876 }
877
878 PVR_ERROR CPVRClient::AddTimer(const cPVRTimerInfoTag &timerinfo)
879 {
880   CSingleLock lock(m_critSection);
881
882   PVR_ERROR ret = PVR_ERROR_UNKOWN;
883
884   if (m_ReadyToUse)
885   {
886     try
887     {
888       PVR_TIMERINFO tag;
889       WriteClientTimerInfo(timerinfo, tag);
890
891       ret = m_pClient->AddTimer(tag);
892       if (ret != PVR_ERROR_NO_ERROR)
893         throw ret;
894
895       return PVR_ERROR_NO_ERROR;
896     }
897     catch (std::exception &e)
898     {
899       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during AddTimer occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
900     }
901     catch (PVR_ERROR ret)
902     {
903       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after AddTimer", m_strName.c_str(), m_hostName.c_str(), ret);
904     }
905   }
906   return ret;
907 }
908
909 PVR_ERROR CPVRClient::DeleteTimer(const cPVRTimerInfoTag &timerinfo, bool force)
910 {
911   CSingleLock lock(m_critSection);
912
913   PVR_ERROR ret = PVR_ERROR_UNKOWN;
914
915   if (m_ReadyToUse)
916   {
917     try
918     {
919       PVR_TIMERINFO tag;
920       WriteClientTimerInfo(timerinfo, tag);
921
922       ret = m_pClient->DeleteTimer(tag, force);
923       if (ret != PVR_ERROR_NO_ERROR)
924         throw ret;
925
926       return PVR_ERROR_NO_ERROR;
927     }
928     catch (std::exception &e)
929     {
930       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during DeleteTimer occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
931     }
932     catch (PVR_ERROR ret)
933     {
934       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after DeleteTimer", m_strName.c_str(), m_hostName.c_str(), ret);
935     }
936   }
937   return ret;
938 }
939
940 PVR_ERROR CPVRClient::RenameTimer(const cPVRTimerInfoTag &timerinfo, CStdString &newname)
941 {
942   CSingleLock lock(m_critSection);
943
944   PVR_ERROR ret = PVR_ERROR_UNKOWN;
945
946   if (m_ReadyToUse)
947   {
948     try
949     {
950       PVR_TIMERINFO tag;
951       WriteClientTimerInfo(timerinfo, tag);
952
953       ret = m_pClient->RenameTimer(tag, newname.c_str());
954       if (ret != PVR_ERROR_NO_ERROR)
955         throw ret;
956
957       return PVR_ERROR_NO_ERROR;
958     }
959     catch (std::exception &e)
960     {
961       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during RenameTimer occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
962     }
963     catch (PVR_ERROR ret)
964     {
965       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after RenameTimer", m_strName.c_str(), m_hostName.c_str(), ret);
966     }
967   }
968   return ret;
969 }
970
971 PVR_ERROR CPVRClient::UpdateTimer(const cPVRTimerInfoTag &timerinfo)
972 {
973   CSingleLock lock(m_critSection);
974
975   PVR_ERROR ret = PVR_ERROR_UNKOWN;
976
977   if (m_ReadyToUse)
978   {
979     try
980     {
981       PVR_TIMERINFO tag;
982       WriteClientTimerInfo(timerinfo, tag);
983
984       ret = m_pClient->UpdateTimer(tag);
985       if (ret != PVR_ERROR_NO_ERROR)
986         throw ret;
987
988       return PVR_ERROR_NO_ERROR;
989     }
990     catch (std::exception &e)
991     {
992       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during UpdateTimer occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
993     }
994     catch (PVR_ERROR ret)
995     {
996       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after UpdateTimer", m_strName.c_str(), m_hostName.c_str(), ret);
997     }
998   }
999   return ret;
1000 }
1001
1002 void CPVRClient::WriteClientTimerInfo(const cPVRTimerInfoTag &timerinfo, PVR_TIMERINFO &tag)
1003 {
1004   tag.index         = timerinfo.ClientIndex();
1005   tag.active        = timerinfo.Active();
1006   tag.channelNum    = timerinfo.ClientNumber();
1007   tag.recording     = timerinfo.IsRecording();
1008   tag.title         = timerinfo.Title();
1009   tag.priority      = timerinfo.Priority();
1010   tag.lifetime      = timerinfo.Lifetime();
1011   tag.repeat        = timerinfo.IsRepeating();
1012   tag.repeatflags   = timerinfo.Weekdays();
1013   tag.starttime     = timerinfo.StartTime();
1014   tag.endtime       = timerinfo.StopTime();
1015   tag.firstday      = timerinfo.FirstDayTime();
1016   return;
1017 }
1018
1019 /**********************************************************
1020  * Stream PVR Functions
1021  */
1022
1023 bool CPVRClient::OpenLiveStream(const cPVRChannelInfoTag &channelinfo)
1024 {
1025   CSingleLock lock(m_critSection);
1026
1027   if (m_ReadyToUse)
1028   {
1029     try
1030     {
1031       PVR_CHANNEL tag;
1032       WriteClientChannelInfo(channelinfo, tag);
1033       return m_pClient->OpenLiveStream(tag);
1034     }
1035     catch (std::exception &e)
1036     {
1037       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during OpenLiveStream occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1038     }
1039   }
1040   return false;
1041 }
1042
1043 void CPVRClient::CloseLiveStream()
1044 {
1045   CSingleLock lock(m_critSection);
1046
1047   if (m_ReadyToUse)
1048   {
1049     try
1050     {
1051       m_pClient->CloseLiveStream();
1052       return;
1053     }
1054     catch (std::exception &e)
1055     {
1056       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during CloseLiveStream occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1057     }
1058   }
1059   return;
1060 }
1061
1062 int CPVRClient::ReadLiveStream(BYTE* buf, int buf_size)
1063 {
1064   return m_pClient->ReadLiveStream(buf, buf_size);
1065 }
1066
1067 __int64 CPVRClient::SeekLiveStream(__int64 pos, int whence)
1068 {
1069   return m_pClient->SeekLiveStream(pos, whence);
1070 }
1071
1072 __int64 CPVRClient::LengthLiveStream(void)
1073 {
1074   return m_pClient->LengthLiveStream();
1075 }
1076
1077 int CPVRClient::GetCurrentClientChannel()
1078 {
1079   CSingleLock lock(m_critSection);
1080
1081   return m_pClient->GetCurrentClientChannel();
1082 }
1083
1084 bool CPVRClient::SwitchChannel(const cPVRChannelInfoTag &channelinfo)
1085 {
1086   CSingleLock lock(m_critSection);
1087
1088   PVR_CHANNEL tag;
1089   WriteClientChannelInfo(channelinfo, tag);
1090   return m_pClient->SwitchChannel(tag);
1091 }
1092
1093 bool CPVRClient::SignalQuality(PVR_SIGNALQUALITY &qualityinfo)
1094 {
1095   CSingleLock lock(m_critSection);
1096
1097   if (m_ReadyToUse)
1098   {
1099     PVR_ERROR ret = PVR_ERROR_UNKOWN;
1100     try
1101     {
1102       ret = m_pClient->SignalQuality(qualityinfo);
1103       if (ret != PVR_ERROR_NO_ERROR)
1104         throw ret;
1105
1106       return true;
1107     }
1108     catch (std::exception &e)
1109     {
1110       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during SignalQuality occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1111     }
1112     catch (PVR_ERROR ret)
1113     {
1114       CLog::Log(LOGERROR, "PVR: %s/%s - Client returns bad error (%i) after SignalQuality", m_strName.c_str(), m_hostName.c_str(), ret);
1115     }
1116   }
1117   return false;
1118 }
1119
1120 void CPVRClient::WriteClientChannelInfo(const cPVRChannelInfoTag &channelinfo, PVR_CHANNEL &tag)
1121 {
1122   tag.uid               = channelinfo.UniqueID();
1123   tag.number            = channelinfo.ClientNumber();
1124   tag.name              = channelinfo.Name().c_str();
1125   tag.callsign          = channelinfo.ClientName().c_str();
1126   tag.iconpath          = channelinfo.Icon().c_str();
1127   tag.encryption        = channelinfo.EncryptionSystem();
1128   tag.radio             = channelinfo.IsRadio();
1129   tag.hide              = channelinfo.IsHidden();
1130   tag.recording         = channelinfo.IsRecording();
1131   tag.bouquet           = 0;
1132   tag.multifeed         = false;
1133   tag.multifeed_master  = 0;
1134   tag.multifeed_number  = 0;
1135   tag.stream_url        = channelinfo.Stream();
1136   return;
1137 }
1138
1139 bool CPVRClient::OpenRecordedStream(const cPVRRecordingInfoTag &recinfo)
1140 {
1141   CSingleLock lock(m_critSection);
1142
1143   PVR_RECORDINGINFO tag;
1144   WriteClientRecordingInfo(recinfo, tag);
1145   return m_pClient->OpenRecordedStream(tag);
1146 }
1147
1148 void CPVRClient::CloseRecordedStream(void)
1149 {
1150   CSingleLock lock(m_critSection);
1151
1152   return m_pClient->CloseRecordedStream();
1153 }
1154
1155 int CPVRClient::ReadRecordedStream(BYTE* buf, int buf_size)
1156 {
1157   return m_pClient->ReadRecordedStream(buf, buf_size);
1158 }
1159
1160 __int64 CPVRClient::SeekRecordedStream(__int64 pos, int whence)
1161 {
1162   return m_pClient->SeekRecordedStream(pos, whence);
1163 }
1164
1165 __int64 CPVRClient::LengthRecordedStream(void)
1166 {
1167   return m_pClient->LengthRecordedStream();
1168 }
1169
1170 bool CPVRClient::OpenTVDemux(PVRDEMUXHANDLE handle, const cPVRChannelInfoTag &channelinfo)
1171 {
1172   CSingleLock lock(m_critSection);
1173
1174   if (m_ReadyToUse)
1175   {
1176     try
1177     {
1178       PVR_CHANNEL tag;
1179       WriteClientChannelInfo(channelinfo, tag);
1180       return m_pClient->OpenTVDemux(handle, tag);
1181     }
1182     catch (std::exception &e)
1183     {
1184       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during OpenTVDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1185     }
1186   }
1187   return false;
1188 }
1189
1190 bool CPVRClient::OpenRecordingDemux(PVRDEMUXHANDLE handle, const cPVRRecordingInfoTag &recinfo)
1191 {
1192   CSingleLock lock(m_critSection);
1193
1194   if (m_ReadyToUse)
1195   {
1196     try
1197     {
1198       PVR_RECORDINGINFO tag;
1199       WriteClientRecordingInfo(recinfo, tag);
1200       return m_pClient->OpenRecordingDemux(handle, tag);
1201     }
1202     catch (std::exception &e)
1203     {
1204       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during OpenRecordingDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1205     }
1206   }
1207   return false;
1208 }
1209
1210 void CPVRClient::DisposeDemux()
1211 {
1212   CSingleLock lock(m_critSection);
1213
1214   if (m_ReadyToUse)
1215   {
1216     try
1217     {
1218       m_pClient->DisposeDemux();
1219       return;
1220     }
1221     catch (std::exception &e)
1222     {
1223       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during DisposeDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1224     }
1225   }
1226   return;
1227 }
1228
1229 void CPVRClient::ResetDemux()
1230 {
1231   CSingleLock lock(m_critSection);
1232
1233   if (m_ReadyToUse)
1234   {
1235     try
1236     {
1237       m_pClient->ResetDemux();
1238       return;
1239     }
1240     catch (std::exception &e)
1241     {
1242       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during ResetDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1243     }
1244   }
1245   return;
1246 }
1247
1248 void CPVRClient::FlushDemux()
1249 {
1250   CSingleLock lock(m_critSection);
1251
1252   if (m_ReadyToUse)
1253   {
1254     try
1255     {
1256       m_pClient->FlushDemux();
1257       return;
1258     }
1259     catch (std::exception &e)
1260     {
1261       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during FlushDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1262     }
1263   }
1264   return;
1265 }
1266
1267 void CPVRClient::AbortDemux()
1268 {
1269   CSingleLock lock(m_critSection);
1270
1271   if (m_ReadyToUse)
1272   {
1273     try
1274     {
1275       m_pClient->AbortDemux();
1276       return;
1277     }
1278     catch (std::exception &e)
1279     {
1280       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during AbortDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1281     }
1282   }
1283   return;
1284 }
1285
1286 void CPVRClient::SetDemuxSpeed(int iSpeed)
1287 {
1288   CSingleLock lock(m_critSection);
1289
1290   if (m_ReadyToUse)
1291   {
1292     try
1293     {
1294       m_pClient->SetDemuxSpeed(iSpeed);
1295       return;
1296     }
1297     catch (std::exception &e)
1298     {
1299       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during SetDemuxSpeed occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1300     }
1301   }
1302   return;
1303 }
1304
1305 demux_packet_t* CPVRClient::ReadDemux()
1306 {
1307   CSingleLock lock(m_critSection);
1308
1309   if (m_ReadyToUse)
1310   {
1311     try
1312     {
1313       return m_pClient->ReadDemux();
1314     }
1315     catch (std::exception &e)
1316     {
1317       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during ReadDemux occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1318     }
1319   }
1320   return NULL;
1321 }
1322
1323 bool CPVRClient::SeekDemuxTime(int time, bool backwords, double* startpts)
1324 {
1325   CSingleLock lock(m_critSection);
1326
1327   if (m_ReadyToUse)
1328   {
1329     try
1330     {
1331       return m_pClient->SeekDemuxTime(time, backwords, startpts);
1332     }
1333     catch (std::exception &e)
1334     {
1335       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during SeekDemuxTime occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1336     }
1337   }
1338   return false;
1339 }
1340
1341 int CPVRClient::GetDemuxStreamLength()
1342 {
1343   CSingleLock lock(m_critSection);
1344
1345   if (m_ReadyToUse)
1346   {
1347     try
1348     {
1349       return m_pClient->GetDemuxStreamLength();
1350     }
1351     catch (std::exception &e)
1352     {
1353       CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during GetDemuxStreamLength occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1354     }
1355   }
1356   return 0;
1357 }
1358
1359
1360 /**********************************************************
1361  * Addon specific functions
1362  * Are used for every type of AddOn
1363  */
1364
1365 ADDON_STATUS CPVRClient::SetSetting(const char *settingName, const void *settingValue)
1366 {
1367   CSingleLock lock(m_critSection);
1368
1369   try
1370   {
1371     return m_pDll->SetSetting(settingName, settingValue);
1372   }
1373   catch (std::exception &e)
1374   {
1375     CLog::Log(LOGERROR, "PVR: %s/%s - exception '%s' during SetSetting occurred, contact Developer '%s' of this AddOn", m_strName.c_str(), m_hostName.c_str(), e.what(), m_strCreator.c_str());
1376     return STATUS_UNKNOWN;
1377   }
1378 }
1379
1380
1381 /**********************************************************
1382  * Client specific Callbacks
1383  * Are independent and can be different for every type of
1384  * AddOn
1385  */
1386
1387 void CPVRClient::PVRResetPlayer(void *userData)
1388 {
1389   CPVRClient* client=(CPVRClient*) userData;
1390   if (!client)
1391     return;
1392
1393   g_application.m_pPlayer->PlaybackReset();
1394   return;
1395 }
1396
1397 void CPVRClient::PVREventCallback(void *userData, const PVR_EVENT pvrevent, const char *msg)
1398 {
1399   CPVRClient* client=(CPVRClient*) userData;
1400   if (!client)
1401     return;
1402
1403   client->m_manager->OnClientMessage(client->m_clientID, pvrevent, msg);
1404 }