Ejemplo n.º 1
0
int EpgSearchFilter::FilterTimers(CFileItemList &results)
{
  int iRemoved(0);
  if (!g_PVRManager.IsStarted())
    return iRemoved;

  vector<CFileItemPtr> timers = g_PVRTimers->GetActiveTimers();
  // TODO inefficient!
  for (unsigned int iTimerPtr = 0; iTimerPtr < timers.size(); iTimerPtr++)
  {
    CFileItemPtr fileItem = timers.at(iTimerPtr);
    if (!fileItem || !fileItem->HasPVRTimerInfoTag())
      continue;

    CPVRTimerInfoTag *timer = fileItem->GetPVRTimerInfoTag();
    if (!timer)
      continue;

    for (int iResultPtr = 0; iResultPtr < results.Size(); iResultPtr++)
    {
      const CEpgInfoTagPtr epgentry(results.Get(iResultPtr)->GetEPGInfoTag());
      if (!epgentry ||
          *epgentry->ChannelTag() != *timer->ChannelTag() ||
          epgentry->StartAsUTC()   <  timer->StartAsUTC() ||
          epgentry->EndAsUTC()     >  timer->EndAsUTC())
        continue;

      results.Remove(iResultPtr);
      iResultPtr--;
      ++iRemoved;
    }
  }

  return iRemoved;
}
Ejemplo n.º 2
0
CFileItemPtr CPVRTimers::GetTimerForEpgTag(const CFileItem *item) const
{
  if (item && item->HasEPGInfoTag() && item->GetEPGInfoTag()->ChannelTag())
  {
    const CEpgInfoTagPtr epgTag(item->GetEPGInfoTag());
    const CPVRChannelPtr channel(epgTag->ChannelTag());
    CSingleLock lock(m_critSection);

    for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
    {
      for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
      {
        CPVRTimerInfoTagPtr timer = *timerIt;

        if (timer->GetEpgInfoTag() == epgTag || 
            (timer->m_iClientChannelUid == channel->UniqueID() &&
            timer->m_bIsRadio == channel->IsRadio() &&
            timer->StartAsUTC() <= epgTag->StartAsUTC() &&
            timer->EndAsUTC() >= epgTag->EndAsUTC()))
        {
          CFileItemPtr fileItem(new CFileItem(timer));
          return fileItem;
        }
      }
    }
  }

  CFileItemPtr fileItem;
  return fileItem;
}
Ejemplo n.º 3
0
bool CGUIDialogPVRGuideInfo::ActionStartTimer(const CEpgInfoTagPtr &tag)
{
  bool bReturn = false;

  if (!tag)
    return false;

  CPVRChannelPtr channel = tag->ChannelTag();
  if (!channel || !g_PVRManager.CheckParentalLock(channel))
    return false;

  // prompt user for confirmation of channel record
  if (CGUIDialogYesNo::ShowAndGetInput(CVariant{264} /* "Record" */, CVariant{tag->Title()}))
  {
    Close();

    CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag);
    if (newTimer)
      bReturn = CPVRTimers::AddTimer(newTimer);
    else
      bReturn = false;
  }

  return bReturn;
}
Ejemplo n.º 4
0
bool CGUIWindowPVRBase::AddTimer(CFileItem *item, bool bAdvanced)
{
  CFileItemPtr epgTag;
  if (item->IsEPG())
  {
    epgTag.reset(new CFileItem(*item));
    if (!epgTag->GetEPGInfoTag()->HasPVRChannel())
      return false;
  }
  else if (item->IsPVRChannel())
  {
    CPVRChannelPtr channel(item->GetPVRChannelInfoTag());
    if (!channel)
      return false;

    CEpgInfoTagPtr epgNow(channel->GetEPGNow());
    if (!epgNow)
      return false;

    epgTag.reset(new CFileItem(epgNow));
  }

  const CEpgInfoTagPtr tag = epgTag->GetEPGInfoTag();
  CPVRChannelPtr channel = tag->ChannelTag();

  if (!channel || !g_PVRManager.CheckParentalLock(channel))
    return false;

  CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(item);
  if (timer && timer->HasPVRTimerInfoTag())
  {
    CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19034});
    return false;
  }

  bool bReturn(false);

  if (bAdvanced)
  {
    CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag, true);
    if (newTimer)
    {
      CFileItem *newItem = new CFileItem(newTimer);

      if (ShowTimerSettings(newItem))
        bReturn = g_PVRTimers->AddTimer(newItem->GetPVRTimerInfoTag());

      delete newItem;
    }
  }
  else
  {
    CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag);

    if (newTimer)
      bReturn = g_PVRTimers->AddTimer(newTimer);
  }
  return bReturn;
}
Ejemplo n.º 5
0
bool CGUIWindowPVRBase::AddTimer(CFileItem *item, bool bCreateRule, bool bShowTimerSettings)
{
  CEpgInfoTagPtr epgTag;
  CPVRChannelPtr channel;

  if (item->IsEPG())
  {
    epgTag  = item->GetEPGInfoTag();
    channel = epgTag->ChannelTag();
  }
  else if (item->IsPVRChannel())
  {
    channel = item->GetPVRChannelInfoTag();
    epgTag  = channel->GetEPGNow();
  }

  if (!channel)
  {
    CLog::Log(LOGERROR, "CGUIWindowPVRBase - %s - no channel!", __FUNCTION__);
    return false;
  }

  if (!g_PVRManager.CheckParentalLock(channel))
    return false;

  if (!epgTag && bCreateRule)
  {
    CLog::Log(LOGERROR, "CGUIWindowPVRBase - %s - no epg tag!", __FUNCTION__);
    return false;
  }

  CPVRTimerInfoTagPtr timer(bCreateRule || !epgTag ? nullptr : epgTag->Timer());
  CPVRTimerInfoTagPtr rule (bCreateRule ? g_PVRTimers->GetTimerRule(timer) : nullptr);
  if (timer || rule)
  {
    CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19034}); // "Information", "There is already a timer set for this event"
    return false;
  }

  CPVRTimerInfoTagPtr newTimer(epgTag ? CPVRTimerInfoTag::CreateFromEpg(epgTag, bCreateRule) : CPVRTimerInfoTag::CreateInstantTimerTag(channel));
  if (!newTimer)
  {
    CGUIDialogOK::ShowAndGetInput(CVariant{19033},
                                  bCreateRule
                                    ? CVariant{19095} // "Information", "Timer rule creation failed. The PVR add-on does not support a suitable timer rule type."
                                    : CVariant{19094}); // "Information", "Timer creation failed. The PVR add-on does not support a suitable timer type."
    return false;
  }

  if (bShowTimerSettings)
  {
    if (!ShowTimerSettings(newTimer))
      return false;
  }

  return g_PVRTimers->AddTimer(newTimer);
}
void CGUIWindowPVRBase::ShowEPGInfo(CFileItem *item)
{
  CEpgInfoTagPtr epgTag;
  CPVRChannelPtr channel;

  if (item->IsEPG())
  {
    epgTag  = item->GetEPGInfoTag();
    channel = epgTag->ChannelTag();
  }
  else if (item->IsPVRChannel())
  {
    channel = item->GetPVRChannelInfoTag();
    epgTag  = channel->GetEPGNow();
  }
  else if (item->IsPVRTimer())
  {
    epgTag = item->GetPVRTimerInfoTag()->GetEpgInfoTag();
    if (epgTag && epgTag->HasPVRChannel())
      channel = epgTag->ChannelTag();
  }

  if (channel && !g_PVRManager.CheckParentalLock(channel))
    return;

  if (!epgTag)
  {
    CLog::Log(LOGERROR, "CGUIWindowPVRBase - %s - no epg tag!", __FUNCTION__);
    return;
  }

  CGUIDialogPVRGuideInfo* pDlgInfo = (CGUIDialogPVRGuideInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_GUIDE_INFO);
  if (!pDlgInfo)
  {
    CLog::Log(LOGERROR, "CGUIWindowPVRBase - %s - unable to get WINDOW_DIALOG_PVR_GUIDE_INFO!", __FUNCTION__);
    return;
  }

  pDlgInfo->SetProgInfo(epgTag);
  pDlgInfo->Open();
}
Ejemplo n.º 7
0
CPVRTimerInfoTagPtr CPVRTimers::GetTimerForEpgTag(const CEpgInfoTagPtr &epgTag) const
{
  if (epgTag)
  {
    // already a timer assigned to tag?
    CPVRTimerInfoTagPtr timer(epgTag->Timer());
    if (timer)
      return timer;

    // try to find a matching timer for the tag.
    if (epgTag->ChannelTag())
    {
      const CPVRChannelPtr channel(epgTag->ChannelTag());
      CSingleLock lock(m_critSection);

      for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
      {
        for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
        {
          timer = *timerIt;

          if (!timer->IsRepeating() &&
              (timer->GetEpgInfoTag(false) == epgTag ||
               (timer->m_iEpgUid != EPG_TAG_INVALID_UID && timer->m_iEpgUid == epgTag->UniqueBroadcastID()) ||
               (timer->m_iClientChannelUid == channel->UniqueID() &&
                timer->m_bIsRadio == channel->IsRadio() &&
                timer->StartAsUTC() <= epgTag->StartAsUTC() &&
                timer->EndAsUTC() >= epgTag->EndAsUTC())))
          {
            return timer;
          }
        }
      }
    }
  }

  return CPVRTimerInfoTagPtr();
}
Ejemplo n.º 8
0
void CGUIEPGGridContainerModel::FindChannelAndBlockIndex(int channelUid, unsigned int broadcastUid, int eventOffset, int &newChannelIndex, int &newBlockIndex) const
{
  const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0);
  bool bFoundPrevChannel = false;

  for (size_t channel = 0; channel < m_channelItems.size(); ++channel)
  {
    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();
    CEpgInfoTagPtr tag;
    CPVRChannelPtr chan;

    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)
          {
            newChannelIndex = channel;
            newBlockIndex   = block + eventOffset;
            return; // both found. done.
          }
          if (!bFoundPrevChannel && channelUid > -1)
          {
            chan = tag->ChannelTag();
            if (chan && chan->UniqueID() == channelUid)
            {
              newChannelIndex = channel;
              bFoundPrevChannel = true;
            }
          }
          break; // next block
        }
        progIdx++;
      }
      gridCursor += blockDuration;
    }
  }
}
Ejemplo n.º 9
0
bool CGUIWindowPVRBase::StartRecordFile(CFileItem *item, bool bAdvanced)
{
  if (!item->HasEPGInfoTag())
    return false;

  const CEpgInfoTagPtr tag = item->GetEPGInfoTag();
  CPVRChannelPtr channel = tag->ChannelTag();

  if (!channel || !g_PVRManager.CheckParentalLock(channel))
    return false;

  CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(item);
  if (timer && timer->HasPVRTimerInfoTag())
  {
    CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19034});
    return false;
  }

  bool bReturn(false);

  if (bAdvanced)
  {
    CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag, true);
    if (newTimer)
    {
      CFileItem *newItem = new CFileItem(newTimer);

      if (ShowTimerSettings(newItem))
        bReturn = g_PVRTimers->AddTimer(newItem->GetPVRTimerInfoTag());

      delete newItem;
    }
  }
  else
  {
    // ask for confirmation before starting a timer
    if (!CGUIDialogYesNo::ShowAndGetInput(
        CVariant{264} /* "Record" */, CVariant{tag->PVRChannelName()}, CVariant{""}, CVariant{tag->Title()}))
      return false;
  
    CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag);

    if (newTimer)
      bReturn = g_PVRTimers->AddTimer(newTimer);
  }
  return bReturn;
}
Ejemplo n.º 10
0
void CGUIWindowPVRGuide::OnInputDone()
{
  const int iChannelNumber = GetChannelNumber();
  if (iChannelNumber >= 0)
  {
    for (const CFileItemPtr event : m_vecItems->GetList())
    {
      const CEpgInfoTagPtr tag(event->GetEPGInfoTag());
      if (tag->HasPVRChannel() && tag->PVRChannelNumber() == iChannelNumber)
      {
        CGUIEPGGridContainer* epgGridContainer = dynamic_cast<CGUIEPGGridContainer*>(GetControl(m_viewControl.GetCurrentControl()));
        if (epgGridContainer)
        {
          epgGridContainer->SetChannel(tag->ChannelTag());
          return;
        }
      }
    }
  }
}
Ejemplo n.º 11
0
bool CGUIWindowPVRBase::StartRecordFile(const CFileItem &item)
{
  if (!item.HasEPGInfoTag())
    return false;

  const CEpgInfoTagPtr tag = item.GetEPGInfoTag();
  CPVRChannelPtr channel = tag->ChannelTag();

  if (!channel || !g_PVRManager.CheckParentalLock(*channel))
    return false;

  CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(&item);
  if (timer && timer->HasPVRTimerInfoTag())
  {
    CGUIDialogOK::ShowAndGetInput(19033,19034,0,0);
    return false;
  }

  // ask for confirmation before starting a timer
  CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
  if (!pDialog)
    return false;
  pDialog->SetHeading(264);
  pDialog->SetLine(0, tag->PVRChannelName());
  pDialog->SetLine(1, "");
  pDialog->SetLine(2, tag->Title());
  pDialog->DoModal();

  if (!pDialog->IsConfirmed())
    return false;

  CPVRTimerInfoTag *newTimer = CPVRTimerInfoTag::CreateFromEpg(*tag);
  bool bReturn(false);
  if (newTimer)
  {
    bReturn = g_PVRTimers->AddTimer(*newTimer);
    delete newTimer;
  }
  return bReturn;
}
Ejemplo n.º 12
0
bool CGUIDialogPVRGuideInfo::ActionStartTimer(const CEpgInfoTagPtr &tag)
{
  bool bReturn = false;

  if (!tag)
    return false;

  CPVRChannelPtr channel = tag->ChannelTag();
  if (!channel || !g_PVRManager.CheckParentalLock(channel))
    return false;

  // prompt user for confirmation of channel record
  CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);

  if (pDialog)
  {
    pDialog->SetHeading(264);
    pDialog->SetLine(0, "");
    pDialog->SetLine(1, tag->Title());
    pDialog->SetLine(2, "");
    pDialog->DoModal();

    if (pDialog->IsConfirmed())
    {
      Close();
      CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(tag);
      if (newTimer)
      {
        bReturn = CPVRTimers::AddTimer(newTimer);
      }
      else
      {
        bReturn = false;
      }
    }
  }

  return bReturn;
}
Ejemplo n.º 13
0
 CPVRChannelPtr CPVRItem::GetChannel() const
 {
   if (m_item->IsPVRChannel())
   {
     return m_item->GetPVRChannelInfoTag();
   }
   else if (m_item->IsEPG())
   {
     return m_item->GetEPGInfoTag()->ChannelTag();
   }
   else if (m_item->IsPVRTimer())
   {
     const CEpgInfoTagPtr epgTag(m_item->GetPVRTimerInfoTag()->GetEpgInfoTag());
     if (epgTag)
       return epgTag->ChannelTag();
   }
   else
   {
     CLog::Log(LOGERROR, "CPVRItem - %s - unsupported item type!", __FUNCTION__);
   }
   return CPVRChannelPtr();
 }
