Example #1
0
void CPVRManager::OnPlaybackStarted(const CFileItemPtr item)
{
  m_playingChannel.reset();
  m_playingRecording.reset();
  m_playingEpgTag.reset();

  if (item->HasPVRChannelInfoTag())
  {
    const CPVRChannelPtr channel(item->GetPVRChannelInfoTag());

    m_playingChannel = channel;
    SetPlayingGroup(channel);
    UpdateLastWatched(channel);
  }
  else if (item->HasPVRRecordingInfoTag())
  {
    m_playingRecording = item->GetPVRRecordingInfoTag();
  }
  else if (item->HasEPGInfoTag())
  {
    m_playingEpgTag = item->GetEPGInfoTag();
  }

  m_guiActions->OnPlaybackStarted(item);
}
Example #2
0
void CPVRManager::OnPlaybackStopped(const CFileItemPtr item)
{
  // Playback ended due to user interaction

  if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag() == m_playingChannel)
  {
    UpdateLastWatched(item->GetPVRChannelInfoTag());
    SetChanged();
    NotifyObservers(ObservableMessageChannelPlaybackStopped);

    m_playingChannel.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }
  else if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag() == m_playingRecording)
  {
    m_playingRecording.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }
  else if (item->HasEPGInfoTag() && item->GetEPGInfoTag() == m_playingEpgTag)
  {
    m_playingEpgTag.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }

  m_guiActions->OnPlaybackStopped(item);
}
Example #3
0
JSONRPC_STATUS CPVROperations::AddTimer(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
  if (!g_PVRManager.IsStarted())
    return FailedToExecute;

  CFileItemPtr broadcast = CPVROperations::GetBroadcastFromBroadcastid(parameterObject["broadcastid"].asUnsignedInteger());
  if (!broadcast)
    return InvalidParams;

  if (!broadcast->HasEPGInfoTag())
    return InvalidParams;

  CEpgInfoTagPtr epgTag = broadcast->GetEPGInfoTag();

  if (!epgTag)
    return InvalidParams;

  if (epgTag->HasTimer())
    return InvalidParams;

  CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(epgTag, parameterObject["timerrule"].asBoolean(false));
  if (newTimer)
  {
    if (g_PVRTimers->AddTimer(newTimer))
      return ACK;
  }
  return FailedToExecute;
}
Example #4
0
void CGUIWindowPVRSearch::GetContextButtons(int itemNumber, CContextButtons &buttons)
{
  if (itemNumber < 0 || itemNumber >= m_vecItems->Size())
    return;
  CFileItemPtr pItem = m_vecItems->Get(itemNumber);

  if (pItem->HasEPGInfoTag())
  {
    if (pItem->GetEPGInfoTag()->EndAsLocalTime() > CDateTime::GetCurrentDateTime())
    {
      if (!pItem->GetEPGInfoTag()->HasTimer())
      {
        if (pItem->GetEPGInfoTag()->StartAsLocalTime() < CDateTime::GetCurrentDateTime())
          buttons.Add(CONTEXT_BUTTON_START_RECORD, 264);   /* RECORD programme */
        else
          buttons.Add(CONTEXT_BUTTON_START_RECORD, 19061); /* Create a Timer */
      }
      else
      {
        if (pItem->GetEPGInfoTag()->StartAsLocalTime() < CDateTime::GetCurrentDateTime())
          buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19059); /* Stop recording */
        else
          buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19060); /* Delete Timer */
      }
    }

    buttons.Add(CONTEXT_BUTTON_INFO, 19047);              /* Epg info button */
    if (pItem->GetEPGInfoTag()->HasPVRChannel() &&
        g_PVRClients->HasMenuHooks(pItem->GetEPGInfoTag()->ChannelTag()->ClientID(), PVR_MENUHOOK_EPG))
      buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195);      /* PVR client specific action */
  }

  buttons.Add(CONTEXT_BUTTON_CLEAR, 19232);             /* Clear search results */
}
Example #5
0
void CGUIWindowPVRGuide::GetContextButtons(int itemNumber, CContextButtons &buttons)
{
  if (itemNumber < 0 || itemNumber >= m_vecItems->Size())
    return;
  CFileItemPtr pItem = m_vecItems->Get(itemNumber);

  buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 19000);         /* switch channel */

  if (pItem->HasEPGInfoTag() && pItem->GetEPGInfoTag()->HasRecording())
    buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 19687);      /* play recording */

  CFileItemPtr timer = g_PVRTimers->GetTimerForEpgTag(pItem.get());
  if (timer && timer->HasPVRTimerInfoTag())
  {
    if (timer->GetPVRTimerInfoTag()->IsRecording())
      buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19059);  /* stop recording */
    else if (timer->GetPVRTimerInfoTag()->HasTimerType() &&
             !timer->GetPVRTimerInfoTag()->GetTimerType()->IsReadOnly())
      buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19060);  /* delete timer */
  }
  else if (pItem->HasEPGInfoTag() && pItem->GetEPGInfoTag()->EndAsLocalTime() > CDateTime::GetCurrentDateTime())
  {
    if (pItem->GetEPGInfoTag()->StartAsLocalTime() < CDateTime::GetCurrentDateTime())
      buttons.Add(CONTEXT_BUTTON_START_RECORD, 264);   /* record */

    buttons.Add(CONTEXT_BUTTON_START_RECORD, 19061);   /* add timer */
    buttons.Add(CONTEXT_BUTTON_ADVANCED_RECORD, 841);  /* add custom timer */
  }

  buttons.Add(CONTEXT_BUTTON_INFO, 19047);              /* epg info */
  buttons.Add(CONTEXT_BUTTON_FIND, 19003);              /* find similar program */

  if (m_viewControl.GetCurrentControl() == GUIDE_VIEW_TIMELINE)
  {
    buttons.Add(CONTEXT_BUTTON_BEGIN, 19063);           /* go to begin */
    buttons.Add(CONTEXT_BUTTON_NOW, 19070);             /* go to now */
    buttons.Add(CONTEXT_BUTTON_END, 19064);             /* go to end */
  }

  if (pItem->HasEPGInfoTag() &&
      pItem->GetEPGInfoTag()->HasPVRChannel() &&
      g_PVRClients->HasMenuHooks(pItem->GetEPGInfoTag()->ChannelTag()->ClientID(), PVR_MENUHOOK_EPG))
    buttons.Add(CONTEXT_BUTTON_MENU_HOOKS, 19195);      /* PVR client specific action */

  CGUIWindowPVRBase::GetContextButtons(itemNumber, buttons);
  CContextMenuManager::Get().AddVisibleItems(pItem, buttons);
}
Example #6
0
void CPVRManager::OnPlaybackStarted(const CFileItemPtr item)
{
  m_playingChannel.reset();
  m_playingRecording.reset();
  m_playingEpgTag.reset();
  m_playingClientId = -1;
  m_strPlayingClientName.clear();

  if (item->HasPVRChannelInfoTag())
  {
    const CPVRChannelPtr channel(item->GetPVRChannelInfoTag());

    m_playingChannel = channel;
    m_playingClientId = m_playingChannel->ClientID();

    SetPlayingGroup(channel);

    int iLastWatchedDelay = m_settings.GetIntValue(CSettings::SETTING_PVRPLAYBACK_DELAYMARKLASTWATCHED) * 1000;
    if (iLastWatchedDelay > 0)
    {
      // Insert new / replace existing last watched update timer
      if (m_lastWatchedUpdateTimer)
        m_lastWatchedUpdateTimer->Stop(true);

      m_lastWatchedUpdateTimer.reset(new CLastWatchedUpdateTimer(*this, channel, CDateTime::GetUTCDateTime()));
      m_lastWatchedUpdateTimer->Start(iLastWatchedDelay);
    }
    else
    {
      // Store last watched timestamp immediately
      UpdateLastWatched(channel, CDateTime::GetUTCDateTime());
    }
  }
  else if (item->HasPVRRecordingInfoTag())
  {
    m_playingRecording = item->GetPVRRecordingInfoTag();
    m_playingClientId = m_playingRecording->m_iClientId;
  }
  else if (item->HasEPGInfoTag())
  {
    m_playingEpgTag = item->GetEPGInfoTag();
    m_playingClientId = m_playingEpgTag->ClientID();
  }

  if (m_playingClientId != -1)
  {
    const CPVRClientPtr client = GetClient(m_playingClientId);
    if (client)
      m_strPlayingClientName = client->GetFriendlyName();
  }

  m_guiActions->OnPlaybackStarted(item);
  m_epgContainer.OnPlaybackStarted(item);
}
Example #7
0
void CPVRManager::OnPlaybackStopped(const CFileItemPtr item)
{
  // Playback ended due to user interaction

  if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag() == m_playingChannel)
  {
    bool bUpdateLastWatched = true;

    if (m_lastWatchedUpdateTimer)
    {
      if (m_lastWatchedUpdateTimer->IsRunning())
      {
        // If last watched timer is still running, cancel it. Channel was not watched long enough to store the value.
        m_lastWatchedUpdateTimer->Stop(true);
        bUpdateLastWatched = false;
      }
      m_lastWatchedUpdateTimer.reset();
    }

    if (bUpdateLastWatched)
    {
      // If last watched timer is not running (any more), channel was watched long enough to store the value.
      UpdateLastWatched(m_playingChannel, CDateTime::GetUTCDateTime());
    }

    SetChanged();
    NotifyObservers(ObservableMessageChannelPlaybackStopped);

    m_playingChannel.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }
  else if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag() == m_playingRecording)
  {
    m_playingRecording.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }
  else if (item->HasEPGInfoTag() && item->GetEPGInfoTag() == m_playingEpgTag)
  {
    m_playingEpgTag.reset();
    m_playingClientId = -1;
    m_strPlayingClientName.clear();
  }

  m_guiActions->OnPlaybackStopped(item);
  m_epgContainer.OnPlaybackStopped(item);
}
Example #8
0
  bool CPVRGUIActions::ToggleTimer(const CFileItemPtr &item) const
  {
    if (!item->HasEPGInfoTag())
      return false;

    const CPVRTimerInfoTagPtr timer(CPVRItem(item).GetTimerInfoTag());
    if (timer)
    {
      if (timer->IsRecording())
        return StopRecording(item);
      else
        return DeleteTimer(item);
    }
    else
      return AddTimer(item, false);
  }
