[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / epg / EpgInfoTag.cpp
1 /*
2  *      Copyright (C) 2012-2013 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, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "guilib/LocalizeStrings.h"
22 #include "Epg.h"
23 #include "EpgInfoTag.h"
24 #include "EpgContainer.h"
25 #include "EpgDatabase.h"
26 #include "pvr/channels/PVRChannelGroupsContainer.h"
27 #include "pvr/timers/PVRTimers.h"
28 #include "pvr/PVRManager.h"
29 #include "settings/AdvancedSettings.h"
30 #include "settings/GUISettings.h"
31 #include "utils/log.h"
32 #include "utils/Variant.h"
33 #include "addons/include/xbmc_pvr_types.h"
34
35 using namespace std;
36 using namespace EPG;
37 using namespace PVR;
38
39 CEpgInfoTag::CEpgInfoTag(void) :
40     m_bNotify(false),
41     m_bChanged(false),
42     m_iBroadcastId(-1),
43     m_iGenreType(0),
44     m_iGenreSubType(0),
45     m_iParentalRating(0),
46     m_iStarRating(0),
47     m_iSeriesNumber(0),
48     m_iEpisodeNumber(0),
49     m_iEpisodePart(0),
50     m_iUniqueBroadcastID(-1),
51     m_epg(NULL)
52 {
53   CPVRChannelPtr emptyChannel;
54   m_pvrChannel = emptyChannel;
55
56   CPVRTimerInfoTagPtr emptyTimer;
57   m_timer = emptyTimer;
58 }
59
60 CEpgInfoTag::CEpgInfoTag(CEpg *epg, PVR::CPVRChannelPtr pvrChannel, const CStdString &strTableName /* = StringUtils::EmptyString */, const CStdString &strIconPath /* = StringUtils::EmptyString */) :
61     m_bNotify(false),
62     m_bChanged(false),
63     m_iBroadcastId(-1),
64     m_iGenreType(0),
65     m_iGenreSubType(0),
66     m_iParentalRating(0),
67     m_iStarRating(0),
68     m_iSeriesNumber(0),
69     m_iEpisodeNumber(0),
70     m_iEpisodePart(0),
71     m_iUniqueBroadcastID(-1),
72     m_strIconPath(strIconPath),
73     m_epg(epg),
74     m_pvrChannel(pvrChannel)
75 {
76   CPVRTimerInfoTagPtr emptyTimer;
77   m_timer = emptyTimer;
78 }
79
80 CEpgInfoTag::CEpgInfoTag(const EPG_TAG &data) :
81     m_bNotify(false),
82     m_bChanged(false),
83     m_iBroadcastId(-1),
84     m_iGenreType(0),
85     m_iGenreSubType(0),
86     m_iParentalRating(0),
87     m_iStarRating(0),
88     m_iSeriesNumber(0),
89     m_iEpisodeNumber(0),
90     m_iEpisodePart(0),
91     m_iUniqueBroadcastID(-1),
92     m_epg(NULL)
93 {
94   CPVRChannelPtr emptyChannel;
95   m_pvrChannel = emptyChannel;
96
97   CPVRTimerInfoTagPtr emptyTimer;
98   m_timer = emptyTimer;
99
100   Update(data);
101 }
102
103 CEpgInfoTag::CEpgInfoTag(const CEpgInfoTag &tag) :
104     m_bNotify(tag.m_bNotify),
105     m_bChanged(tag.m_bChanged),
106     m_iBroadcastId(tag.m_iBroadcastId),
107     m_iGenreType(tag.m_iGenreType),
108     m_iGenreSubType(tag.m_iGenreSubType),
109     m_iParentalRating(tag.m_iParentalRating),
110     m_iStarRating(tag.m_iStarRating),
111     m_iSeriesNumber(tag.m_iSeriesNumber),
112     m_iEpisodeNumber(tag.m_iEpisodeNumber),
113     m_iEpisodePart(tag.m_iEpisodePart),
114     m_iUniqueBroadcastID(tag.m_iUniqueBroadcastID),
115     m_strTitle(tag.m_strTitle),
116     m_strPlotOutline(tag.m_strPlotOutline),
117     m_strPlot(tag.m_strPlot),
118     m_genre(tag.m_genre),
119     m_strEpisodeName(tag.m_strEpisodeName),
120     m_strIconPath(tag.m_strIconPath),
121     m_strFileNameAndPath(tag.m_strFileNameAndPath),
122     m_startTime(tag.m_startTime),
123     m_endTime(tag.m_endTime),
124     m_firstAired(tag.m_firstAired),
125     m_timer(tag.m_timer),
126     m_epg(tag.m_epg),
127     m_pvrChannel(tag.m_pvrChannel)
128 {
129 }
130
131 CEpgInfoTag::~CEpgInfoTag()
132 {
133   ClearTimer();
134 }
135
136 bool CEpgInfoTag::operator ==(const CEpgInfoTag& right) const
137 {
138   if (this == &right) return true;
139
140   CSingleLock lock(m_critSection);
141   return (m_bNotify            == right.m_bNotify &&
142           m_bChanged           == right.m_bChanged &&
143           m_iBroadcastId       == right.m_iBroadcastId &&
144           m_iGenreType         == right.m_iGenreType &&
145           m_iGenreSubType      == right.m_iGenreSubType &&
146           m_iParentalRating    == right.m_iParentalRating &&
147           m_firstAired         == right.m_firstAired &&
148           m_iStarRating        == right.m_iStarRating &&
149           m_iSeriesNumber      == right.m_iSeriesNumber &&
150           m_iEpisodeNumber     == right.m_iEpisodeNumber &&
151           m_iEpisodePart       == right.m_iEpisodePart &&
152           m_iUniqueBroadcastID == right.m_iUniqueBroadcastID &&
153           m_strTitle           == right.m_strTitle &&
154           m_strPlotOutline     == right.m_strPlotOutline &&
155           m_strPlot            == right.m_strPlot &&
156           m_genre              == right.m_genre &&
157           m_strEpisodeName     == right.m_strEpisodeName &&
158           m_strIconPath        == right.m_strIconPath &&
159           m_strFileNameAndPath == right.m_strFileNameAndPath &&
160           m_startTime          == right.m_startTime &&
161           m_endTime            == right.m_endTime &&
162           m_pvrChannel         == right.m_pvrChannel);
163 }
164
165 bool CEpgInfoTag::operator !=(const CEpgInfoTag& right) const
166 {
167   if (this == &right) return false;
168
169   return !(*this == right);
170 }
171
172 CEpgInfoTag &CEpgInfoTag::operator =(const CEpgInfoTag &other)
173 {
174   CSingleLock lock(other.m_critSection);
175
176   m_bNotify            = other.m_bNotify;
177   m_bChanged           = other.m_bChanged;
178   m_iBroadcastId       = other.m_iBroadcastId;
179   m_iGenreType         = other.m_iGenreType;
180   m_iGenreSubType      = other.m_iGenreSubType;
181   m_iParentalRating    = other.m_iParentalRating;
182   m_iStarRating        = other.m_iStarRating;
183   m_iSeriesNumber      = other.m_iSeriesNumber;
184   m_iEpisodeNumber     = other.m_iEpisodeNumber;
185   m_iEpisodePart       = other.m_iEpisodePart;
186   m_iUniqueBroadcastID = other.m_iUniqueBroadcastID;
187   m_strTitle           = other.m_strTitle;
188   m_strPlotOutline     = other.m_strPlotOutline;
189   m_strPlot            = other.m_strPlot;
190   m_genre              = other.m_genre;
191   m_strEpisodeName     = other.m_strEpisodeName;
192   m_strIconPath        = other.m_strIconPath;
193   m_strFileNameAndPath = other.m_strFileNameAndPath;
194   m_startTime          = other.m_startTime;
195   m_endTime            = other.m_endTime;
196   m_firstAired         = other.m_firstAired;
197   m_timer              = other.m_timer;
198   m_epg                = other.m_epg;
199   m_pvrChannel         = other.m_pvrChannel;
200
201   return *this;
202 }
203
204 void CEpgInfoTag::Serialize(CVariant &value) const
205 {
206   value["rating"] = m_iStarRating;
207   value["title"] = m_strTitle;
208   value["plotoutline"] = m_strPlotOutline;
209   value["plot"] = m_strPlot;
210   value["genre"] = m_genre;
211   value["filenameandpath"] = m_strFileNameAndPath;
212   value["starttime"] = m_startTime.IsValid() ? m_startTime.GetAsDBDateTime() : StringUtils::EmptyString;
213   value["endtime"] = m_endTime.IsValid() ? m_endTime.GetAsDBDateTime() : StringUtils::EmptyString;
214   value["runtime"] = StringUtils::Format("%d", GetDuration() / 60);
215   value["firstaired"] = m_firstAired.IsValid() ? m_firstAired.GetAsDBDate() : StringUtils::EmptyString;
216 }
217
218 bool CEpgInfoTag::Changed(void) const
219 {
220   CSingleLock lock(m_critSection);
221   return m_bChanged;
222 }
223
224 bool CEpgInfoTag::IsActive(void) const
225 {
226   CDateTime now = CDateTime::GetUTCDateTime();
227   CSingleLock lock(m_critSection);
228   return (m_startTime <= now && m_endTime > now);
229 }
230
231 bool CEpgInfoTag::WasActive(void) const
232 {
233   CDateTime now = CDateTime::GetUTCDateTime();
234   CSingleLock lock(m_critSection);
235   return (m_endTime < now);
236 }
237
238 bool CEpgInfoTag::InTheFuture(void) const
239 {
240   CDateTime now = CDateTime::GetUTCDateTime();
241   CSingleLock lock(m_critSection);
242   return (m_startTime > now);
243 }
244
245 float CEpgInfoTag::ProgressPercentage(void) const
246 {
247   float fReturn(0);
248   int iDuration;
249   time_t currentTime, startTime, endTime;
250   CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(currentTime);
251
252   CSingleLock lock(m_critSection);
253   m_startTime.GetAsTime(startTime);
254   m_endTime.GetAsTime(endTime);
255   iDuration = endTime - startTime > 0 ? endTime - startTime : 3600;
256
257   if (currentTime >= startTime && currentTime <= endTime)
258     fReturn = ((float) currentTime - startTime) / iDuration * 100;
259   else if (currentTime > endTime)
260     fReturn = 100;
261
262   return fReturn;
263 }
264
265 int CEpgInfoTag::Progress(void) const
266 {
267   int iDuration;
268   time_t currentTime, startTime;
269   CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(currentTime);
270
271   CSingleLock lock(m_critSection);
272   m_startTime.GetAsTime(startTime);
273   iDuration = currentTime - startTime;
274   if (iDuration <= 0)
275     return 0;
276
277   return iDuration;
278 }
279
280 CEpgInfoTagPtr CEpgInfoTag::GetNextEvent(void) const
281 {
282   return GetTable()->GetNextEvent(*this);
283 }
284
285 CEpgInfoTagPtr CEpgInfoTag::GetPreviousEvent(void) const
286 {
287   return GetTable()->GetPreviousEvent(*this);
288 }
289
290 void CEpgInfoTag::SetUniqueBroadcastID(int iUniqueBroadcastID)
291 {
292   bool bUpdate(false);
293   {
294     CSingleLock lock(m_critSection);
295     if (m_iUniqueBroadcastID != iUniqueBroadcastID)
296     {
297       m_iUniqueBroadcastID = iUniqueBroadcastID;
298       m_bChanged = true;
299       bUpdate = true;
300     }
301   }
302   if (bUpdate)
303     UpdatePath();
304 }
305
306 int CEpgInfoTag::UniqueBroadcastID(void) const
307 {
308   CSingleLock lock(m_critSection);
309   return m_iUniqueBroadcastID;
310 }
311
312 void CEpgInfoTag::SetBroadcastId(int iId)
313 {
314   bool bUpdate(false);
315   {
316     CSingleLock lock(m_critSection);
317     if (m_iBroadcastId != iId)
318     {
319       m_iBroadcastId = iId;
320       m_bChanged = true;
321       bUpdate = true;
322     }
323   }
324   if (bUpdate)
325     UpdatePath();
326 }
327
328 int CEpgInfoTag::BroadcastId(void) const
329 {
330   CSingleLock lock(m_critSection);
331   return m_iBroadcastId;
332 }
333
334 CDateTime CEpgInfoTag::StartAsUTC(void) const
335 {
336   CSingleLock lock(m_critSection);
337   return m_startTime;
338 }
339
340 CDateTime CEpgInfoTag::StartAsLocalTime(void) const
341 {
342   CDateTime retVal;
343   CSingleLock lock(m_critSection);
344   retVal.SetFromUTCDateTime(m_startTime);
345   return retVal;
346 }
347
348 void CEpgInfoTag::SetStartFromUTC(const CDateTime &start)
349 {
350   bool bUpdate(false);
351   {
352     CSingleLock lock(m_critSection);
353     if (m_startTime != start)
354     {
355       m_startTime = start;
356       m_bChanged = true;
357       bUpdate = true;
358     }
359   }
360   if (bUpdate)
361     UpdatePath();
362 }
363
364 void CEpgInfoTag::SetStartFromLocalTime(const CDateTime &start)
365 {
366   CDateTime tmp = start.GetAsUTCDateTime();
367   SetStartFromUTC(tmp);
368 }
369
370 CDateTime CEpgInfoTag::EndAsUTC(void) const
371 {
372   CDateTime retVal;
373   CSingleLock lock(m_critSection);
374   retVal = m_endTime;
375   return retVal;
376 }
377
378 CDateTime CEpgInfoTag::EndAsLocalTime(void) const
379 {
380   CDateTime retVal;
381   CSingleLock lock(m_critSection);
382   retVal.SetFromUTCDateTime(m_endTime);
383   return retVal;
384 }
385
386 void CEpgInfoTag::SetEndFromUTC(const CDateTime &end)
387 {
388   bool bUpdate(false);
389   {
390     CSingleLock lock(m_critSection);
391     if (m_endTime != end)
392     {
393       m_endTime = end;
394       m_bChanged = true;
395       bUpdate = true;
396     }
397   }
398   if (bUpdate)
399     UpdatePath();
400 }
401
402 void CEpgInfoTag::SetEndFromLocalTime(const CDateTime &end)
403 {
404   CDateTime tmp = end.GetAsUTCDateTime();
405   SetEndFromUTC(tmp);
406 }
407
408 int CEpgInfoTag::GetDuration(void) const
409 {
410   time_t start, end;
411   CSingleLock lock(m_critSection);
412   m_startTime.GetAsTime(start);
413   m_endTime.GetAsTime(end);
414   return end - start > 0 ? end - start : 3600;
415 }
416
417 void CEpgInfoTag::SetTitle(const CStdString &strTitle)
418 {
419   bool bUpdate(false);
420   {
421     CSingleLock lock(m_critSection);
422     if (m_strTitle != strTitle)
423     {
424       m_strTitle = strTitle;
425       m_bChanged = true;
426       bUpdate = true;
427     }
428   }
429   if (bUpdate)
430     UpdatePath();
431 }
432
433 CStdString CEpgInfoTag::Title(bool bOverrideParental /* = false */) const
434 {
435   CStdString strTitle;
436   bool bParentalLocked(false);
437
438   {
439     CSingleLock lock(m_critSection);
440     strTitle = m_strTitle;
441     if (m_pvrChannel)
442       bParentalLocked = g_PVRManager.IsParentalLocked(*m_pvrChannel);
443   }
444
445   if (!bOverrideParental && bParentalLocked)
446     strTitle = g_localizeStrings.Get(19266); // parental locked
447   else if (strTitle.empty() && !g_guiSettings.GetBool("epg.hidenoinfoavailable"))
448     strTitle = g_localizeStrings.Get(19055); // no information available
449
450   return strTitle;
451 }
452
453 void CEpgInfoTag::SetPlotOutline(const CStdString &strPlotOutline)
454 {
455   bool bUpdate(false);
456   {
457     CSingleLock lock(m_critSection);
458     if (m_strPlotOutline != strPlotOutline)
459     {
460       m_strPlotOutline = strPlotOutline;
461       m_bChanged = true;
462       bUpdate = true;
463     }
464   }
465   if (bUpdate)
466     UpdatePath();
467 }
468
469 CStdString CEpgInfoTag::PlotOutline(bool bOverrideParental /* = false */) const
470 {
471   CStdString retVal;
472   CSingleLock lock(m_critSection);
473   if (bOverrideParental || !m_pvrChannel || !g_PVRManager.IsParentalLocked(*m_pvrChannel))
474     retVal = m_strPlotOutline;
475
476   return retVal;
477 }
478
479 void CEpgInfoTag::SetPlot(const CStdString &strPlot)
480 {
481   bool bUpdate(false);
482   {
483     CSingleLock lock(m_critSection);
484     bUpdate = !m_strPlot.Equals(strPlot);
485     m_bChanged |= bUpdate;
486     m_strPlot = strPlot;
487   }
488   if (bUpdate)
489     UpdatePath();
490 }
491
492 CStdString CEpgInfoTag::Plot(bool bOverrideParental /* = false */) const
493 {
494   CStdString retVal;
495   CSingleLock lock(m_critSection);
496   if (bOverrideParental || !m_pvrChannel || !g_PVRManager.IsParentalLocked(*m_pvrChannel))
497     retVal = m_strPlot;
498
499   return retVal;
500 }
501
502 void CEpgInfoTag::SetGenre(int iID, int iSubID, const char* strGenre)
503 {
504   bool bUpdate(false);
505   {
506     CSingleLock lock(m_critSection);
507     if (m_iGenreType != iID || m_iGenreSubType != iSubID)
508     {
509       m_iGenreType    = iID;
510       m_iGenreSubType = iSubID;
511       if ((iID == EPG_GENRE_USE_STRING) && (strGenre != NULL) && (strlen(strGenre) > 0))
512       {
513         /* Type and sub type are not given. No EPG color coding possible
514          * Use the provided genre description as backup. */
515         m_genre = StringUtils::Split(strGenre, g_advancedSettings.m_videoItemSeparator);
516       }
517       else
518       {
519         /* Determine the genre description from the type and subtype IDs */
520         m_genre = StringUtils::Split(CEpg::ConvertGenreIdToString(iID, iSubID), g_advancedSettings.m_videoItemSeparator);
521       }
522       m_bChanged = true;
523       bUpdate = true;
524     }
525   }
526   if (bUpdate)
527     UpdatePath();
528 }
529
530 int CEpgInfoTag::GenreType(void) const
531 {
532   CSingleLock lock(m_critSection);
533   return m_iGenreType;
534 }
535
536 int CEpgInfoTag::GenreSubType(void) const
537 {
538   CSingleLock lock(m_critSection);
539   return m_iGenreSubType;
540 }
541
542 const vector<string> CEpgInfoTag::Genre(void) const
543 {
544   vector<string> retVal;
545   CSingleLock lock(m_critSection);
546   retVal = m_genre;
547   return retVal;
548 }
549
550 CDateTime CEpgInfoTag::FirstAiredAsUTC(void) const
551 {
552   CDateTime retVal;
553   CSingleLock lock(m_critSection);
554   retVal = m_firstAired;
555   return retVal;
556 }
557
558 CDateTime CEpgInfoTag::FirstAiredAsLocalTime(void) const
559 {
560   CDateTime retVal;
561   CSingleLock lock(m_critSection);
562   retVal.SetFromUTCDateTime(m_firstAired);
563   return retVal;
564 }
565
566 void CEpgInfoTag::SetFirstAiredFromUTC(const CDateTime &firstAired)
567 {
568   bool bUpdate(false);
569   {
570     CSingleLock lock(m_critSection);
571     if (m_firstAired != firstAired)
572     {
573       m_firstAired = firstAired;
574       m_bChanged = true;
575       bUpdate = true;
576     }
577   }
578   if (bUpdate)
579     UpdatePath();
580 }
581
582 void CEpgInfoTag::SetFirstAiredFromLocalTime(const CDateTime &firstAired)
583 {
584   CDateTime tmp = firstAired.GetAsUTCDateTime();
585   SetFirstAiredFromUTC(tmp);
586 }
587
588 void CEpgInfoTag::SetParentalRating(int iParentalRating)
589 {
590   bool bUpdate(false);
591   {
592     CSingleLock lock(m_critSection);
593     if (m_iParentalRating != iParentalRating)
594     {
595       m_iParentalRating = iParentalRating;
596       m_bChanged = true;
597       bUpdate = true;
598     }
599   }
600   if (bUpdate)
601     UpdatePath();
602 }
603
604 int CEpgInfoTag::ParentalRating(void) const
605 {
606   CSingleLock lock(m_critSection);
607   return m_iParentalRating;
608 }
609
610 void CEpgInfoTag::SetStarRating(int iStarRating)
611 {
612   bool bUpdate(false);
613   {
614     CSingleLock lock(m_critSection);
615     if (m_iStarRating != iStarRating)
616     {
617       m_iStarRating = iStarRating;
618       m_bChanged = true;
619       bUpdate = true;
620     }
621   }
622   if (bUpdate)
623     UpdatePath();
624 }
625
626 int CEpgInfoTag::StarRating(void) const
627 {
628   CSingleLock lock(m_critSection);
629   return m_iStarRating;
630 }
631
632 void CEpgInfoTag::SetNotify(bool bNotify)
633 {
634   bool bUpdate(false);
635   {
636     CSingleLock lock(m_critSection);
637     if (m_bNotify != bNotify)
638     {
639       m_bNotify = bNotify;
640       m_bChanged = true;
641       bUpdate = true;
642     }
643   }
644   if (bUpdate)
645     UpdatePath();
646 }
647
648 bool CEpgInfoTag::Notify(void) const
649 {
650   CSingleLock lock(m_critSection);
651   return m_bNotify;
652 }
653
654 void CEpgInfoTag::SetSeriesNum(int iSeriesNum)
655 {
656   bool bUpdate(false);
657   {
658     CSingleLock lock(m_critSection);
659     if (m_iSeriesNumber != iSeriesNum)
660     {
661       m_iSeriesNumber = iSeriesNum;
662       m_bChanged = true;
663       bUpdate = true;
664     }
665   }
666   if (bUpdate)
667     UpdatePath();
668 }
669
670 int CEpgInfoTag::SeriesNum(void) const
671 {
672   CSingleLock lock(m_critSection);
673   return m_iSeriesNumber;
674 }
675
676 void CEpgInfoTag::SetEpisodeNum(int iEpisodeNum)
677 {
678   bool bUpdate(false);
679   {
680     CSingleLock lock(m_critSection);
681     if (m_iEpisodeNumber != iEpisodeNum)
682     {
683       m_iEpisodeNumber = iEpisodeNum;
684       m_bChanged = true;
685       bUpdate = true;
686     }
687   }
688   if (bUpdate)
689     UpdatePath();
690 }
691
692 int CEpgInfoTag::EpisodeNum(void) const
693 {
694   CSingleLock lock(m_critSection);
695   return m_iEpisodeNumber;
696 }
697
698 void CEpgInfoTag::SetEpisodePart(int iEpisodePart)
699 {
700   bool bUpdate(false);
701   {
702     CSingleLock lock(m_critSection);
703     if (m_iEpisodePart != iEpisodePart)
704     {
705       m_iEpisodePart = iEpisodePart;
706       m_bChanged = true;
707       bUpdate = true;
708     }
709   }
710   if (bUpdate)
711     UpdatePath();
712 }
713
714 int CEpgInfoTag::EpisodePart(void) const
715 {
716   CSingleLock lock(m_critSection);
717   return m_iEpisodePart;
718 }
719
720 void CEpgInfoTag::SetEpisodeName(const CStdString &strEpisodeName)
721 {
722   bool bUpdate(false);
723   {
724     CSingleLock lock(m_critSection);
725     if (m_strEpisodeName != strEpisodeName)
726     {
727       m_strEpisodeName = strEpisodeName;
728       m_bChanged = true;
729       bUpdate = true;
730     }
731   }
732   if (bUpdate)
733     UpdatePath();
734 }
735
736 CStdString CEpgInfoTag::EpisodeName(void) const
737 {
738   CStdString retVal;
739   CSingleLock lock(m_critSection);
740   retVal = m_strEpisodeName;
741   return retVal;
742 }
743
744 void CEpgInfoTag::SetIcon(const CStdString &strIconPath)
745 {
746   bool bUpdate(false);
747   {
748     CSingleLock lock(m_critSection);
749     if (m_strIconPath != strIconPath)
750     {
751       m_strIconPath = strIconPath;
752       m_bChanged = true;
753       bUpdate = true;
754     }
755   }
756   if (bUpdate)
757     UpdatePath();
758 }
759
760 CStdString CEpgInfoTag::Icon(void) const
761 {
762   CStdString retVal;
763
764   CSingleLock lock(m_critSection);
765   retVal = m_strIconPath;
766   return retVal;
767 }
768
769 void CEpgInfoTag::SetPath(const CStdString &strFileNameAndPath)
770 {
771   CSingleLock lock(m_critSection);
772   if (m_strFileNameAndPath != strFileNameAndPath)
773   {
774     m_strFileNameAndPath = strFileNameAndPath;
775     m_bChanged = true;
776   }
777 }
778
779 CStdString CEpgInfoTag::Path(void) const
780 {
781   string retVal;
782   CSingleLock lock(m_critSection);
783   retVal = m_strFileNameAndPath;
784   return retVal;
785 }
786
787 //void CEpgInfoTag::SetTimer(CPVRTimerInfoTagPtr newTimer)
788 //{
789 //  CPVRTimerInfoTagPtr oldTimer;
790 //  {
791 //    CSingleLock lock(m_critSection);
792 //    oldTimer = m_timer;
793 //    m_timer = newTimer;
794 //  }
795 //  if (oldTimer)
796 //    oldTimer->ClearEpgTag();
797 //}
798
799 bool CEpgInfoTag::HasTimer(void) const
800 {
801   CSingleLock lock(m_critSection);
802   return m_timer != NULL;
803 }
804
805 CPVRTimerInfoTagPtr CEpgInfoTag::Timer(void) const
806 {
807   CSingleLock lock(m_critSection);
808   return m_timer;
809 }
810
811 void CEpgInfoTag::SetPVRChannel(PVR::CPVRChannelPtr channel)
812 {
813   CSingleLock lock(m_critSection);
814   m_pvrChannel = channel;
815 }
816
817 bool CEpgInfoTag::HasPVRChannel(void) const
818 {
819   CSingleLock lock(m_critSection);
820   return m_pvrChannel != NULL;
821 }
822
823 int CEpgInfoTag::PVRChannelNumber(void) const
824 {
825   CSingleLock lock(m_critSection);
826   return m_pvrChannel ? m_pvrChannel->ChannelNumber() : -1;
827 }
828
829 CStdString CEpgInfoTag::PVRChannelName(void) const
830 {
831   CStdString strReturn;
832   CSingleLock lock(m_critSection);
833   if (m_pvrChannel)
834     strReturn = m_pvrChannel->ChannelName();
835   return strReturn;
836 }
837
838 const PVR::CPVRChannelPtr CEpgInfoTag::ChannelTag(void) const
839 {
840   CSingleLock lock(m_critSection);
841   return m_pvrChannel;
842 }
843
844 void CEpgInfoTag::Update(const EPG_TAG &tag)
845 {
846   CSingleLock lock(m_critSection);
847   SetStartFromUTC(tag.startTime + g_advancedSettings.m_iPVRTimeCorrection);
848   SetEndFromUTC(tag.endTime + g_advancedSettings.m_iPVRTimeCorrection);
849   SetTitle(tag.strTitle);
850   SetPlotOutline(tag.strPlotOutline);
851   SetPlot(tag.strPlot);
852   SetGenre(tag.iGenreType, tag.iGenreSubType, tag.strGenreDescription);
853   SetParentalRating(tag.iParentalRating);
854   SetUniqueBroadcastID(tag.iUniqueBroadcastId);
855   SetNotify(tag.bNotify);
856   SetFirstAiredFromUTC(tag.firstAired + g_advancedSettings.m_iPVRTimeCorrection);
857   SetEpisodeNum(tag.iEpisodeNumber);
858   SetEpisodePart(tag.iEpisodePartNumber);
859   SetEpisodeName(tag.strEpisodeName);
860   SetStarRating(tag.iStarRating);
861   SetIcon(tag.strIconPath);
862 }
863
864 bool CEpgInfoTag::Update(const CEpgInfoTag &tag, bool bUpdateBroadcastId /* = true */)
865 {
866   bool bChanged(false);
867   {
868     CSingleLock lock(m_critSection);
869     bChanged = (
870         m_strTitle           != tag.m_strTitle ||
871         m_strPlotOutline     != tag.m_strPlotOutline ||
872         m_strPlot            != tag.m_strPlot ||
873         m_startTime          != tag.m_startTime ||
874         m_endTime            != tag.m_endTime ||
875         m_iGenreType         != tag.m_iGenreType ||
876         m_iGenreSubType      != tag.m_iGenreSubType ||
877         m_firstAired         != tag.m_firstAired ||
878         m_iParentalRating    != tag.m_iParentalRating ||
879         m_iStarRating        != tag.m_iStarRating ||
880         m_bNotify            != tag.m_bNotify ||
881         m_iEpisodeNumber     != tag.m_iEpisodeNumber ||
882         m_iEpisodePart       != tag.m_iEpisodePart ||
883         m_iSeriesNumber      != tag.m_iSeriesNumber ||
884         m_strEpisodeName     != tag.m_strEpisodeName ||
885         m_iUniqueBroadcastID != tag.m_iUniqueBroadcastID ||
886         EpgID()              != tag.EpgID() ||
887         m_pvrChannel         != tag.m_pvrChannel ||
888         m_genre              != tag.m_genre
889     );
890     if (bUpdateBroadcastId)
891       bChanged = bChanged || m_iBroadcastId != tag.m_iBroadcastId;
892
893     if (bChanged)
894     {
895       if (bUpdateBroadcastId)
896         m_iBroadcastId       = tag.m_iBroadcastId;
897
898       m_strTitle           = tag.m_strTitle;
899       m_strPlotOutline     = tag.m_strPlotOutline;
900       m_strPlot            = tag.m_strPlot;
901       m_startTime          = tag.m_startTime;
902       m_endTime            = tag.m_endTime;
903       m_iGenreType         = tag.m_iGenreType;
904       m_iGenreSubType      = tag.m_iGenreSubType;
905       m_epg                = tag.m_epg;
906       m_pvrChannel         = tag.m_pvrChannel;
907       if (m_iGenreType == EPG_GENRE_USE_STRING)
908       {
909         /* No type/subtype. Use the provided description */
910         m_genre = tag.m_genre;
911       }
912       else
913       {
914         /* Determine genre description by type/subtype */
915         m_genre = StringUtils::Split(CEpg::ConvertGenreIdToString(tag.m_iGenreType, tag.m_iGenreSubType), g_advancedSettings.m_videoItemSeparator);
916       }
917       m_firstAired         = tag.m_firstAired;
918       m_iParentalRating    = tag.m_iParentalRating;
919       m_iStarRating        = tag.m_iStarRating;
920       m_bNotify            = tag.m_bNotify;
921       m_iEpisodeNumber     = tag.m_iEpisodeNumber;
922       m_iEpisodePart       = tag.m_iEpisodePart;
923       m_iSeriesNumber      = tag.m_iSeriesNumber;
924       m_strEpisodeName     = tag.m_strEpisodeName;
925       m_iUniqueBroadcastID = tag.m_iUniqueBroadcastID;
926
927       m_bChanged = true;
928     }
929   }
930   if (bChanged)
931     UpdatePath();
932
933   return bChanged;
934 }
935
936 bool CEpgInfoTag::Persist(bool bSingleUpdate /* = true */)
937 {
938   bool bReturn = false;
939   CSingleLock lock(m_critSection);
940   if (!m_bChanged)
941     return true;
942
943 #if EPG_DEBUGGING
944   CLog::Log(LOGDEBUG, "Epg - %s - Infotag '%s' %s, persisting...", __FUNCTION__, m_strTitle.c_str(), m_iBroadcastId > 0 ? "has changes" : "is new");
945 #endif
946
947   CEpgDatabase *database = g_EpgContainer.GetDatabase();
948   if (!database || (bSingleUpdate && !database->IsOpen()))
949   {
950     CLog::Log(LOGERROR, "%s - could not open the database", __FUNCTION__);
951     return bReturn;
952   }
953
954   int iId = database->Persist(*this, bSingleUpdate);
955   if (iId >= 0)
956   {
957     bReturn = true;
958
959     if (iId > 0)
960     {
961       m_iBroadcastId = iId;
962       m_bChanged = false;
963     }
964   }
965
966   return bReturn;
967 }
968
969 void CEpgInfoTag::UpdatePath(void)
970 {
971   CStdString path;
972   {
973     CSingleLock lock(m_critSection);
974     path.Format("pvr://guide/%04i/%s.epg", EpgID(), m_startTime.GetAsDBDateTime().c_str());
975   }
976
977   SetPath(path);
978 }
979
980 const CEpg *CEpgInfoTag::GetTable() const
981 {
982   return m_epg;
983 }
984
985 const int CEpgInfoTag::EpgID(void) const
986 {
987   return m_epg ? m_epg->EpgID() : -1;
988 }
989
990 void CEpgInfoTag::SetTimer(CPVRTimerInfoTagPtr timer)
991 {
992   CSingleLock lock(m_critSection);
993   m_timer = timer;
994 }
995
996 void CEpgInfoTag::ClearTimer(void)
997 {
998   CPVRTimerInfoTagPtr previousTag;
999   {
1000     CSingleLock lock(m_critSection);
1001     previousTag = m_timer;
1002     CPVRTimerInfoTagPtr empty;
1003     m_timer = empty;
1004   }
1005
1006   if (previousTag)
1007     previousTag->ClearEpgTag();
1008 }