Repository: xbmc/xbmc
File: xbmc/pvr/PVRPlaybackState.cpp (C++)

Code before:
{
  // Obtain dynamic playback url and properties from the respective pvr client
  const std::shared_ptr<const CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
  if (client)
  {
    CPVRStreamProperties props;

    if (item->IsPVRChannel())
    {
      if (source == PVR_SOURCE::DEFAULT)
      {
        PVR_ERROR retVal = client->StreamClosed();
        if (retVal != PVR_ERROR_NO_ERROR)
          CLog::LogFC(LOGERROR, LOGPVR, "Client error on call to StreamClosed(): {}",
                      CPVRClient::ToString(retVal));
      }

      client->GetChannelStreamProperties(item->GetPVRChannelInfoTag(), source, props);

      if (props.LivePlaybackAsEPG())
      {
        const std::shared_ptr<CPVREpgInfoTag> epgTag = item->GetPVRChannelInfoTag()->GetEPGNow();
        if (epgTag)
        {
          delete item;
          item = new CFileItem(epgTag);
        }
      }
    }
    else if (item->IsPVRRecording())
    {
      client->GetRecordingStreamProperties(item->GetPVRRecordingInfoTag(), props);
    }
    else if (item->IsEPG())
    {
      PVR_ERROR retVal = client->StreamClosed();
      if (retVal != PVR_ERROR_NO_ERROR)
        CLog::LogFC(LOGERROR, LOGPVR, "Client error on call to StreamClosed(): {}",
                    CPVRClient::ToString(retVal));

      client->GetEpgTagStreamProperties(item->GetEPGInfoTag(), props);

      if (mode == ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM)
      {
        if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
                CSettings::SETTING_PVRPLAYBACK_AUTOPLAYNEXTPROGRAMME))
          item->SetProperty("epg_playlist_item", true);
      }
      else if (mode == ContentUtils::PlayMode::PLAY_FROM_HERE)
      {
        item->SetProperty("epg_playlist_item", true);

Review comment (bug):
Although it works, this is so ugly. `item` is handed in from outside this method. If you delete it here and the calling method later on accesses the pointer - which currently is not the case but can change anytime  - this will crash.

Not sure how to solve this best. Maybe change method signature to take a `CFileItem*& item`? So the caller at least will automatically get the new item.

Code after:
{
  // Obtain dynamic playback url and properties from the respective pvr client
  const std::shared_ptr<const CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(*item);
  if (client)
  {
    CPVRStreamProperties props;

    if (item->IsPVRChannel())
    {
      if (source == PVR_SOURCE::DEFAULT)
      {
        PVR_ERROR retVal = client->StreamClosed();
        if (retVal != PVR_ERROR_NO_ERROR)
          CLog::LogFC(LOGERROR, LOGPVR, "Client error on call to StreamClosed(): {}",
                      CPVRClient::ToString(retVal));
      }

      client->GetChannelStreamProperties(item->GetPVRChannelInfoTag(), source, props);

      if (props.LivePlaybackAsEPG())
      {
        const std::shared_ptr<CPVREpgInfoTag> epgTag = item->GetPVRChannelInfoTag()->GetEPGNow();
        if (epgTag)
        {
          item = std::make_unique<CFileItem>(epgTag);
        }
      }
    }
    else if (item->IsPVRRecording())
    {
      client->GetRecordingStreamProperties(item->GetPVRRecordingInfoTag(), props);
    }
    else if (item->IsEPG())
    {
      PVR_ERROR retVal = client->StreamClosed();
      if (retVal != PVR_ERROR_NO_ERROR)
        CLog::LogFC(LOGERROR, LOGPVR, "Client error on call to StreamClosed(): {}",
                    CPVRClient::ToString(retVal));

      client->GetEpgTagStreamProperties(item->GetEPGInfoTag(), props);

      if (mode == ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM)
      {
        if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
                CSettings::SETTING_PVRPLAYBACK_AUTOPLAYNEXTPROGRAMME))
          item->SetProperty("epg_playlist_item", true);
      }
      else if (mode == ContentUtils::PlayMode::PLAY_FROM_HERE)
      {
        item->SetProperty("epg_playlist_item", true);
      }