Example #9
0
CFileItemPtr CPVRTimers::GetTimerRule(const CFileItemPtr &item) const
{
  CPVRTimerInfoTagPtr timer;
  if (item && item->HasEPGInfoTag())
    timer = GetTimerForEpgTag(item->GetEPGInfoTag());
  else if (item && item->HasPVRTimerInfoTag())
    timer = item->GetPVRTimerInfoTag();

  if (timer)
  {
    timer = GetTimerRule(timer);
    if (timer)
      return CFileItemPtr(new CFileItem(timer));
  }
  return CFileItemPtr();
}
Example #10
0
void CPVRManager::OnPlaybackStopped(const CFileItemPtr item)
{
  // Playback ended due to user interaction

  if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag() == m_playingChannel)
  {
    UpdateLastWatched(item->GetPVRChannelInfoTag());
    m_playingChannel.reset();
  }
  else if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag() == m_playingRecording)
  {
    m_playingRecording.reset();
  }
  else if (item->HasEPGInfoTag() && item->GetEPGInfoTag() == m_playingEpgTag)
  {
    m_playingEpgTag.reset();
  }

  m_guiActions->OnPlaybackStopped(item);
}
Example #11
0
JSONRPC_STATUS CPVROperations::ToggleTimer(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
  if (!g_PVRManager.IsStarted())
    return FailedToExecute;

  CFileItemPtr broadcast = CPVROperations::GetBroadcastFromBroadcastid(parameterObject["broadcastid"].asUnsignedInteger());
  if (!broadcast)
    return InvalidParams;

  if (!broadcast->HasEPGInfoTag())
    return InvalidParams;

  CEpgInfoTagPtr epgTag = broadcast->GetEPGInfoTag();

  if (!epgTag)
    return InvalidParams;

  bool timerrule = parameterObject["timerrule"].asBoolean(false);
  bool sentOkay = false;
  CPVRTimerInfoTagPtr timer(epgTag->Timer());
  if (timer)
  {
    if (timerrule)
      timer = g_PVRTimers->GetTimerRule(timer);

    if (timer)
      sentOkay = g_PVRTimers->DeleteTimer(timer, timer->IsRecording(), false);
  }
  else
  {
    timer = CPVRTimerInfoTag::CreateFromEpg(epgTag, timerrule);
    sentOkay = g_PVRTimers->AddTimer(timer);
  }

  if (sentOkay)
    return ACK;

  return FailedToExecute;
}
Example #12
0
void CPVRManager::OnPlaybackStarted(const CFileItemPtr item)
{
  m_playingChannel.reset();
  m_playingRecording.reset();
  m_playingEpgTag.reset();
  m_playingClientId = -1;
  m_strPlayingClientName.clear();

  if (item->HasPVRChannelInfoTag())
  {
    const CPVRChannelPtr channel(item->GetPVRChannelInfoTag());

    m_playingChannel = channel;
    m_playingClientId = m_playingChannel->ClientID();

    SetPlayingGroup(channel);
    UpdateLastWatched(channel);
  }
  else if (item->HasPVRRecordingInfoTag())
  {
    m_playingRecording = item->GetPVRRecordingInfoTag();
    m_playingClientId = m_playingRecording->m_iClientId;
  }
  else if (item->HasEPGInfoTag())
  {
    m_playingEpgTag = item->GetEPGInfoTag();
    m_playingClientId = m_playingEpgTag->ClientID();
  }

  if (m_playingClientId != -1)
  {
    const CPVRClientPtr client = GetClient(m_playingClientId);
    if (client)
      m_strPlayingClientName = client->GetFriendlyName();
  }

  m_guiActions->OnPlaybackStarted(item);
}
Example #13
0
void CGUIDialogPVRGuideOSD::OnInitWindow()
{
  /* Close dialog immediately if no TV or radio channel is playing */
  if (!g_PVRManager.IsPlaying())
  {
    Close();
    return;
  }

  // lock our display, as this window is rendered from the player thread
  g_graphicsContext.Lock();
  m_viewControl.SetCurrentView(DEFAULT_VIEW_LIST);

  // empty the list ready for population
  Clear();

  g_PVRManager.GetCurrentEpg(*m_vecItems);
  m_viewControl.SetItems(*m_vecItems);

  g_graphicsContext.Unlock();

  // call init
  CGUIDialog::OnInitWindow();

  // select the active entry
  unsigned int iSelectedItem = 0;
  for (int iEpgPtr = 0; iEpgPtr < m_vecItems->Size(); iEpgPtr++)
  {
    CFileItemPtr entry = m_vecItems->Get(iEpgPtr);
    if (entry->HasEPGInfoTag() && entry->GetEPGInfoTag()->IsActive())
    {
      iSelectedItem = iEpgPtr;
      break;
    }
  }
  m_viewControl.SetSelectedItem(iSelectedItem);
}
Example #14
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++;
      }
    }
  }
}
void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char *resultname, CFileItemPtr item, const CVariant &parameterObject, const std::set<std::string> &validFields, CVariant &result, bool append /* = true */, CThumbLoader *thumbLoader /* = NULL */)
{
  CVariant object;
  std::set<std::string> fields(validFields.begin(), validFields.end());

  if (item.get())
  {
    std::set<std::string>::const_iterator fileField = fields.find("file");
    if (fileField != fields.end())
    {
      if (allowFile)
      {
        if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->GetPath().empty())
          object["file"] = item->GetVideoInfoTag()->GetPath().c_str();
        if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetURL().empty())
          object["file"] = item->GetMusicInfoTag()->GetURL().c_str();
        if (item->HasPVRRecordingInfoTag() && !item->GetPVRRecordingInfoTag()->GetPath().empty())
          object["file"] = item->GetPVRRecordingInfoTag()->GetPath().c_str();
        if (item->HasPVRTimerInfoTag() && !item->GetPVRTimerInfoTag()->m_strFileNameAndPath.empty())
          object["file"] = item->GetPVRTimerInfoTag()->m_strFileNameAndPath.c_str();

        if (!object.isMember("file"))
          object["file"] = item->GetPath().c_str();
      }
      fields.erase(fileField);
    }

    if (ID)
    {
      if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag()->ChannelID() > 0)
         object[ID] = item->GetPVRChannelInfoTag()->ChannelID();
      else if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->UniqueBroadcastID() > 0)
         object[ID] = item->GetEPGInfoTag()->UniqueBroadcastID();
      else if (item->HasPVRRecordingInfoTag() && item->GetPVRRecordingInfoTag()->m_iRecordingId > 0)
         object[ID] = item->GetPVRRecordingInfoTag()->m_iRecordingId;
      else if (item->HasPVRTimerInfoTag() && item->GetPVRTimerInfoTag()->m_iTimerId > 0)
         object[ID] = item->GetPVRTimerInfoTag()->m_iTimerId;
      else if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > 0)
        object[ID] = (int)item->GetMusicInfoTag()->GetDatabaseId();
      else if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > 0)
        object[ID] = item->GetVideoInfoTag()->m_iDbId;

      if (stricmp(ID, "id") == 0)
      {
        if (item->HasPVRChannelInfoTag())
          object["type"] = "channel";
        else if (item->HasMusicInfoTag())
        {
          std::string type = item->GetMusicInfoTag()->GetType();
          if (type == MediaTypeAlbum || type == MediaTypeSong || type == MediaTypeArtist)
            object["type"] = type;
          else if (!item->m_bIsFolder)
            object["type"] = MediaTypeSong;
        }
        else if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_type.empty())
        {
          std::string type = item->GetVideoInfoTag()->m_type;
          if (type == MediaTypeMovie || type == MediaTypeTvShow || type == MediaTypeEpisode || type == MediaTypeMusicVideo)
            object["type"] = type;
        }
        else if (item->HasPictureInfoTag())
          object["type"] = "picture";

        if (!object.isMember("type"))
          object["type"] = "unknown";

        if (fields.find("filetype") != fields.end())
        {
          if (item->m_bIsFolder)
            object["filetype"] = "directory";
          else 
            object["filetype"] = "file";
        }
      }
    }

    bool deleteThumbloader = false;
    if (thumbLoader == NULL)
    {
      if (item->HasVideoInfoTag())
        thumbLoader = new CVideoThumbLoader();
      else if (item->HasMusicInfoTag())
        thumbLoader = new CMusicThumbLoader();

      if (thumbLoader != NULL)
      {
        deleteThumbloader = true;
        thumbLoader->OnLoaderStart();
      }
    }

    if (item->HasPVRChannelInfoTag())
      FillDetails(item->GetPVRChannelInfoTag().get(), item, fields, object, thumbLoader);
    if (item->HasEPGInfoTag())
      FillDetails(item->GetEPGInfoTag().get(), item, fields, object, thumbLoader);
    if (item->HasPVRRecordingInfoTag())
      FillDetails(item->GetPVRRecordingInfoTag().get(), item, fields, object, thumbLoader);
    if (item->HasPVRTimerInfoTag())
      FillDetails(item->GetPVRTimerInfoTag().get(), item, fields, object, thumbLoader);
    if (item->HasVideoInfoTag())
      FillDetails(item->GetVideoInfoTag(), item, fields, object, thumbLoader);
    if (item->HasMusicInfoTag())
      FillDetails(item->GetMusicInfoTag(), item, fields, object, thumbLoader);
    if (item->HasPictureInfoTag())
      FillDetails(item->GetPictureInfoTag(), item, fields, object, thumbLoader);
    
    FillDetails(item.get(), item, fields, object, thumbLoader);

    if (deleteThumbloader)
      delete thumbLoader;

    object["label"] = item->GetLabel().c_str();
  }
  else
    object = CVariant(CVariant::VariantTypeNull);

  if (resultname)
  {
    if (append)
      result[resultname].append(object);
    else
      result[resultname] = object;
  }
}