Example #1
0
CPVREpgInfoTagPtr CPVREpg::GetTagNow(bool bUpdateIfNeeded /* = true */) const
{
  CSingleLock lock(m_critSection);
  if (m_nowActiveStart.IsValid())
  {
    std::map<CDateTime, CPVREpgInfoTagPtr>::const_iterator it = m_tags.find(m_nowActiveStart);
    if (it != m_tags.end() && it->second->IsActive())
      return it->second;
  }

  if (bUpdateIfNeeded)
  {
    CPVREpgInfoTagPtr lastActiveTag;

    /* one of the first items will always match if the list is sorted */
    for (std::map<CDateTime, CPVREpgInfoTagPtr>::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
    {
      if (it->second->IsActive())
      {
        m_nowActiveStart = it->first;
        return it->second;
      }
      else if (it->second->WasActive())
        lastActiveTag = it->second;
    }

    /* there might be a gap between the last and next event. return the last if found and it ended not more than 5 minutes ago */
    if (lastActiveTag &&
        lastActiveTag->EndAsUTC() + CDateTimeSpan(0, 0, 5, 0) >= CDateTime::GetUTCDateTime())
      return lastActiveTag;
  }

  return CPVREpgInfoTagPtr();
}
Example #2
0
void CPVRChannel::Serialize(CVariant& value) const
{
  value["channelid"] = m_iChannelId;
  value["channeltype"] = m_bIsRadio ? "radio" : "tv";
  value["hidden"] = m_bIsHidden;
  value["locked"] = m_bIsLocked;
  value["icon"] = m_strIconPath;
  value["channel"]  = m_strChannelName;
  value["uniqueid"]  = m_iUniqueId;
  CDateTime lastPlayed(m_iLastWatched);
  value["lastplayed"] = lastPlayed.IsValid() ? lastPlayed.GetAsDBDate() : "";
  value["channelnumber"] = m_channelNumber.GetChannelNumber();
  value["subchannelnumber"] = m_channelNumber.GetSubChannelNumber();

  CPVREpgInfoTagPtr epg = GetEPGNow();
  if (epg)
  {
    // add the properties of the current EPG item to the main object
    epg->Serialize(value);
    // and add an extra sub-object with only the current EPG details
    epg->Serialize(value["broadcastnow"]);
  }

  epg = GetEPGNext();
  if (epg)
    epg->Serialize(value["broadcastnext"]);

  value["isrecording"] = false; // compat
}
Example #3
0
CPVRRecordingPtr CPVRRecordings::GetRecordingForEpgTag(const CPVREpgInfoTagPtr &epgTag) const
{
  if (!epgTag)
    return {};

  CSingleLock lock(m_critSection);

  for (const auto recording : m_recordings)
  {
    if (recording.second->IsDeleted())
      continue;

    if (recording.second->ClientID() != epgTag->ClientID())
      continue;

    if (recording.second->ChannelUid() != epgTag->UniqueChannelID())
      continue;

    unsigned int iEpgEvent = recording.second->BroadcastUid();
    if (iEpgEvent != EPG_TAG_INVALID_UID)
    {
      if (iEpgEvent == epgTag->UniqueBroadcastID())
        return recording.second;
    }
    else
    {
      if (recording.second->RecordingTimeAsUTC() <= epgTag->StartAsUTC() &&
          recording.second->EndTimeAsUTC() >= epgTag->EndAsUTC())
        return recording.second;
    }
  }

  return CPVRRecordingPtr();
}
Example #4
0
CPVRTimerInfoTagPtr CPVRTimers::GetTimerForEpgTag(const CPVREpgInfoTagPtr &epgTag) const
{
  if (epgTag)
  {
    CSingleLock lock(m_critSection);

    for (const auto &tagsEntry : m_tags)
    {
      for (const auto &timersEntry : tagsEntry.second)
      {
        if (timersEntry->IsTimerRule())
          continue;

        if (timersEntry->GetEpgInfoTag(false) == epgTag)
          return timersEntry;

        if (timersEntry->m_iClientChannelUid != PVR_CHANNEL_INVALID_UID &&
            timersEntry->m_iClientChannelUid == epgTag->UniqueChannelID())
        {
          if (timersEntry->UniqueBroadcastID() != EPG_TAG_INVALID_UID &&
              timersEntry->UniqueBroadcastID() == epgTag->UniqueBroadcastID())
            return timersEntry;

          if (timersEntry->m_bIsRadio == epgTag->IsRadio() &&
              timersEntry->StartAsUTC() <= epgTag->StartAsUTC() &&
              timersEntry->EndAsUTC() >= epgTag->EndAsUTC())
            return timersEntry;
        }
      }
    }
  }

  return CPVRTimerInfoTagPtr();
}
Example #5
0
int CPVRChannelGroup::GetEPGNowOrNext(CFileItemList &results, bool bGetNext) const
{
  int iInitialSize = results.Size();
  CPVREpgInfoTagPtr epgNext;
  CPVRChannelPtr channel;
  CSingleLock lock(m_critSection);

  for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end(); ++it)
  {
    channel = (*it).channel;
    CPVREpgPtr epg = channel->GetEPG();
    if (epg && !channel->IsHidden())
    {
      epgNext = bGetNext ? epg->GetTagNext() : epg->GetTagNow();
      if (epgNext)
      {
        CFileItemPtr entry(new CFileItem(epgNext));
        entry->SetLabel2(epgNext->StartAsLocalTime().GetAsLocalizedTime("", false));
        entry->SetPath(channel->Path());
        entry->SetArt("thumb", channel->IconPath());
        results.Add(entry);
      }
    }
  }

  return results.Size() - iInitialSize;
}
Example #6
0
int CPVRChannelGroup::GetEPGAll(CFileItemList &results, bool bIncludeChannelsWithoutEPG /* = false */) const
{
  int iInitialSize = results.Size();
  CPVREpgInfoTagPtr epgTag;
  CPVRChannelPtr channel;
  CSingleLock lock(m_critSection);

  for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end(); ++it)
  {
    channel = (*it).channel;
    if (!channel->IsHidden())
    {
      int iAdded = 0;

      CPVREpgPtr epg = channel->GetEPG();
      if (epg)
      {
        // XXX channel pointers aren't set in some occasions. this works around the issue, but is not very nice
        epg->SetChannel(channel);
        iAdded = epg->Get(results);
      }

      if (bIncludeChannelsWithoutEPG && iAdded == 0)
      {
        // Add dummy EPG tag associated with this channel
        epgTag = CPVREpgInfoTag::CreateDefaultTag();
        epgTag->SetChannel(channel);
        results.Add(CFileItemPtr(new CFileItem(epgTag)));
      }
    }
  }

  return results.Size() - iInitialSize;
}
void CGUIDialogPVRTimerSettings::InitializeTypesList()
{
  m_typeEntries.clear();

  // If timer is read-only or was created by a timer rule, only add current type, for information. Type can't be changed.
  if (m_timerType->IsReadOnly() || m_timerInfoTag->GetTimerRuleId() != PVR_TIMER_NO_PARENT)
  {
    m_typeEntries.insert(std::make_pair(0, m_timerType));
    return;
  }

  bool bFoundThisType(false);
  int idx(0);
  const std::vector<CPVRTimerTypePtr> types(CPVRTimerType::GetAllTypes());
  for (const auto &type : types)
  {
    // Type definition prohibits created of new instances.
    // But the dialog can act as a viewer for these types.
    if (type->ForbidsNewInstances())
      continue;

    // Read-only timers cannot be created using this dialog.
    // But the dialog can act as a viewer for read-only types.
    if (type->IsReadOnly())
      continue;

    // Drop TimerTypes that require EPGInfo, if none is populated
    if (type->RequiresEpgTagOnCreate() && !m_timerInfoTag->GetEpgInfoTag())
      continue;

    // Drop TimerTypes without 'Series' EPG attributes if none are set
    if (type->RequiresEpgSeriesOnCreate())
    {
      const CPVREpgInfoTagPtr epgTag(m_timerInfoTag->GetEpgInfoTag());
      if (epgTag && !epgTag->IsSeries())
        continue;
    }

    // Drop TimerTypes that forbid EPGInfo, if it is populated
    if (type->ForbidsEpgTagOnCreate() && m_timerInfoTag->GetEpgInfoTag())
      continue;

    // Drop TimerTypes that aren't rules if end time is in the past
    if (!type->IsTimerRule() && m_timerInfoTag->EndAsLocalTime() < CDateTime::GetCurrentDateTime())
      continue;

    if (!bFoundThisType && *type == *m_timerType)
      bFoundThisType = true;

    m_typeEntries.insert(std::make_pair(idx++, type));
  }

  if (!bFoundThisType)
    m_typeEntries.insert(std::make_pair(idx++, m_timerType));
}
Example #8
0
bool CPVREpgSearchFilter::MatchDuration(const CPVREpgInfoTagPtr &tag) const
{
  bool bReturn(true);

  if (m_iMinimumDuration != EPG_SEARCH_UNSET)
    bReturn = (tag->GetDuration() > m_iMinimumDuration * 60);

  if (bReturn && m_iMaximumDuration != EPG_SEARCH_UNSET)
    bReturn = (tag->GetDuration() < m_iMaximumDuration * 60);

  return bReturn;
}
Example #9
0
void CPVRRecording::OnDelete(void)
{
  if (m_iEpgEventId != EPG_TAG_INVALID_UID)
  {
    const CPVRChannelPtr channel(Channel());
    if (channel)
    {
      const CPVREpgInfoTagPtr epgTag(CServiceBroker::GetPVRManager().EpgContainer().GetTagById(channel, m_iEpgEventId));
      if (epgTag)
        epgTag->ClearRecording();
    }
  }
}
Example #10
0
bool CPVREpgSearchFilter::MatchGenre(const CPVREpgInfoTagPtr &tag) const
{
  bool bReturn(true);

  if (m_iGenreType != EPG_SEARCH_UNSET)
  {
    bool bIsUnknownGenre(tag->GenreType() > EPG_EVENT_CONTENTMASK_USERDEFINED ||
                         tag->GenreType() < EPG_EVENT_CONTENTMASK_MOVIEDRAMA);
    bReturn = ((m_bIncludeUnknownGenres && bIsUnknownGenre) || tag->GenreType() == m_iGenreType);
  }

  return bReturn;
}
Example #11
0
bool CPVREpgSearchFilter::MatchSearchTerm(const CPVREpgInfoTagPtr &tag) const
{
  bool bReturn(true);

  if (!m_strSearchTerm.empty())
  {
    CTextSearch search(m_strSearchTerm, m_bIsCaseSensitive, SEARCH_DEFAULT_OR);
    bReturn = search.Search(tag->Title()) ||
              search.Search(tag->PlotOutline()) ||
              (m_bSearchInDescription && search.Search(tag->Plot()));
  }

  return bReturn;
}
Example #12
0
int CPVREpgSearchFilter::RemoveDuplicates(CFileItemList &results)
{
  unsigned int iSize = results.Size();

  for (unsigned int iResultPtr = 0; iResultPtr < iSize; iResultPtr++)
  {
    const CPVREpgInfoTagPtr epgentry_1(results.Get(iResultPtr)->GetEPGInfoTag());
    if (!epgentry_1)
      continue;

    for (unsigned int iTagPtr = 0; iTagPtr < iSize; iTagPtr++)
    {
      if (iResultPtr == iTagPtr)
        continue;

      const CPVREpgInfoTagPtr epgentry_2(results.Get(iTagPtr)->GetEPGInfoTag());
      if (!epgentry_2)
        continue;

      if (epgentry_1->Title()       != epgentry_2->Title() ||
          epgentry_1->Plot()        != epgentry_2->Plot() ||
          epgentry_1->PlotOutline() != epgentry_2->PlotOutline())
        continue;

      results.Remove(iTagPtr);
      iResultPtr--;
      iTagPtr--;
      iSize--;
    }
  }

  return iSize;
}
Example #13
0
bool CPVRGUIInfo::GetListItemAndPlayerInt(const CFileItem *item, const CGUIInfo &info, int &iValue) const
{
  switch (info.m_info)
  {
    case LISTITEM_PROGRESS:
      if (item->IsPVRChannel() || item->IsEPG())
      {
        const CPVREpgInfoTagPtr epgTag = CPVRItem(item).GetEpgInfoTag();
        if (epgTag)
          iValue = static_cast<int>(epgTag->ProgressPercentage());
      }
      return true;
  }
  return false;
}
Example #14
0
bool CPVREpgSearchFilter::MatchBroadcastId(const CPVREpgInfoTagPtr &tag) const
{
  if (m_iUniqueBroadcastId != EPG_TAG_INVALID_UID)
    return (tag->UniqueBroadcastID() == m_iUniqueBroadcastId);

  return true;
}
Example #15
0
bool CPVREpg::UpdateEntry(const CPVREpgInfoTagPtr &tag, EPG_EVENT_STATE newState, bool bUpdateDatabase)
{
  bool bRet(true);
  bool bNotify(true);

  if (newState == EPG_EVENT_CREATED || newState == EPG_EVENT_UPDATED)
  {
    bRet = UpdateEntry(tag, bUpdateDatabase);
  }
  else if (newState == EPG_EVENT_DELETED)
  {
    CSingleLock lock(m_critSection);

    auto it = m_tags.begin();
    for (; it != m_tags.end(); ++it)
    {
      if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID())
        break;
    }

    if (it == m_tags.end())
    {
      bRet = false;
    }
    else
    {
      // Respect epg linger time.
      int iPastDays = CServiceBroker::GetPVRManager().EpgContainer().GetPastDaysToDisplay();
      const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(iPastDays, 0, 0, 0));
      if (it->second->EndAsUTC() < cleanupTime)
      {
        if (bUpdateDatabase)
          m_deletedTags.insert(std::make_pair(it->second->UniqueBroadcastID(), it->second));

        it->second->ClearTimer();
        it->second->ClearRecording();
        m_tags.erase(it);
      }
      else
      {
        bNotify = false;
      }
    }
  }
  else
  {
    CLog::Log(LOGERROR, "EPG - %s - unknown epg event state value: %d", __FUNCTION__, newState);
    bRet = false;
  }

  if (bRet && bNotify)
  {
    SetChanged();
    NotifyObservers(ObservableMessageEpgItemUpdate);
  }

  return bRet;
}
Example #16
0
void CPVREpg::AddEntry(const CPVREpgInfoTag &tag)
{
  CPVREpgInfoTagPtr newTag;
  CPVRChannelPtr channel;
  {
    CSingleLock lock(m_critSection);
    std::map<CDateTime, CPVREpgInfoTagPtr>::iterator itr = m_tags.find(tag.StartAsUTC());
    if (itr != m_tags.end())
      newTag = itr->second;
    else
    {
      newTag.reset(new CPVREpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : ""));
      m_tags.insert(make_pair(tag.StartAsUTC(), newTag));
    }

    channel = m_pvrChannel;
  }

  if (newTag)
  {
    newTag->Update(tag);
    newTag->SetChannel(channel);
    newTag->SetEpg(this);
    newTag->SetTimer(CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(newTag));
    newTag->SetRecording(CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(newTag));
  }
}
Example #17
0
void CGUIWindowPVRGuideBase::OnInputDone()
{
  const int iChannelNumber = GetChannelNumber();
  if (iChannelNumber >= 0)
  {
    for (const CFileItemPtr event : m_vecItems->GetList())
    {
      const CPVREpgInfoTagPtr tag(event->GetEPGInfoTag());
      if (tag->HasChannel() && tag->ChannelNumber() == iChannelNumber)
      {
        CGUIEPGGridContainer* epgGridContainer = GetGridControl();
        if (epgGridContainer)
        {
          epgGridContainer->SetChannel(tag->Channel());
          return;
        }
      }
    }
  }
}
Example #18
0
bool CPVREpgSearchFilter::MatchChannelGroup(const CPVREpgInfoTagPtr &tag) const
{
  bool bReturn(true);

  if (m_iChannelGroup != EPG_SEARCH_UNSET && CServiceBroker::GetPVRManager().IsStarted())
  {
    CPVRChannelGroupPtr group = CServiceBroker::GetPVRManager().ChannelGroups()->GetByIdFromAll(m_iChannelGroup);
    bReturn = (group && group->IsGroupMember(tag->Channel()));
  }

  return bReturn;
}
Example #19
0
CPVRRecordingPtr CPVRRecordings::GetRecordingForEpgTag(const CPVREpgInfoTagPtr &epgTag) const
{
  CSingleLock lock(m_critSection);

  for (const auto recording : m_recordings)
  {
    if (recording.second->IsDeleted())
      continue;

    unsigned int iEpgEvent = recording.second->BroadcastUid();
    if (iEpgEvent != EPG_TAG_INVALID_UID)
    {
      if (iEpgEvent == epgTag->UniqueBroadcastID())
      {
        // uid matches. perfect.
        return recording.second;
      }
    }
    else
    {
      // uid is optional, so check other relevant data.

      // note: don't use recording.second->Channel() for comparing channels here as this can lead
      //       to deadlocks. compare client ids and channel ids instead, this has the same effect.
      if (epgTag->Channel() &&
          recording.second->ClientID() == epgTag->Channel()->ClientID() &&
          recording.second->ChannelUid() == epgTag->Channel()->UniqueID() &&
          recording.second->RecordingTimeAsUTC() <= epgTag->StartAsUTC() &&
          recording.second->EndTimeAsUTC() >= epgTag->EndAsUTC())
        return recording.second;
    }
  }

  return CPVRRecordingPtr();
}
Example #20
0
void CPVRRecordings::UpdateFromClient(const CPVRRecordingPtr &tag)
{
  CSingleLock lock(m_critSection);

  if (tag->IsDeleted())
  {
    if (tag->IsRadio())
      m_bDeletedRadioRecordings = true;
    else
      m_bDeletedTVRecordings = true;
  }

  CPVRRecordingPtr newTag = GetById(tag->m_iClientId, tag->m_strRecordingId);
  if (newTag)
  {
    newTag->Update(*tag);
  }
  else
  {
    newTag = CPVRRecordingPtr(new CPVRRecording);
    newTag->Update(*tag);
    if (newTag->BroadcastUid() != EPG_TAG_INVALID_UID)
    {
      const CPVRChannelPtr channel(newTag->Channel());
      if (channel)
      {
        const CPVREpgInfoTagPtr epgTag = CServiceBroker::GetPVRManager().EpgContainer().GetTagById(channel, newTag->BroadcastUid());
        if (epgTag)
          epgTag->SetRecording(newTag);
      }
    }
    newTag->m_iRecordingId = ++m_iLastId;
    m_recordings.insert(std::make_pair(CPVRRecordingUid(newTag->m_iClientId, newTag->m_strRecordingId), newTag));
    if (newTag->IsRadio())
      ++m_iRadioRecordings;
    else
      ++m_iTVRecordings;
  }
}
Example #21
0
/*!
 * @brief Copy over timer info from xbmcTimer to addonTimer.
 * @param xbmcTimer The timer on XBMC's side.
 * @param addonTimer The timer on the addon's side.
 */