Ejemplo n.º 14
0
bool CGUIDialogPVRGuideInfo::OnClickButtonFind(CGUIMessage &message)
{
  bool bReturn = false;

  if (message.GetSenderId() == CONTROL_BTN_FIND)
  {
    const CEpgInfoTagPtr tag(m_progItem->GetEPGInfoTag());
    if (tag && tag->HasPVRChannel())
    {
      int windowSearchId = tag->ChannelTag()->IsRadio() ? WINDOW_RADIO_SEARCH : WINDOW_TV_SEARCH;
      CGUIWindowPVRBase *windowSearch = (CGUIWindowPVRBase*) g_windowManager.GetWindow(windowSearchId);
      if (windowSearch)
      {
        Close();
        g_windowManager.ActivateWindow(windowSearchId);
        bReturn = windowSearch->OnContextButton(*m_progItem.get(), CONTEXT_BUTTON_FIND);
      }
    }
  }

  return bReturn;
}
Ejemplo n.º 15
0
CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag)
{
    /* create a new timer */
    CPVRTimerInfoTagPtr newTag(new CPVRTimerInfoTag());
    if (!newTag)
    {
        CLog::Log(LOGERROR, "%s - couldn't create new timer", __FUNCTION__);
        return CPVRTimerInfoTagPtr();
    }

    /* check if a valid channel is set */
    CPVRChannelPtr channel = tag->ChannelTag();
    if (!channel)
    {
        CLog::Log(LOGERROR, "%s - no channel set", __FUNCTION__);
        return CPVRTimerInfoTagPtr();
    }

    /* check if the epg end date is in the future */
    if (tag->EndAsLocalTime() < CDateTime::GetCurrentDateTime())
    {
        CLog::Log(LOGERROR, "%s - end time is in the past", __FUNCTION__);
        return CPVRTimerInfoTagPtr();
    }

    /* set the timer data */
    CDateTime newStart = tag->StartAsUTC();
    CDateTime newEnd = tag->EndAsUTC();
    newTag->m_iClientIndex      = -1;
    newTag->m_strTitle          = tag->Title().empty() ? channel->ChannelName() : tag->Title();
    newTag->m_iChannelNumber    = channel->ChannelNumber();
    newTag->m_iClientChannelUid = channel->UniqueID();
    newTag->m_iClientId         = channel->ClientID();
    newTag->m_bIsRadio          = channel->IsRadio();
    newTag->m_iGenreType        = tag->GenreType();
    newTag->m_iGenreSubType     = tag->GenreSubType();
    newTag->m_channel           = channel;
    newTag->SetStartFromUTC(newStart);
    newTag->SetEndFromUTC(newEnd);

    if (tag->Plot().empty())
    {
        newTag->m_strSummary= StringUtils::Format("%s %s %s %s %s",
                              newTag->StartAsLocalTime().GetAsLocalizedDate().c_str(),
                              g_localizeStrings.Get(19159).c_str(),
                              newTag->StartAsLocalTime().GetAsLocalizedTime("", false).c_str(),
                              g_localizeStrings.Get(19160).c_str(),
                              newTag->EndAsLocalTime().GetAsLocalizedTime("", false).c_str());
    }
    else
    {
        newTag->m_strSummary = tag->Plot();
    }

    newTag->m_epgTag = g_EpgContainer.GetById(tag->EpgID())->GetTag(tag->StartAsUTC());

    /* unused only for reference */
    newTag->m_strFileNameAndPath = "pvr://timers/new";

    return newTag;
}
Ejemplo n.º 16
0
CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag, bool bCreateRule /* = false */)
{
  /* create a new timer */
  CPVRTimerInfoTagPtr newTag(new CPVRTimerInfoTag());

  /* check if a valid channel is set */
  CPVRChannelPtr channel = tag->ChannelTag();
  if (!channel)
  {
    CLog::Log(LOGERROR, "%s - no channel set", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  /* check if the epg end date is in the future */
  if (tag->EndAsLocalTime() < CDateTime::GetCurrentDateTime() && !bCreateRule)
  {
    CLog::Log(LOGERROR, "%s - end time is in the past", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  /* set the timer data */
  CDateTime newStart = tag->StartAsUTC();
  CDateTime newEnd = tag->EndAsUTC();
  newTag->m_iClientIndex       = PVR_TIMER_NO_CLIENT_INDEX;
  newTag->m_iParentClientIndex = PVR_TIMER_NO_PARENT;
  newTag->m_strTitle           = tag->Title().empty() ? channel->ChannelName() : tag->Title();
  newTag->m_iChannelNumber     = channel->ChannelNumber();
  newTag->m_iClientChannelUid  = channel->UniqueID();
  newTag->m_iClientId          = channel->ClientID();
  newTag->m_bIsRadio           = channel->IsRadio();
  newTag->m_channel            = channel;
  newTag->m_iEpgUid            = tag->UniqueBroadcastID();
  newTag->SetStartFromUTC(newStart);
  newTag->SetEndFromUTC(newEnd);

  CPVRTimerTypePtr timerType;
  if (bCreateRule)
  {
    // create epg-based timer rule
    timerType = CPVRTimerType::CreateFromAttributes(
      PVR_TIMER_TYPE_IS_REPEATING,
      PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());

    if (timerType)
    {
      if (timerType->SupportsEpgTitleMatch())
        newTag->m_strEpgSearchString = newTag->m_strTitle;

      if (timerType->SupportsWeekdays())
        newTag->m_iWeekdays = PVR_WEEKDAY_ALLDAYS;

      if (timerType->SupportsStartAnyTime())
        newTag->m_bStartAnyTime = true;

      if (timerType->SupportsEndAnyTime())
        newTag->m_bEndAnyTime = true;
    }
  }
  else
  {
    // create one-shot epg-based timer
    timerType = CPVRTimerType::CreateFromAttributes(
      PVR_TIMER_TYPE_ATTRIBUTE_NONE,
      PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());
  }

  if (!timerType)
  {
    CLog::Log(LOGERROR, "%s - unable to create any epg-based timer type", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  newTag->SetTimerType(timerType);
  newTag->UpdateSummary();
  newTag->UpdateEpgInfoTag();

  /* unused only for reference */
  newTag->m_strFileNameAndPath = CPVRTimersPath::PATH_NEW;

  return newTag;
}
Ejemplo n.º 17
0
CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag, bool bRepeating /* = false */)
{
  /* create a new timer */
  CPVRTimerInfoTagPtr newTag(new CPVRTimerInfoTag());

  /* check if a valid channel is set */
  CPVRChannelPtr channel = tag->ChannelTag();
  if (!channel)
  {
    CLog::Log(LOGERROR, "%s - no channel set", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  /* check if the epg end date is in the future */
  if (tag->EndAsLocalTime() < CDateTime::GetCurrentDateTime())
  {
    CLog::Log(LOGERROR, "%s - end time is in the past", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  /* set the timer data */
  CDateTime newStart = tag->StartAsUTC();
  CDateTime newEnd = tag->EndAsUTC();
  newTag->m_iClientIndex       = -1;
  newTag->m_iParentClientIndex = PVR_TIMER_NO_PARENT;
  newTag->m_strTitle           = tag->Title().empty() ? channel->ChannelName() : tag->Title();
  newTag->m_iChannelNumber     = channel->ChannelNumber();
  newTag->m_iClientChannelUid  = channel->UniqueID();
  newTag->m_iClientId          = channel->ClientID();
  newTag->m_bIsRadio           = channel->IsRadio();
  newTag->m_iGenreType         = tag->GenreType();
  newTag->m_iGenreSubType      = tag->GenreSubType();
  newTag->m_channel            = channel;
  newTag->SetStartFromUTC(newStart);
  newTag->SetEndFromUTC(newEnd);

  CPVRTimerTypePtr timerType;
  if (bRepeating)
  {
    // create repeating epg-based timer
    timerType = CPVRTimerType::CreateFromAttributes(
      PVR_TIMER_TYPE_IS_REPEATING,
      PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());
  }
  if (!timerType)
  {
    // create one-shot epg-based timer
    timerType = CPVRTimerType::CreateFromAttributes(
      PVR_TIMER_TYPE_ATTRIBUTE_NONE,
      PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());
  }
  if (!timerType)
  {
    CLog::Log(LOGERROR, "%s - unable to create any epg-based timer type", __FUNCTION__);
    return CPVRTimerInfoTagPtr();
  }

  newTag->SetTimerType(timerType);
  newTag->UpdateSummary();
  newTag->m_epgTag = g_EpgContainer.GetById(tag->EpgID())->GetTag(tag->StartAsUTC());

  /* unused only for reference */
  newTag->m_strFileNameAndPath = CPVRTimersPath::PATH_NEW;

  return newTag;
}