[cstdstring] demise Format, replacing with StringUtils::Format
[vuplus_xbmc] / xbmc / pvr / PVRGUIInfo.cpp
1 /*
2  *      Copyright (C) 2012-2013 Team XBMC
3  *      http://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, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "Application.h"
22 #include "PVRGUIInfo.h"
23 #include "guilib/LocalizeStrings.h"
24 #include "utils/StringUtils.h"
25 #include "GUIInfoManager.h"
26 #include "Util.h"
27 #include "threads/SingleLock.h"
28 #include "PVRManager.h"
29 #include "pvr/addons/PVRClients.h"
30 #include "pvr/timers/PVRTimers.h"
31 #include "pvr/recordings/PVRRecordings.h"
32 #include "pvr/channels/PVRChannel.h"
33 #include "epg/EpgInfoTag.h"
34 #include "settings/AdvancedSettings.h"
35 #include "settings/Settings.h"
36
37 using namespace PVR;
38 using namespace EPG;
39 using namespace std;
40
41 CPVRGUIInfo::CPVRGUIInfo(void) :
42     CThread("PVRGUIInfo"),
43     m_playingEpgTag(NULL)
44 {
45   ResetProperties();
46 }
47
48 CPVRGUIInfo::~CPVRGUIInfo(void)
49 {
50   Stop();
51 }
52
53 void CPVRGUIInfo::ResetProperties(void)
54 {
55   CSingleLock lock(m_critSection);
56   m_strActiveTimerTitle         = StringUtils::EmptyString;
57   m_strActiveTimerChannelName   = StringUtils::EmptyString;
58   m_strActiveTimerChannelIcon   = StringUtils::EmptyString;
59   m_strActiveTimerTime          = StringUtils::EmptyString;
60   m_strNextTimerInfo            = StringUtils::EmptyString;
61   m_strNextRecordingTitle       = StringUtils::EmptyString;
62   m_strNextRecordingChannelName = StringUtils::EmptyString;
63   m_strNextRecordingChannelIcon = StringUtils::EmptyString;
64   m_strNextRecordingTime        = StringUtils::EmptyString;
65   m_iTimerAmount                = 0;
66   m_bHasRecordings              = false;
67   m_iRecordingTimerAmount       = 0;
68   m_iActiveClients              = 0;
69   m_strPlayingClientName        = StringUtils::EmptyString;
70   m_strBackendName              = StringUtils::EmptyString;
71   m_strBackendVersion           = StringUtils::EmptyString;
72   m_strBackendHost              = StringUtils::EmptyString;
73   m_strBackendDiskspace         = StringUtils::EmptyString;
74   m_strBackendTimers            = StringUtils::EmptyString;
75   m_strBackendRecordings        = StringUtils::EmptyString;
76   m_strBackendChannels          = StringUtils::EmptyString;
77   m_strTotalDiskspace           = StringUtils::EmptyString;
78   m_iAddonInfoToggleStart       = 0;
79   m_iAddonInfoToggleCurrent     = 0;
80   m_iTimerInfoToggleStart       = 0;
81   m_iTimerInfoToggleCurrent     = 0;
82   m_ToggleShowInfo.SetInfinite();
83   m_iDuration                   = 0;
84   m_bHasNonRecordingTimers      = false;
85   m_bIsPlayingTV                = false;
86   m_bIsPlayingRadio             = false;
87   m_bIsPlayingRecording         = false;
88   m_bIsPlayingEncryptedStream   = false;
89
90   ResetPlayingTag();
91   ClearQualityInfo(m_qualityInfo);
92 }
93
94 void CPVRGUIInfo::ClearQualityInfo(PVR_SIGNAL_STATUS &qualityInfo)
95 {
96   memset(&qualityInfo, 0, sizeof(qualityInfo));
97   strncpy(qualityInfo.strAdapterName, g_localizeStrings.Get(13106).c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1);
98   strncpy(qualityInfo.strAdapterStatus, g_localizeStrings.Get(13106).c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1);
99 }
100
101 void CPVRGUIInfo::Start(void)
102 {
103   ResetProperties();
104   Create();
105   SetPriority(-1);
106 }
107
108 void CPVRGUIInfo::Stop(void)
109 {
110   StopThread();
111   if (g_PVRTimers)
112     g_PVRTimers->UnregisterObserver(this);
113 }
114
115 void CPVRGUIInfo::Notify(const Observable &obs, const ObservableMessage msg)
116 {
117   if (msg == ObservableMessageTimers || msg == ObservableMessageTimersReset)
118     UpdateTimersCache();
119 }
120
121 void CPVRGUIInfo::ShowPlayerInfo(int iTimeout)
122 {
123   CSingleLock lock(m_critSection);
124
125   if (iTimeout > 0)
126     m_ToggleShowInfo.Set(iTimeout * 1000);
127
128   g_infoManager.SetShowInfo(true);
129 }
130
131 void CPVRGUIInfo::ToggleShowInfo(void)
132 {
133   CSingleLock lock(m_critSection);
134
135   if (m_ToggleShowInfo.IsTimePast())
136   {
137     m_ToggleShowInfo.SetInfinite();
138     g_infoManager.SetShowInfo(false);
139   }
140 }
141
142 bool CPVRGUIInfo::AddonInfoToggle(void)
143 {
144   CSingleLock lock(m_critSection);
145   if (m_iAddonInfoToggleStart == 0)
146   {
147     m_iAddonInfoToggleStart = XbmcThreads::SystemClockMillis();
148     m_iAddonInfoToggleCurrent = 0;
149     return true;
150   }
151
152   if ((int) (XbmcThreads::SystemClockMillis() - m_iAddonInfoToggleStart) > g_advancedSettings.m_iPVRInfoToggleInterval)
153   {
154     unsigned int iPrevious = m_iAddonInfoToggleCurrent;
155     if (((int) ++m_iAddonInfoToggleCurrent) > m_iActiveClients - 1)
156       m_iAddonInfoToggleCurrent = 0;
157
158     return m_iAddonInfoToggleCurrent != iPrevious;
159   }
160
161   return false;
162 }
163
164 bool CPVRGUIInfo::TimerInfoToggle(void)
165 {
166   CSingleLock lock(m_critSection);
167   if (m_iTimerInfoToggleStart == 0)
168   {
169     m_iTimerInfoToggleStart = XbmcThreads::SystemClockMillis();
170     m_iTimerInfoToggleCurrent = 0;
171     return true;
172   }
173
174   if ((int) (XbmcThreads::SystemClockMillis() - m_iTimerInfoToggleStart) > g_advancedSettings.m_iPVRInfoToggleInterval)
175   {
176     unsigned int iPrevious = m_iTimerInfoToggleCurrent;
177     unsigned int iBoundary = m_iRecordingTimerAmount > 0 ? m_iRecordingTimerAmount : m_iTimerAmount;
178     if (++m_iTimerInfoToggleCurrent > iBoundary - 1)
179       m_iTimerInfoToggleCurrent = 0;
180
181     return m_iTimerInfoToggleCurrent != iPrevious;
182   }
183
184   return false;
185 }
186
187 void CPVRGUIInfo::Process(void)
188 {
189   unsigned int mLoop(0);
190
191   /* updated on request */
192   g_PVRTimers->RegisterObserver(this);
193   UpdateTimersCache();
194
195   while (!g_application.m_bStop && !m_bStop)
196   {
197     if (!m_bStop)
198       ToggleShowInfo();
199     Sleep(0);
200
201     if (!m_bStop)
202       UpdateQualityData();
203     Sleep(0);
204
205     if (!m_bStop)
206       UpdateMisc();
207     Sleep(0);
208
209     if (!m_bStop)
210       UpdatePlayingTag();
211     Sleep(0);
212
213     if (!m_bStop)
214       UpdateTimersToggle();
215     Sleep(0);
216
217     if (!m_bStop)
218       UpdateNextTimer();
219     Sleep(0);
220
221     if (!m_bStop && mLoop % 10 == 0)
222       UpdateBackendCache();    /* updated every 10 iterations */
223
224     if (++mLoop == 1000)
225       mLoop = 0;
226
227     if (!m_bStop)
228       Sleep(1000);
229   }
230
231   if (!m_bStop)
232     ResetPlayingTag();
233 }
234
235 void CPVRGUIInfo::UpdateQualityData(void)
236 {
237   PVR_SIGNAL_STATUS qualityInfo;
238   ClearQualityInfo(qualityInfo);
239
240   PVR_CLIENT client;
241   if (CSettings::Get().GetBool("pvrplayback.signalquality") &&
242       g_PVRClients->GetPlayingClient(client))
243   {
244     client->SignalQuality(qualityInfo);
245   }
246
247   memcpy(&m_qualityInfo, &qualityInfo, sizeof(m_qualityInfo));
248 }
249
250 void CPVRGUIInfo::UpdateMisc(void)
251 {
252   bool bStarted = g_PVRManager.IsStarted();
253   CStdString strPlayingClientName      = bStarted ? g_PVRClients->GetPlayingClientName() : StringUtils::EmptyString;
254   bool       bHasRecordings            = bStarted && g_PVRRecordings->GetNumRecordings() > 0;
255   bool       bIsPlayingTV              = bStarted && g_PVRClients->IsPlayingTV();
256   bool       bIsPlayingRadio           = bStarted && g_PVRClients->IsPlayingRadio();
257   bool       bIsPlayingRecording       = bStarted && g_PVRClients->IsPlayingRecording();
258   bool       bIsPlayingEncryptedStream = bStarted && g_PVRClients->IsEncrypted();
259   /* safe to fetch these unlocked, since they're updated from the same thread as this one */
260   bool       bHasNonRecordingTimers    = bStarted && m_iTimerAmount - m_iRecordingTimerAmount > 0;
261
262   CSingleLock lock(m_critSection);
263   m_strPlayingClientName      = strPlayingClientName;
264   m_bHasRecordings            = bHasRecordings;
265   m_bHasNonRecordingTimers    = bHasNonRecordingTimers;
266   m_bIsPlayingTV              = bIsPlayingTV;
267   m_bIsPlayingRadio           = bIsPlayingRadio;
268   m_bIsPlayingRecording       = bIsPlayingRecording;
269   m_bIsPlayingEncryptedStream = bIsPlayingEncryptedStream;
270 }
271
272 bool CPVRGUIInfo::TranslateCharInfo(DWORD dwInfo, CStdString &strValue) const
273 {
274   bool bReturn(true);
275   CSingleLock lock(m_critSection);
276
277   switch(dwInfo)
278   {
279   case PVR_NOW_RECORDING_TITLE:
280     CharInfoActiveTimerTitle(strValue);
281     break;
282   case PVR_NOW_RECORDING_CHANNEL:
283     CharInfoActiveTimerChannelName(strValue);
284     break;
285   case PVR_NOW_RECORDING_CHAN_ICO:
286     CharInfoActiveTimerChannelIcon(strValue);
287     break;
288   case PVR_NOW_RECORDING_DATETIME:
289     CharInfoActiveTimerDateTime(strValue);
290     break;
291   case PVR_NEXT_RECORDING_TITLE:
292     CharInfoNextTimerTitle(strValue);
293     break;
294   case PVR_NEXT_RECORDING_CHANNEL:
295     CharInfoNextTimerChannelName(strValue);
296     break;
297   case PVR_NEXT_RECORDING_CHAN_ICO:
298     CharInfoNextTimerChannelIcon(strValue);
299     break;
300   case PVR_NEXT_RECORDING_DATETIME:
301     CharInfoNextTimerDateTime(strValue);
302     break;
303   case PVR_PLAYING_DURATION:
304     CharInfoPlayingDuration(strValue);
305     break;
306   case PVR_PLAYING_TIME:
307     CharInfoPlayingTime(strValue);
308     break;
309   case PVR_NEXT_TIMER:
310     CharInfoNextTimer(strValue);
311     break;
312   case PVR_ACTUAL_STREAM_VIDEO_BR:
313     CharInfoVideoBR(strValue);
314     break;
315   case PVR_ACTUAL_STREAM_AUDIO_BR:
316     CharInfoAudioBR(strValue);
317     break;
318   case PVR_ACTUAL_STREAM_DOLBY_BR:
319     CharInfoDolbyBR(strValue);
320     break;
321   case PVR_ACTUAL_STREAM_SIG:
322     CharInfoSignal(strValue);
323     break;
324   case PVR_ACTUAL_STREAM_SNR:
325     CharInfoSNR(strValue);
326     break;
327   case PVR_ACTUAL_STREAM_BER:
328     CharInfoBER(strValue);
329     break;
330   case PVR_ACTUAL_STREAM_UNC:
331     CharInfoUNC(strValue);
332     break;
333   case PVR_ACTUAL_STREAM_CLIENT:
334     CharInfoPlayingClientName(strValue);
335     break;
336   case PVR_ACTUAL_STREAM_DEVICE:
337     CharInfoFrontendName(strValue);
338     break;
339   case PVR_ACTUAL_STREAM_STATUS:
340     CharInfoFrontendStatus(strValue);
341     break;
342   case PVR_ACTUAL_STREAM_CRYPTION:
343     CharInfoEncryption(strValue);
344     break;
345   case PVR_ACTUAL_STREAM_SERVICE:
346     CharInfoService(strValue);
347     break;
348   case PVR_ACTUAL_STREAM_MUX:
349     CharInfoMux(strValue);
350     break;
351   case PVR_ACTUAL_STREAM_PROVIDER:
352     CharInfoProvider(strValue);
353     break;
354   case PVR_BACKEND_NAME:
355     CharInfoBackendName(strValue);
356     break;
357   case PVR_BACKEND_VERSION:
358     CharInfoBackendVersion(strValue);
359     break;
360   case PVR_BACKEND_HOST:
361     CharInfoBackendHost(strValue);
362     break;
363   case PVR_BACKEND_DISKSPACE:
364     CharInfoBackendDiskspace(strValue);
365     break;
366   case PVR_BACKEND_CHANNELS:
367     CharInfoBackendChannels(strValue);
368     break;
369   case PVR_BACKEND_TIMERS:
370     CharInfoBackendTimers(strValue);
371     break;
372   case PVR_BACKEND_RECORDINGS:
373     CharInfoBackendRecordings(strValue);
374     break;
375   case PVR_BACKEND_NUMBER:
376     CharInfoBackendNumber(strValue);
377     break;
378   case PVR_TOTAL_DISKSPACE:
379     CharInfoTotalDiskSpace(strValue);
380     break;
381   default:
382     strValue = StringUtils::EmptyString;
383     bReturn = false;
384     break;
385   }
386
387   return bReturn;
388 }
389
390 bool CPVRGUIInfo::TranslateBoolInfo(DWORD dwInfo) const
391 {
392   bool bReturn(false);
393   CSingleLock lock(m_critSection);
394
395   switch (dwInfo)
396   {
397   case PVR_IS_RECORDING:
398     bReturn = m_iRecordingTimerAmount > 0;
399     break;
400   case PVR_HAS_TIMER:
401     bReturn = m_iTimerAmount > 0;
402     break;
403   case PVR_HAS_NONRECORDING_TIMER:
404     bReturn = m_bHasNonRecordingTimers;
405     break;
406   case PVR_IS_PLAYING_TV:
407     bReturn = m_bIsPlayingTV;
408     break;
409   case PVR_IS_PLAYING_RADIO:
410     bReturn = m_bIsPlayingRadio;
411     break;
412   case PVR_IS_PLAYING_RECORDING:
413     bReturn = m_bIsPlayingRecording;
414     break;
415   case PVR_ACTUAL_STREAM_ENCRYPTED:
416     bReturn = m_bIsPlayingEncryptedStream;
417     break;
418   default:
419     break;
420   }
421
422   return bReturn;
423 }
424
425 int CPVRGUIInfo::TranslateIntInfo(DWORD dwInfo) const
426 {
427   int iReturn(0);
428   CSingleLock lock(m_critSection);
429
430   if (dwInfo == PVR_PLAYING_PROGRESS)
431     iReturn = (int) ((float) GetStartTime() / m_iDuration * 100);
432   else if (dwInfo == PVR_ACTUAL_STREAM_SIG_PROGR)
433     iReturn = (int) ((float) m_qualityInfo.iSignal / 0xFFFF * 100);
434   else if (dwInfo == PVR_ACTUAL_STREAM_SNR_PROGR)
435     iReturn = (int) ((float) m_qualityInfo.iSNR / 0xFFFF * 100);
436
437   return iReturn;
438 }
439
440 void CPVRGUIInfo::CharInfoActiveTimerTitle(CStdString &strValue) const
441 {
442   strValue = StringUtils::Format("%s", m_strActiveTimerTitle.c_str());
443 }
444
445 void CPVRGUIInfo::CharInfoActiveTimerChannelName(CStdString &strValue) const
446 {
447   strValue = StringUtils::Format("%s", m_strActiveTimerChannelName.c_str());
448 }
449
450 void CPVRGUIInfo::CharInfoActiveTimerChannelIcon(CStdString &strValue) const
451 {
452   strValue = StringUtils::Format("%s", m_strActiveTimerChannelIcon.c_str());
453 }
454
455 void CPVRGUIInfo::CharInfoActiveTimerDateTime(CStdString &strValue) const
456 {
457   strValue = StringUtils::Format("%s", m_strActiveTimerTime.c_str());
458 }
459
460 void CPVRGUIInfo::CharInfoNextTimerTitle(CStdString &strValue) const
461 {
462   strValue = StringUtils::Format("%s", m_strNextRecordingTitle.c_str());
463 }
464
465 void CPVRGUIInfo::CharInfoNextTimerChannelName(CStdString &strValue) const
466 {
467   strValue = StringUtils::Format("%s", m_strNextRecordingChannelName.c_str());
468 }
469
470 void CPVRGUIInfo::CharInfoNextTimerChannelIcon(CStdString &strValue) const
471 {
472   strValue = StringUtils::Format("%s", m_strNextRecordingChannelIcon.c_str());
473 }
474
475 void CPVRGUIInfo::CharInfoNextTimerDateTime(CStdString &strValue) const
476 {
477   strValue = StringUtils::Format("%s", m_strNextRecordingTime.c_str());
478 }
479
480 void CPVRGUIInfo::CharInfoPlayingDuration(CStdString &strValue) const
481 {
482   strValue = StringUtils::Format("%s", StringUtils::SecondsToTimeString(m_iDuration / 1000, TIME_FORMAT_GUESS).c_str());
483 }
484
485 void CPVRGUIInfo::CharInfoPlayingTime(CStdString &strValue) const
486 {
487   strValue = StringUtils::Format("%s", StringUtils::SecondsToTimeString(GetStartTime()/1000, TIME_FORMAT_GUESS).c_str());
488 }
489
490 void CPVRGUIInfo::CharInfoNextTimer(CStdString &strValue) const
491 {
492   strValue = StringUtils::Format("%s", m_strNextTimerInfo.c_str());
493 }
494
495 void CPVRGUIInfo::CharInfoBackendNumber(CStdString &strValue) const
496 {
497   if (m_iActiveClients > 0)
498     strValue = StringUtils::Format("%u %s %u", m_iAddonInfoToggleCurrent+1, g_localizeStrings.Get(20163).c_str(), m_iActiveClients);
499   else
500     strValue = StringUtils::Format("%s", g_localizeStrings.Get(14023).c_str());
501 }
502
503 void CPVRGUIInfo::CharInfoTotalDiskSpace(CStdString &strValue) const
504 {
505   strValue = StringUtils::Format("%s", m_strTotalDiskspace.c_str());
506 }
507
508 void CPVRGUIInfo::CharInfoVideoBR(CStdString &strValue) const
509 {
510   strValue = StringUtils::Format("%.2f Mbit/s", m_qualityInfo.dVideoBitrate);
511 }
512
513 void CPVRGUIInfo::CharInfoAudioBR(CStdString &strValue) const
514 {
515   strValue = StringUtils::Format("%.0f kbit/s", m_qualityInfo.dAudioBitrate);
516 }
517
518 void CPVRGUIInfo::CharInfoDolbyBR(CStdString &strValue) const
519 {
520   strValue = StringUtils::Format("%.0f kbit/s", m_qualityInfo.dDolbyBitrate);
521 }
522
523 void CPVRGUIInfo::CharInfoSignal(CStdString &strValue) const
524 {
525   strValue = StringUtils::Format("%d %%", m_qualityInfo.iSignal / 655);
526 }
527
528 void CPVRGUIInfo::CharInfoSNR(CStdString &strValue) const
529 {
530   strValue = StringUtils::Format("%d %%", m_qualityInfo.iSNR / 655);
531 }
532
533 void CPVRGUIInfo::CharInfoBER(CStdString &strValue) const
534 {
535   strValue = StringUtils::Format("%08X", m_qualityInfo.iBER);
536 }
537
538 void CPVRGUIInfo::CharInfoUNC(CStdString &strValue) const
539 {
540   strValue = StringUtils::Format("%08X", m_qualityInfo.iUNC);
541 }
542
543 void CPVRGUIInfo::CharInfoFrontendName(CStdString &strValue) const
544 {
545   if (!strcmp(m_qualityInfo.strAdapterName, StringUtils::EmptyString))
546     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
547   else
548     strValue = StringUtils::Format("%s", m_qualityInfo.strAdapterName);
549 }
550
551 void CPVRGUIInfo::CharInfoFrontendStatus(CStdString &strValue) const
552 {
553   if (!strcmp(m_qualityInfo.strAdapterStatus, StringUtils::EmptyString))
554     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
555   else
556     strValue = StringUtils::Format("%s", m_qualityInfo.strAdapterStatus);
557 }
558
559 void CPVRGUIInfo::CharInfoBackendName(CStdString &strValue) const
560 {
561   if (m_strBackendName.IsEmpty())
562     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
563   else
564     strValue = StringUtils::Format("%s", m_strBackendName.c_str());
565 }
566
567 void CPVRGUIInfo::CharInfoBackendVersion(CStdString &strValue) const
568 {
569   if (m_strBackendVersion.IsEmpty())
570     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
571   else
572     strValue = StringUtils::Format("%s",  m_strBackendVersion.c_str());
573 }
574
575 void CPVRGUIInfo::CharInfoBackendHost(CStdString &strValue) const
576 {
577   if (m_strBackendHost.IsEmpty())
578     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
579   else
580     strValue = StringUtils::Format("%s", m_strBackendHost.c_str());
581 }
582
583 void CPVRGUIInfo::CharInfoBackendDiskspace(CStdString &strValue) const
584 {
585   if (m_strBackendDiskspace.IsEmpty())
586     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
587   else
588     strValue = StringUtils::Format("%s", m_strBackendDiskspace.c_str());
589 }
590
591 void CPVRGUIInfo::CharInfoBackendChannels(CStdString &strValue) const
592 {
593   if (m_strBackendChannels.IsEmpty())
594     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
595   else
596     strValue = StringUtils::Format("%s", m_strBackendChannels.c_str());
597 }
598
599 void CPVRGUIInfo::CharInfoBackendTimers(CStdString &strValue) const
600 {
601   if (m_strBackendTimers.IsEmpty())
602     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
603   else
604     strValue = StringUtils::Format("%s", m_strBackendTimers.c_str());
605 }
606
607 void CPVRGUIInfo::CharInfoBackendRecordings(CStdString &strValue) const
608 {
609   if (m_strBackendRecordings.IsEmpty())
610     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
611   else
612     strValue = StringUtils::Format("%s", m_strBackendRecordings.c_str());
613 }
614
615 void CPVRGUIInfo::CharInfoPlayingClientName(CStdString &strValue) const
616 {
617   if (m_strPlayingClientName.IsEmpty())
618     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
619   else
620     strValue = StringUtils::Format("%s", m_strPlayingClientName.c_str());
621 }
622
623 void CPVRGUIInfo::CharInfoEncryption(CStdString &strValue) const
624 {
625   CPVRChannelPtr channel;
626   if (g_PVRClients->GetPlayingChannel(channel))
627     strValue = StringUtils::Format("%s", channel->EncryptionName().c_str());
628   else
629     strValue = StringUtils::EmptyString;
630 }
631
632 void CPVRGUIInfo::CharInfoService(CStdString &strValue) const
633 {
634   if (!strcmp(m_qualityInfo.strServiceName, StringUtils::EmptyString))
635     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
636   else
637     strValue = StringUtils::Format("%s", m_qualityInfo.strServiceName);
638 }
639
640 void CPVRGUIInfo::CharInfoMux(CStdString &strValue) const
641 {
642   if (!strcmp(m_qualityInfo.strMuxName, StringUtils::EmptyString))
643     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
644   else
645     strValue = StringUtils::Format("%s", m_qualityInfo.strMuxName);
646 }
647
648 void CPVRGUIInfo::CharInfoProvider(CStdString &strValue) const
649 {
650   if (!strcmp(m_qualityInfo.strProviderName, StringUtils::EmptyString))
651     strValue = StringUtils::Format("%s", g_localizeStrings.Get(13205).c_str());
652   else
653     strValue = StringUtils::Format("%s", m_qualityInfo.strProviderName);
654 }
655
656 void CPVRGUIInfo::UpdateBackendCache(void)
657 {
658   CStdString strBackendName;
659   CStdString strBackendVersion;
660   CStdString strBackendHost;
661   CStdString strBackendDiskspace;
662   CStdString strBackendTimers;
663   CStdString strBackendRecordings;
664   CStdString strBackendChannels;
665   int        iActiveClients(0);
666
667   if (!AddonInfoToggle())
668     return;
669
670   CPVRClients *clients = g_PVRClients;
671   PVR_CLIENTMAP activeClients;
672   iActiveClients = clients->GetConnectedClients(activeClients);
673   if (iActiveClients > 0)
674   {
675     PVR_CLIENTMAP_CITR activeClient = activeClients.begin();
676     /* safe to read unlocked */
677     for (unsigned int i = 0; i < m_iAddonInfoToggleCurrent; i++)
678       activeClient++;
679
680     long long kBTotal = 0;
681     long long kBUsed  = 0;
682
683     if (activeClient->second->GetDriveSpace(&kBTotal, &kBUsed) == PVR_ERROR_NO_ERROR)
684     {
685       kBTotal /= 1024; // Convert to MBytes
686       kBUsed /= 1024;  // Convert to MBytes
687       strBackendDiskspace = StringUtils::Format("%s %.1f GByte - %s: %.1f GByte",
688           g_localizeStrings.Get(20161).c_str(), (float) kBTotal / 1024, g_localizeStrings.Get(20162).c_str(), (float) kBUsed / 1024);
689     }
690     else
691     {
692       strBackendDiskspace = g_localizeStrings.Get(19055);
693     }
694
695     int NumChannels = activeClient->second->GetChannelsAmount();
696     if (NumChannels >= 0)
697       strBackendChannels = StringUtils::Format("%i", NumChannels);
698     else
699       strBackendChannels = g_localizeStrings.Get(161);
700
701     int NumTimers = activeClient->second->GetTimersAmount();
702     if (NumTimers >= 0)
703       strBackendTimers = StringUtils::Format("%i", NumTimers);
704     else
705       strBackendTimers = g_localizeStrings.Get(161);
706
707     int NumRecordings = activeClient->second->GetRecordingsAmount();
708     if (NumRecordings >= 0)
709       strBackendRecordings = StringUtils::Format("%i", NumRecordings);
710     else
711       strBackendRecordings = g_localizeStrings.Get(161);
712
713     strBackendName    = activeClient->second->GetBackendName();
714     strBackendVersion = activeClient->second->GetBackendVersion();
715     strBackendHost    = activeClient->second->GetConnectionString();
716   }
717
718   CSingleLock lock(m_critSection);
719   m_strBackendName         = strBackendName;
720   m_strBackendVersion      = strBackendVersion;
721   m_strBackendHost         = strBackendHost;
722   m_strBackendDiskspace    = strBackendDiskspace;
723   m_strBackendTimers       = strBackendTimers;
724   m_strBackendRecordings   = strBackendRecordings;
725   m_strBackendChannels     = strBackendChannels;
726   m_iActiveClients         = iActiveClients;
727 }
728
729 void CPVRGUIInfo::UpdateTimersCache(void)
730 {
731   int iTimerAmount          = g_PVRTimers->AmountActiveTimers();
732   int iRecordingTimerAmount = g_PVRTimers->AmountActiveRecordings();
733
734   {
735     CSingleLock lock(m_critSection);
736     m_iTimerAmount          = iTimerAmount;
737     m_iRecordingTimerAmount = iRecordingTimerAmount;
738     m_iTimerInfoToggleStart = 0;
739   }
740
741   UpdateTimersToggle();
742 }
743
744 void CPVRGUIInfo::UpdateNextTimer(void)
745 {
746   CStdString strNextRecordingTitle;
747   CStdString strNextRecordingChannelName;
748   CStdString strNextRecordingChannelIcon;
749   CStdString strNextRecordingTime;
750   CStdString strNextTimerInfo;
751
752   CFileItemPtr tag = g_PVRTimers->GetNextActiveTimer();
753   if (tag && tag->HasPVRTimerInfoTag())
754   {
755     CPVRTimerInfoTag *timer = tag->GetPVRTimerInfoTag();
756     strNextRecordingTitle = StringUtils::Format("%s",       timer->Title().c_str());
757     strNextRecordingChannelName = StringUtils::Format("%s", timer->ChannelName().c_str());
758     strNextRecordingChannelIcon = StringUtils::Format("%s", timer->ChannelIcon().c_str());
759     strNextRecordingTime = StringUtils::Format("%s",        timer->StartAsLocalTime().GetAsLocalizedDateTime(false, false).c_str());
760
761     strNextTimerInfo = StringUtils::Format("%s %s %s %s",
762         g_localizeStrings.Get(19106).c_str(),
763         timer->StartAsLocalTime().GetAsLocalizedDate(true).c_str(),
764         g_localizeStrings.Get(19107).c_str(),
765         timer->StartAsLocalTime().GetAsLocalizedTime("HH:mm", false).c_str());
766   }
767
768   CSingleLock lock(m_critSection);
769   m_strNextRecordingTitle       = strNextRecordingTitle;
770   m_strNextRecordingChannelName = strNextRecordingChannelName;
771   m_strNextRecordingChannelIcon = strNextRecordingChannelIcon;
772   m_strNextRecordingTime        = strNextRecordingTime;
773   m_strNextTimerInfo            = strNextTimerInfo;
774 }
775
776 void CPVRGUIInfo::UpdateTimersToggle(void)
777 {
778   if (!TimerInfoToggle())
779     return;
780
781   CStdString strActiveTimerTitle;
782   CStdString strActiveTimerChannelName;
783   CStdString strActiveTimerChannelIcon;
784   CStdString strActiveTimerTime;
785
786   /* safe to fetch these unlocked, since they're updated from the same thread as this one */
787   if (m_iRecordingTimerAmount > 0)
788   {
789     vector<CFileItemPtr> activeTags = g_PVRTimers->GetActiveRecordings();
790     if (m_iTimerInfoToggleCurrent < activeTags.size() && activeTags.at(m_iTimerInfoToggleCurrent)->HasPVRTimerInfoTag())
791     {
792       CPVRTimerInfoTag *tag = activeTags.at(m_iTimerInfoToggleCurrent)->GetPVRTimerInfoTag();
793       strActiveTimerTitle = StringUtils::Format("%s",       tag->Title().c_str());
794       strActiveTimerChannelName = StringUtils::Format("%s", tag->ChannelName().c_str());
795       strActiveTimerChannelIcon = StringUtils::Format("%s", tag->ChannelIcon().c_str());
796       strActiveTimerTime = StringUtils::Format("%s",        tag->StartAsLocalTime().GetAsLocalizedDateTime(false, false).c_str());
797     }
798   }
799
800   CSingleLock lock(m_critSection);
801   m_strActiveTimerTitle         = strActiveTimerTitle;
802   m_strActiveTimerChannelName   = strActiveTimerChannelName;
803   m_strActiveTimerChannelIcon   = strActiveTimerChannelIcon;
804   m_strActiveTimerTime          = strActiveTimerTime;
805 }
806
807 int CPVRGUIInfo::GetDuration(void) const
808 {
809   CSingleLock lock(m_critSection);
810   return m_iDuration;
811 }
812
813 int CPVRGUIInfo::GetStartTime(void) const
814 {
815   CSingleLock lock(m_critSection);
816   if (m_playingEpgTag)
817   {
818     /* Calculate here the position we have of the running live TV event.
819      * "position in ms" = ("current UTC" - "event start UTC") * 1000
820      */
821     CDateTime current = g_PVRClients->GetPlayingTime();
822     CDateTime start = m_playingEpgTag->StartAsUTC();
823     CDateTimeSpan time = current > start ? current - start : CDateTimeSpan(0, 0, 0, 0);
824     return (time.GetDays()   * 60 * 60 * 24
825          + time.GetHours()   * 60 * 60
826          + time.GetMinutes() * 60
827          + time.GetSeconds()) * 1000;
828   }
829   else
830   {
831     return 0;
832   }
833 }
834
835 void CPVRGUIInfo::ResetPlayingTag(void)
836 {
837   CSingleLock lock(m_critSection);
838   SAFE_DELETE(m_playingEpgTag);
839   m_iDuration = 0;
840 }
841
842 bool CPVRGUIInfo::GetPlayingTag(CEpgInfoTag &tag) const
843 {
844   bool bReturn(false);
845
846   CSingleLock lock(m_critSection);
847   if (m_playingEpgTag)
848   {
849     tag = *m_playingEpgTag;
850     bReturn = true;
851   }
852
853   return bReturn;
854 }
855
856 void CPVRGUIInfo::UpdatePlayingTag(void)
857 {
858   CPVRChannelPtr currentChannel;
859   CPVRRecording recording;
860   if (g_PVRManager.GetCurrentChannel(currentChannel))
861   {
862     CEpgInfoTag epgTag;
863     bool bHasEpgTag  = GetPlayingTag(epgTag);
864     CPVRChannelPtr channel;
865     if (bHasEpgTag)
866       channel = epgTag.ChannelTag();
867
868     if (!bHasEpgTag || !epgTag.IsActive() ||
869         !channel || *channel != *currentChannel)
870     {
871       CEpgInfoTag newTag;
872       {
873         CSingleLock lock(m_critSection);
874         ResetPlayingTag();
875         if (currentChannel->GetEPGNow(newTag))
876         {
877           m_playingEpgTag = new CEpgInfoTag(newTag);
878           m_iDuration     = m_playingEpgTag->GetDuration() * 1000;
879         }
880       }
881       g_PVRManager.UpdateCurrentFile();
882     }
883   }
884   else if (g_PVRClients->GetPlayingRecording(recording))
885   {
886     ResetPlayingTag();
887     m_iDuration = recording.GetDuration() * 1000;
888   }
889 }