void CPVRClient::WriteClientTimerInfo(const CPVRTimerInfoTag &xbmcTimer, PVR_TIMER &addonTimer)
{
  time_t start, end, firstDay;
  xbmcTimer.StartAsUTC().GetAsTime(start);
  xbmcTimer.EndAsUTC().GetAsTime(end);
  xbmcTimer.FirstDayAsUTC().GetAsTime(firstDay);
  CPVREpgInfoTagPtr epgTag = xbmcTimer.GetEpgInfoTag();

  memset(&addonTimer, 0, sizeof(addonTimer));

  addonTimer.iClientIndex              = xbmcTimer.m_iClientIndex;
  addonTimer.iParentClientIndex        = xbmcTimer.m_iParentClientIndex;
  addonTimer.state                     = xbmcTimer.m_state;
  addonTimer.iTimerType                = xbmcTimer.GetTimerType() ? xbmcTimer.GetTimerType()->GetTypeId() : PVR_TIMER_TYPE_NONE;
  addonTimer.iClientChannelUid         = xbmcTimer.m_iClientChannelUid;
  strncpy(addonTimer.strTitle, xbmcTimer.m_strTitle.c_str(), sizeof(addonTimer.strTitle) - 1);
  strncpy(addonTimer.strEpgSearchString, xbmcTimer.m_strEpgSearchString.c_str(), sizeof(addonTimer.strEpgSearchString) - 1);
  addonTimer.bFullTextEpgSearch        = xbmcTimer.m_bFullTextEpgSearch;
  strncpy(addonTimer.strDirectory, xbmcTimer.m_strDirectory.c_str(), sizeof(addonTimer.strDirectory) - 1);
  addonTimer.iPriority                 = xbmcTimer.m_iPriority;
  addonTimer.iLifetime                 = xbmcTimer.m_iLifetime;
  addonTimer.iMaxRecordings            = xbmcTimer.m_iMaxRecordings;
  addonTimer.iPreventDuplicateEpisodes = xbmcTimer.m_iPreventDupEpisodes;
  addonTimer.iRecordingGroup           = xbmcTimer.m_iRecordingGroup;
  addonTimer.iWeekdays                 = xbmcTimer.m_iWeekdays;
  addonTimer.startTime                 = start - g_advancedSettings.m_iPVRTimeCorrection;
  addonTimer.endTime                   = end - g_advancedSettings.m_iPVRTimeCorrection;
  addonTimer.bStartAnyTime             = xbmcTimer.m_bStartAnyTime;
  addonTimer.bEndAnyTime               = xbmcTimer.m_bEndAnyTime;
  addonTimer.firstDay                  = firstDay - g_advancedSettings.m_iPVRTimeCorrection;
  addonTimer.iEpgUid                   = epgTag ? epgTag->UniqueBroadcastID() : PVR_TIMER_NO_EPG_UID;
  strncpy(addonTimer.strSummary, xbmcTimer.m_strSummary.c_str(), sizeof(addonTimer.strSummary) - 1);
  addonTimer.iMarginStart              = xbmcTimer.m_iMarginStart;
  addonTimer.iMarginEnd                = xbmcTimer.m_iMarginEnd;
  addonTimer.iGenreType                = epgTag ? epgTag->GenreType() : 0;
  addonTimer.iGenreSubType             = epgTag ? epgTag->GenreSubType() : 0;
}
Example #22
0
bool CPVREpgSearchFilter::FilterEntry(const CPVREpgInfoTagPtr &tag) const
{
  return (MatchGenre(tag) &&
      MatchBroadcastId(tag) &&
      MatchDuration(tag) &&
      MatchStartAndEndTimes(tag) &&
      MatchSearchTerm(tag) &&
      MatchTimers(tag) &&
      MatchRecordings(tag)) &&
      (!tag->HasChannel() ||
       (MatchChannelType(tag) &&
        MatchChannelNumber(tag) &&
        MatchChannelGroup(tag) &&
        MatchFreeToAir(tag)));
}
Example #23
0
bool CPVREpgSearchFilter::MatchChannelNumber(const CPVREpgInfoTagPtr &tag) const
{
  bool bReturn(true);

  if (m_channelNumber.IsValid() && CServiceBroker::GetPVRManager().IsStarted())
  {
    CPVRChannelGroupPtr group = (m_iChannelGroup != EPG_SEARCH_UNSET) ? CServiceBroker::GetPVRManager().ChannelGroups()->GetByIdFromAll(m_iChannelGroup) : CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAllTV();
    if (!group)
      group = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAllTV();

    bReturn = (m_channelNumber == group->GetChannelNumber(tag->Channel()));
  }

  return bReturn;
}
Example #24
0
int CGUIEPGGridContainerModel::GetFirstEventBlock(const CPVREpgInfoTagPtr &event) const
{
  const CDateTime eventStart = event->StartAsUTC();
  int diff;

  if (m_gridStart == eventStart)
    return 0; // block is at grid start
  else if (m_gridStart > eventStart)
    diff = -1 * (m_gridStart - eventStart).GetSecondsTotal();
  else
    diff = (eventStart - m_gridStart).GetSecondsTotal();

  // First block of a tag is always the block calculated using event's start time, rounded up.
  // Refer to CGUIEPGGridContainerModel::Refresh, where the model is created, for details!
  float fBlockIndex = diff / 60.0f / MINSPERBLOCK;
  return std::ceil(fBlockIndex);
}
Example #25
0
void CGUIEPGGridContainerModel::FindChannelAndBlockIndex(int channelUid, unsigned int broadcastUid, int eventOffset, int &newChannelIndex, int &newBlockIndex) const
{
  const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0);

  newChannelIndex = INVALID_INDEX;
  newBlockIndex = INVALID_INDEX;

  // find the channel
  int iCurrentChannel = 0;
  for (const auto& channel : m_channelItems)
  {
    if (channel->GetPVRChannelInfoTag()->UniqueID() == channelUid)
    {
      newChannelIndex = iCurrentChannel;
      break;
    }
    iCurrentChannel++;
  }

  if (newChannelIndex != INVALID_INDEX)
  {
    // find the block
    CDateTime gridCursor(m_gridStart); //reset cursor for new channel
    unsigned long progIdx = m_epgItemsPtr[newChannelIndex].start;
    unsigned long lastIdx = m_epgItemsPtr[newChannelIndex].stop;
    int iEpgId = m_programmeItems[progIdx]->GetEPGInfoTag()->EpgID();
    CPVREpgInfoTagPtr tag;
    for (int block = 0; block < m_blocks; ++block)
    {
      while (progIdx <= lastIdx)
      {
        tag = m_programmeItems[progIdx]->GetEPGInfoTag();

        if (tag->EpgID() != iEpgId || gridCursor < tag->StartAsUTC() || m_gridEnd <= tag->StartAsUTC())
          break; // next block

        if (gridCursor < tag->EndAsUTC())
        {
          if (broadcastUid > 0 && tag->UniqueBroadcastID() == broadcastUid)
          {
            newBlockIndex = block + eventOffset;
            return; // done.
          }
          break; // next block
        }
        progIdx++;
      }
      gridCursor += blockDuration;
    }
  }
}
Example #26
0
int CGUIEPGGridContainerModel::GetLastEventBlock(const CPVREpgInfoTagPtr &event) const
{
  // Last block of a tag is always the block calculated using event's end time, not rounded up.
  // Refer to CGUIEPGGridContainerModel::Refresh, where the model is created, for details!
  return GetBlock(event->EndAsUTC());
}
Example #27
0
void CGUIEPGGridContainerModel::Initialize(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize)
{
  if (!m_channelItems.empty())
  {
    CLog::LogF(LOGERROR, "Already initialized!");
    return;
  }

  ////////////////////////////////////////////////////////////////////////
  // Create programme & channel items
  m_programmeItems.reserve(items->Size());
  CFileItemPtr fileItem;
  int iLastChannelID = -1;
  ItemsPtr itemsPointer;
  itemsPointer.start = 0;
  CPVRChannelPtr channel;
  int j = 0;
  for (int i = 0; i < items->Size(); ++i)
  {
    fileItem = items->Get(i);
    if (!fileItem->HasEPGInfoTag() || !fileItem->GetEPGInfoTag()->HasChannel())
      continue;

    m_programmeItems.emplace_back(fileItem);

    channel = fileItem->GetEPGInfoTag()->Channel();
    if (!channel)
      continue;

    int iCurrentChannelID = channel->ChannelID();
    if (iCurrentChannelID != iLastChannelID)
    {
      if (j > 0)
      {
        itemsPointer.stop = j - 1;
        m_epgItemsPtr.emplace_back(itemsPointer);
        itemsPointer.start = j;
      }
      iLastChannelID = iCurrentChannelID;
      m_channelItems.emplace_back(CFileItemPtr(new CFileItem(channel)));
    }
    ++j;
  }
  if (!m_programmeItems.empty())
  {
    itemsPointer.stop = m_programmeItems.size() - 1;
    m_epgItemsPtr.emplace_back(itemsPointer);
  }

  /* check for invalid start and end time */
  if (gridStart >= gridEnd)
  {
    // default to start "now minus GRID_START_PADDING minutes" and end "start plus one page".
    m_gridStart = CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0);
    m_gridEnd = m_gridStart + CDateTimeSpan(0, 0, iBlocksPerPage * MINSPERBLOCK, 0);
  }
  else if (gridStart > (CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0)))
  {
    // adjust to start "now minus GRID_START_PADDING minutes".
    m_gridStart = CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0);
    m_gridEnd = gridEnd;
  }
  else
  {
    m_gridStart = gridStart;
    m_gridEnd = gridEnd;
  }

  // roundup
  m_gridStart = CDateTime(m_gridStart.GetYear(), m_gridStart.GetMonth(), m_gridStart.GetDay(), m_gridStart.GetHour(), m_gridStart.GetMinute() >= 30 ? 30 : 0, 0);
  m_gridEnd = CDateTime(m_gridEnd.GetYear(), m_gridEnd.GetMonth(), m_gridEnd.GetDay(), m_gridEnd.GetHour(), m_gridEnd.GetMinute() >= 30 ? 30 : 0, 0);

  ////////////////////////////////////////////////////////////////////////
  // Create ruler items
  CDateTime ruler;
  ruler.SetFromUTCDateTime(m_gridStart);
  CDateTime rulerEnd;
  rulerEnd.SetFromUTCDateTime(m_gridEnd);
  CFileItemPtr rulerItem(new CFileItem(ruler.GetAsLocalizedDate(true)));
  rulerItem->SetProperty("DateLabel", true);
  m_rulerItems.emplace_back(rulerItem);

  const CDateTimeSpan unit(0, 0, iRulerUnit * MINSPERBLOCK, 0);
  for (; ruler < rulerEnd; ruler += unit)
  {
    rulerItem.reset(new CFileItem(ruler.GetAsLocalizedTime("", false)));
    rulerItem->SetLabel2(ruler.GetAsLocalizedDate(true));
    m_rulerItems.emplace_back(rulerItem);
  }

  FreeItemsMemory();

  ////////////////////////////////////////////////////////////////////////
  // Create epg grid
  const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0);
  const CDateTimeSpan gridDuration(m_gridEnd - m_gridStart);
  m_blocks = (gridDuration.GetDays() * 24 * 60 + gridDuration.GetHours() * 60 + gridDuration.GetMinutes()) / MINSPERBLOCK;
  if (m_blocks >= MAXBLOCKS)
    m_blocks = MAXBLOCKS;
  else if (m_blocks < iBlocksPerPage)
    m_blocks = iBlocksPerPage;

  m_gridIndex.reserve(m_channelItems.size());
  const std::vector<GridItem> blocks(m_blocks);

  for (size_t channel = 0; channel < m_channelItems.size(); ++channel)
  {
    m_gridIndex.emplace_back(blocks);

    CDateTime gridCursor(m_gridStart); //reset cursor for new channel
    unsigned long progIdx = m_epgItemsPtr[channel].start;
    unsigned long lastIdx = m_epgItemsPtr[channel].stop;
    int iEpgId            = m_programmeItems[progIdx]->GetEPGInfoTag()->EpgID();
    int itemSize          = 1; // size of the programme in blocks
    int savedBlock        = 0;
    CFileItemPtr item;
    CPVREpgInfoTagPtr tag;

    for (int block = 0; block < m_blocks; ++block)
    {
      while (progIdx <= lastIdx)
      {
        item = m_programmeItems[progIdx];
        tag = item->GetEPGInfoTag();

        // Note: Start block of an event is start-time-based calculated block + 1,
        //       unless start times matches exactly the begin of a block.

        if (tag->EpgID() != iEpgId || gridCursor < tag->StartAsUTC() || m_gridEnd <= tag->StartAsUTC())
          break;

        if (gridCursor < tag->EndAsUTC())
        {
          m_gridIndex[channel][block].item = item;
          m_gridIndex[channel][block].progIndex = progIdx;
          break;
        }

        progIdx++;
      }

      gridCursor += blockDuration;

      if (block == 0)
        continue;

      const CFileItemPtr prevItem(m_gridIndex[channel][block - 1].item);
      const CFileItemPtr currItem(m_gridIndex[channel][block].item);

      if (block == m_blocks - 1 || prevItem != currItem)
      {
        // special handling for last block.
        int blockDelta = -1;
        int sizeDelta = 0;
        if (block == m_blocks - 1 && prevItem == currItem)
        {
          itemSize++;
          blockDelta = 0;
          sizeDelta = 1;
        }

        if (prevItem)
        {
          m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", prevItem->GetEPGInfoTag()->GenreType());
        }
        else
        {
          CPVREpgInfoTagPtr gapTag(CPVREpgInfoTag::CreateDefaultTag());
          gapTag->SetChannel(m_channelItems[channel]->GetPVRChannelInfoTag());
          CFileItemPtr gapItem(new CFileItem(gapTag));
          for (int i = block + blockDelta; i >= block - itemSize + sizeDelta; --i)
          {
            m_gridIndex[channel][i].item = gapItem;
          }
        }

        float fItemWidth = itemSize * fBlockSize;
        m_gridIndex[channel][savedBlock].originWidth = fItemWidth;
        m_gridIndex[channel][savedBlock].width = fItemWidth;

        itemSize = 1;
        savedBlock = block;

        // special handling for last block.
        if (block == m_blocks - 1 && prevItem != currItem)
        {
          if (currItem)
          {
            m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", currItem->GetEPGInfoTag()->GenreType());
          }
          else
          {
            CPVREpgInfoTagPtr gapTag(CPVREpgInfoTag::CreateDefaultTag());
            gapTag->SetChannel(m_channelItems[channel]->GetPVRChannelInfoTag());
            CFileItemPtr gapItem(new CFileItem(gapTag));
            m_gridIndex[channel][block].item = gapItem;
          }

          m_gridIndex[channel][savedBlock].originWidth = fBlockSize; // size always 1 block here
          m_gridIndex[channel][savedBlock].width = fBlockSize;
        }
      }
      else
      {
        itemSize++;
      }
    }
  }
}
Example #28
0
bool CPVREpg::UpdateEntry(const CPVREpgInfoTagPtr &tag, bool bUpdateDatabase)
{
  CPVREpgInfoTagPtr infoTag;

  {
    CSingleLock lock(m_critSection);
    std::map<CDateTime, CPVREpgInfoTagPtr>::iterator it = m_tags.find(tag->StartAsUTC());
    bool bNewTag(false);
    if (it != m_tags.end())
    {
      infoTag = it->second;
    }
    else
    {
      infoTag.reset(new CPVREpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : ""));
      infoTag->SetUniqueBroadcastID(tag->UniqueBroadcastID());
      m_tags.insert(std::make_pair(tag->StartAsUTC(), infoTag));
      bNewTag = true;
    }

    infoTag->Update(*tag, bNewTag);
    infoTag->SetEpg(this);
    infoTag->SetChannel(m_pvrChannel);

    if (bUpdateDatabase)
      m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag));
  }

  infoTag->SetTimer(CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(infoTag));
  infoTag->SetRecording(CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(infoTag));

  return true;
}
Example #29
0
bool CPVRGUIInfo::GetPVRLabel(const CFileItem *item, const CGUIInfo &info, std::string &strValue) const
{
  CSingleLock lock(m_critSection);

  switch (info.m_info)
  {
    case PVR_EPG_EVENT_ICON:
    {
      const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
      if (epgTag)
      {
        strValue = epgTag->Icon();
      }
      return true;
    }
    case PVR_EPG_EVENT_DURATION:
    {
      const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
      strValue = m_timesInfo.GetEpgEventDuration(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    }
   case PVR_EPG_EVENT_ELAPSED_TIME:
    {
      const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
      strValue = m_timesInfo.GetEpgEventElapsedTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    }
    case PVR_EPG_EVENT_REMAINING_TIME:
    {
      const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
      strValue = m_timesInfo.GetEpgEventRemainingTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    }
    case PVR_EPG_EVENT_FINISH_TIME:
    {
      const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
      strValue = m_timesInfo.GetEpgEventFinishTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    }
    case PVR_TIMESHIFT_START_TIME:
      strValue = m_timesInfo.GetTimeshiftStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_END_TIME:
      strValue = m_timesInfo.GetTimeshiftEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_PLAY_TIME:
      strValue = m_timesInfo.GetTimeshiftPlayTime(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_OFFSET:
      strValue = m_timesInfo.GetTimeshiftOffset(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_PROGRESS_DURATION:
      strValue = m_timesInfo.GetTimeshiftProgressDuration(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_PROGRESS_START_TIME:
      strValue = m_timesInfo.GetTimeshiftProgressStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_TIMESHIFT_PROGRESS_END_TIME:
      strValue = m_timesInfo.GetTimeshiftProgressEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_EPG_EVENT_SEEK_TIME:
      strValue = m_timesInfo.GetEpgEventSeekTime(g_application.GetAppPlayer().GetSeekHandler().GetSeekSize(),
                                                     static_cast<TIME_FORMAT>(info.GetData1()));
      return true;
    case PVR_NOW_RECORDING_TITLE:
      strValue = m_anyTimersInfo.GetActiveTimerTitle();
      return true;
    case PVR_NOW_RECORDING_CHANNEL:
      strValue = m_anyTimersInfo.GetActiveTimerChannelName();
      return true;
    case PVR_NOW_RECORDING_CHAN_ICO:
      strValue = m_anyTimersInfo.GetActiveTimerChannelIcon();
      return true;
    case PVR_NOW_RECORDING_DATETIME:
      strValue = m_anyTimersInfo.GetActiveTimerDateTime();
      return true;
    case PVR_NEXT_RECORDING_TITLE:
      strValue = m_anyTimersInfo.GetNextTimerTitle();
      return true;
    case PVR_NEXT_RECORDING_CHANNEL:
      strValue = m_anyTimersInfo.GetNextTimerChannelName();
      return true;
    case PVR_NEXT_RECORDING_CHAN_ICO:
      strValue = m_anyTimersInfo.GetNextTimerChannelIcon();
      return true;
    case PVR_NEXT_RECORDING_DATETIME:
      strValue = m_anyTimersInfo.GetNextTimerDateTime();
      return true;
    case PVR_TV_NOW_RECORDING_TITLE:
      strValue = m_tvTimersInfo.GetActiveTimerTitle();
      return true;
    case PVR_TV_NOW_RECORDING_CHANNEL:
      strValue = m_tvTimersInfo.GetActiveTimerChannelName();
      return true;
    case PVR_TV_NOW_RECORDING_CHAN_ICO:
      strValue = m_tvTimersInfo.GetActiveTimerChannelIcon();
      return true;
    case PVR_TV_NOW_RECORDING_DATETIME:
      strValue = m_tvTimersInfo.GetActiveTimerDateTime();
      return true;
    case PVR_TV_NEXT_RECORDING_TITLE:
      strValue = m_tvTimersInfo.GetNextTimerTitle();
      return true;
    case PVR_TV_NEXT_RECORDING_CHANNEL:
      strValue = m_tvTimersInfo.GetNextTimerChannelName();
      return true;
    case PVR_TV_NEXT_RECORDING_CHAN_ICO:
      strValue = m_tvTimersInfo.GetNextTimerChannelIcon();
      return true;
    case PVR_TV_NEXT_RECORDING_DATETIME:
      strValue = m_tvTimersInfo.GetNextTimerDateTime();
      return true;
    case PVR_RADIO_NOW_RECORDING_TITLE:
      strValue = m_radioTimersInfo.GetActiveTimerTitle();
      return true;
    case PVR_RADIO_NOW_RECORDING_CHANNEL:
      strValue = m_radioTimersInfo.GetActiveTimerChannelName();
      return true;
    case PVR_RADIO_NOW_RECORDING_CHAN_ICO:
      strValue = m_radioTimersInfo.GetActiveTimerChannelIcon();
      return true;
    case PVR_RADIO_NOW_RECORDING_DATETIME:
      strValue = m_radioTimersInfo.GetActiveTimerDateTime();
      return true;
    case PVR_RADIO_NEXT_RECORDING_TITLE:
      strValue = m_radioTimersInfo.GetNextTimerTitle();
      return true;
    case PVR_RADIO_NEXT_RECORDING_CHANNEL:
      strValue = m_radioTimersInfo.GetNextTimerChannelName();
      return true;
    case PVR_RADIO_NEXT_RECORDING_CHAN_ICO:
      strValue = m_radioTimersInfo.GetNextTimerChannelIcon();
      return true;
    case PVR_RADIO_NEXT_RECORDING_DATETIME:
      strValue = m_radioTimersInfo.GetNextTimerDateTime();
      return true;
    case PVR_NEXT_TIMER:
      strValue = m_anyTimersInfo.GetNextTimer();
      return true;
    case PVR_ACTUAL_STREAM_SIG:
      CharInfoSignal(strValue);
      return true;
    case PVR_ACTUAL_STREAM_SNR:
      CharInfoSNR(strValue);
      return true;
    case PVR_ACTUAL_STREAM_BER:
      CharInfoBER(strValue);
      return true;
    case PVR_ACTUAL_STREAM_UNC:
      CharInfoUNC(strValue);
      return true;
    case PVR_ACTUAL_STREAM_CLIENT:
      CharInfoPlayingClientName(strValue);
      return true;
    case PVR_ACTUAL_STREAM_DEVICE:
      CharInfoFrontendName(strValue);
      return true;
    case PVR_ACTUAL_STREAM_STATUS:
      CharInfoFrontendStatus(strValue);
      return true;
    case PVR_ACTUAL_STREAM_CRYPTION:
      CharInfoEncryption(strValue);
      return true;
    case PVR_ACTUAL_STREAM_SERVICE:
      CharInfoService(strValue);
      return true;
    case PVR_ACTUAL_STREAM_MUX:
      CharInfoMux(strValue);
      return true;
    case PVR_ACTUAL_STREAM_PROVIDER:
      CharInfoProvider(strValue);
      return true;
    case PVR_BACKEND_NAME:
      CharInfoBackendName(strValue);
      return true;
    case PVR_BACKEND_VERSION:
      CharInfoBackendVersion(strValue);
      return true;
    case PVR_BACKEND_HOST:
      CharInfoBackendHost(strValue);
      return true;
    case PVR_BACKEND_DISKSPACE:
      CharInfoBackendDiskspace(strValue);
      return true;
    case PVR_BACKEND_CHANNELS:
      CharInfoBackendChannels(strValue);
      return true;
    case PVR_BACKEND_TIMERS:
      CharInfoBackendTimers(strValue);
      return true;
    case PVR_BACKEND_RECORDINGS:
      CharInfoBackendRecordings(strValue);
      return true;
    case PVR_BACKEND_DELETED_RECORDINGS:
      CharInfoBackendDeletedRecordings(strValue);
      return true;
    case PVR_BACKEND_NUMBER:
      CharInfoBackendNumber(strValue);
      return true;
    case PVR_TOTAL_DISKSPACE:
      CharInfoTotalDiskSpace(strValue);
      return true;
    case PVR_CHANNEL_NUMBER_INPUT:
      strValue = CServiceBroker::GetPVRManager().GUIActions()->GetChannelNumberInputHandler().GetChannelNumberLabel();
      return true;
  }

  return false;
}
Example #30
0
bool CGUIWindowPVRGuideBase::OnMessage(CGUIMessage& message)
{
  bool bReturn = false;
  switch (message.GetMessage())
  {
    case GUI_MSG_CLICKED:
    {
      if (message.GetSenderId() == m_viewControl.GetCurrentControl())
      {
        int iItem = m_viewControl.GetSelectedItem();
        if (iItem >= 0 && iItem < m_vecItems->Size())
        {
          CFileItemPtr pItem = m_vecItems->Get(iItem);
          /* process actions */
          switch (message.GetParam1())
          {
            case ACTION_SELECT_ITEM:
            case ACTION_MOUSE_LEFT_CLICK:
              switch(CServiceBroker::GetSettings().GetInt(CSettings::SETTING_EPG_SELECTACTION))
              {
                case EPG_SELECT_ACTION_CONTEXT_MENU:
                  OnPopupMenu(iItem);
                  bReturn = true;
                  break;
                case EPG_SELECT_ACTION_SWITCH:
                  CServiceBroker::GetPVRManager().GUIActions()->SwitchToChannel(pItem, true);
                  bReturn = true;
                  break;
                case EPG_SELECT_ACTION_PLAY_RECORDING:
                  CServiceBroker::GetPVRManager().GUIActions()->PlayRecording(pItem, true);
                  bReturn = true;
                  break;
                case EPG_SELECT_ACTION_INFO:
                  CServiceBroker::GetPVRManager().GUIActions()->ShowEPGInfo(pItem);
                  bReturn = true;
                  break;
                case EPG_SELECT_ACTION_RECORD:
                  CServiceBroker::GetPVRManager().GUIActions()->ToggleTimer(pItem);
                  bReturn = true;
                  break;
                case EPG_SELECT_ACTION_SMART_SELECT:
                {
                  const CPVREpgInfoTagPtr tag(pItem->GetEPGInfoTag());
                  if (tag)
                  {
                    const CDateTime start(tag->StartAsUTC());
                    const CDateTime end(tag->EndAsUTC());
                    const CDateTime now(CDateTime::GetUTCDateTime());

                    if (start <= now && now <= end)
                    {
                      // current event
                      CServiceBroker::GetPVRManager().GUIActions()->SwitchToChannel(pItem, true);
                    }
                    else if (now < start)
                    {
                      // future event
                      if (tag->HasTimer())
                        CServiceBroker::GetPVRManager().GUIActions()->EditTimer(pItem);
                      else
                        CServiceBroker::GetPVRManager().GUIActions()->AddTimer(pItem, false);
                    }
                    else
                    {
                      // past event
                      if (tag->HasRecording())
                        CServiceBroker::GetPVRManager().GUIActions()->PlayRecording(pItem, true);
                      else if (tag->IsPlayable())
                        CServiceBroker::GetPVRManager().GUIActions()->PlayEpgTag(pItem);
                      else
                        CServiceBroker::GetPVRManager().GUIActions()->ShowEPGInfo(pItem);
                    }
                    bReturn = true;
                  }
                  break;
                }
              }
              break;
            case ACTION_SHOW_INFO:
              CServiceBroker::GetPVRManager().GUIActions()->ShowEPGInfo(pItem);
              bReturn = true;
              break;
            case ACTION_PLAY:
              CServiceBroker::GetPVRManager().GUIActions()->PlayRecording(pItem, true);
              bReturn = true;
              break;
            case ACTION_RECORD:
              CServiceBroker::GetPVRManager().GUIActions()->ToggleTimer(pItem);
              bReturn = true;
              break;
            case ACTION_PVR_SHOW_TIMER_RULE:
              CServiceBroker::GetPVRManager().GUIActions()->AddTimerRule(pItem, true);
              bReturn = true;
              break;
            case ACTION_CONTEXT_MENU:
            case ACTION_MOUSE_RIGHT_CLICK:
              OnPopupMenu(iItem);
              bReturn = true;
              break;
          }
        }
        else if (iItem == -1)
        {
          /* process actions */
          switch (message.GetParam1())
          {
            case ACTION_SELECT_ITEM:
            case ACTION_MOUSE_LEFT_CLICK:
            case ACTION_PLAY:
            {
              // EPG "gap" selected => switch to associated channel.
              CGUIEPGGridContainer *epgGridContainer = GetGridControl();
              if (epgGridContainer)
              {
                const CFileItemPtr item(epgGridContainer->GetSelectedChannelItem());
                if (item)
                {
                  CServiceBroker::GetPVRManager().GUIActions()->SwitchToChannel(item, true);
                  bReturn = true;
                }
              }
              break;
            }
          }
        }
      }
      else if (message.GetSenderId() == CONTROL_BTNVIEWASICONS)
      {
        // let's set the view mode first before update
        CGUIWindowPVRBase::OnMessage(message);
        Refresh(true);
        bReturn = true;
      }
      break;
    }
    case GUI_MSG_CHANGE_VIEW_MODE:
    {
      // let's set the view mode first before update
      CGUIWindowPVRBase::OnMessage(message);

      // force data update for the new view control
      {
        CSingleLock lock(m_critSection);
        m_bRefreshTimelineItems = true;
      }
      Init();

      Refresh(true);
      bReturn = true;
      break;
    }
    case GUI_MSG_REFRESH_LIST:
      switch(message.GetParam1())
      {
        case ObservableMessageChannelGroupsLoaded:
        {
          // late init
          InitChannelGroup();
          Init();
          break;
        }
        case ObservableMessageChannelGroupReset:
        case ObservableMessageChannelGroup:
        case ObservableMessageEpg:
        case ObservableMessageEpgContainer:
        {
          Refresh(true);
          break;
        }
        case ObservableMessageTimersReset:
        case ObservableMessageTimers:
        {
          SetInvalid();
          break;
        }
      }
      break;
  }

  return bReturn || CGUIWindowPVRBase::OnMessage(message);
}