Esempio n. 1
0
CCdInfo* CCdIoSupport::GetCdInfo(char* cDeviceFileName)
{
  CSingleLock lock(*m_cdio);

  char* source_name;
  if(cDeviceFileName == NULL)
    source_name = m_cdio->GetDeviceFileName();
  else
    source_name = cDeviceFileName;

  cdio = ::cdio_open(source_name, DRIVER_UNKNOWN);
  if (cdio == NULL)
  {
    CLog::Log(LOGERROR, "%s: Error in automatically selecting driver with input", __FUNCTION__);
    return NULL;
  }

  bool bIsCDRom = true;

  m_nFirstTrackNum = ::cdio_get_first_track_num(cdio);
  if (m_nFirstTrackNum == CDIO_INVALID_TRACK)
  {
#if !defined(TARGET_DARWIN)
    ::cdio_destroy(cdio);
    return NULL;
#else
    m_nFirstTrackNum = 1;
    bIsCDRom = false;
#endif
  }

  m_nNumTracks = ::cdio_get_num_tracks(cdio);
  if (m_nNumTracks == CDIO_INVALID_TRACK)
  {
#if !defined(TARGET_DARWIN)
    ::cdio_destroy(cdio);
    return NULL;
#else
    m_nNumTracks = 1;
    bIsCDRom = false;
#endif
  }

  CCdInfo* info = new CCdInfo;
  info->SetFirstTrack( m_nFirstTrackNum );
  info->SetTrackCount( m_nNumTracks );

  for (i = m_nFirstTrackNum; i <= CDIO_CDROM_LEADOUT_TRACK; i++)
  {
    msf_t msf;
    if (bIsCDRom && !::cdio_get_track_msf(cdio, i, &msf))
    {
      trackinfo ti;
      ti.nfsInfo = FS_UNKNOWN;
      ti.ms_offset = 0;
      ti.isofs_size = 0;
      ti.nJolietLevel = 0;
      ti.nFrames = 0;
      ti.nMins = 0;
      ti.nSecs = 0;
      info->SetTrackInformation( i, ti );
      CLog::Log(LOGDEBUG, "cdio_track_msf for track %i failed, I give up.", i);
      delete info;
      ::cdio_destroy(cdio);
      return NULL;
    }

    trackinfo ti;
    if (bIsCDRom && TRACK_FORMAT_AUDIO == ::cdio_get_track_format(cdio, i))
    {
      m_nNumAudio++;
      ti.nfsInfo = FS_NO_DATA;
      m_nFs = FS_NO_DATA;
      int temp1 = ::cdio_get_track_lba(cdio, i) - CDIO_PREGAP_SECTORS;
      int temp2 = ::cdio_get_track_lba(cdio, i + 1) - CDIO_PREGAP_SECTORS;
      // The length is the address of the second track minus the address of the first track
      temp2 -= temp1;                  // temp2 now has length of track1 in frames
      ti.nMins = temp2 / (60 * 75);    // calculate the number of minutes
      temp2 %= 60 * 75;                // calculate the left-over frames
      ti.nSecs = temp2 / 75;           // calculate the number of seconds
      if ( -1 == m_nFirstAudio)
        m_nFirstAudio = i;

      // Make sure that we have the Disc related info available
      if (i == 1)
      {
        xbmc_cdtext_t xcdt;
        GetCdTextInfo(xcdt, 0);
        info->SetDiscCDTextInformation( xcdt );
      }

      // Get this tracks info
      GetCdTextInfo(ti.cdtext, i);
    }
    else
    {
      m_nNumData++;
      if ( -1 == m_nFirstData)
        m_nFirstData = i;
    }
    ti.nfsInfo = FS_NO_DATA;
    ti.ms_offset = 0;
    ti.isofs_size = 0;
    ti.nJolietLevel = 0;
    ti.nFrames = ::cdio_get_track_lba(cdio, i);
    ti.nMins = 0;
    ti.nSecs = 0;

    info->SetTrackInformation( i, ti );
    /* skip to leadout? */
    if (i == m_nNumTracks)
      i = CDIO_CDROM_LEADOUT_TRACK;
  }

  info->SetCddbDiscId( CddbDiscId() );
  info->SetDiscLength( ::cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC );

  info->SetAudioTrackCount( m_nNumAudio );
  info->SetDataTrackCount( m_nNumData );
  info->SetFirstAudioTrack( m_nFirstAudio );
  info->SetFirstDataTrack( m_nFirstData );

  CLog::Log(LOGINFO, "CD Analysis Report");
  CLog::Log(LOGINFO, STRONG);

  /* Try to find out what sort of CD we have */
  if (0 == m_nNumData)
  {
    /* no data track, may be a "real" audio CD or hidden track CD */

    msf_t msf;
    ::cdio_get_track_msf(cdio, 1, &msf);
    m_nStartTrack = ::cdio_msf_to_lsn(&msf);

    /* CD-I/Ready says start_track <= 30*75 then CDDA */
    if (m_nStartTrack > 100 /* 100 is just a guess */)
    {
      m_nFs = GuessFilesystem(0, 1);
      if ((m_nFs & FS_MASK) != FS_UNKNOWN)
        m_nFs |= HIDDEN_TRACK;
      else
      {
        m_nFs &= ~FS_MASK; /* del filesystem info */
        CLog::Log(LOGDEBUG, "Oops: %i unused sectors at start, but hidden track check failed.", m_nStartTrack);
      }
    }
    PrintAnalysis(m_nFs, m_nNumAudio);
  }
  else
  {
    /* We have data track(s) */
    for (j = 2, i = m_nFirstData; i <= m_nNumTracks; i++)
    {
      msf_t msf;
      track_format_t track_format = ::cdio_get_track_format(cdio, i);

      ::cdio_get_track_msf(cdio, i, &msf);

      switch ( track_format )
      {
      case TRACK_FORMAT_AUDIO:
        {
          trackinfo ti;
          ti.nfsInfo = FS_NO_DATA;
          m_nFs = FS_NO_DATA;
          ti.ms_offset = 0;
          ti.isofs_size = 0;
          ti.nJolietLevel = 0;
          ti.nFrames = ::cdio_get_track_lba(cdio, i);
          ti.nMins = 0;
          ti.nSecs = 0;
          info->SetTrackInformation( i + 1, ti );
        }
      case TRACK_FORMAT_ERROR:
        break;
      case TRACK_FORMAT_CDI:
      case TRACK_FORMAT_XA:
      case TRACK_FORMAT_DATA:
      case TRACK_FORMAT_PSX:
        break;
      }

      m_nStartTrack = (i == 1) ? 0 : ::cdio_msf_to_lsn(&msf);

      /* Save the start of the data area */
      if (i == m_nFirstData)
        m_nDataStart = m_nStartTrack;

      /* Skip tracks which belong to the current walked session */
      if (m_nStartTrack < m_nDataStart + m_nIsofsSize)
        continue;

      m_nFs = GuessFilesystem(m_nStartTrack, i);
      trackinfo ti;
      ti.nfsInfo = m_nFs;
      ti.ms_offset = m_nMsOffset;
      ti.isofs_size = m_nIsofsSize;
      ti.nJolietLevel = m_nJolietLevel;
      ti.nFrames = ::cdio_get_track_lba(cdio, i);
      ti.nMins = 0;
      ti.nSecs = 0;
      info->SetDiscLabel(m_strDiscLabel);


      if (i > 1)
      {
        /* Track is beyond last session -> new session found */
        m_nMsOffset = m_nStartTrack;

        CLog::Log(LOGINFO, "Session #%d starts at track %2i, LSN: %6i,"
                  " ISO 9660 blocks: %6i",
                  j++, i, m_nStartTrack, m_nIsofsSize);

        CLog::Log(LOGINFO, "ISO 9660: %i blocks, label %s",
                  m_nIsofsSize, m_strDiscLabel.c_str());
        m_nFs |= MULTISESSION;
        ti.nfsInfo = m_nFs;
      }
      else
      {
        PrintAnalysis(m_nFs, m_nNumAudio);
      }

      info->SetTrackInformation( i, ti );

    }
  }
  ::cdio_destroy( cdio );
  return info;
}
Esempio n. 2
0
CCdInfo* CCdIoSupport::GetCdInfo(char* cDeviceFileName)
{
  CSingleLock lock(*m_cdio);

  char* source_name;
  if(cDeviceFileName == NULL)
    source_name = m_cdio->GetDeviceFileName();
  else
    source_name = cDeviceFileName;

  cdio = ::cdio_open(source_name, DRIVER_UNKNOWN);
  if (cdio == NULL)
  {
    char buf[1024];
    sprintf(buf, "%s: Error in automatically selecting driver with input\n",
            __FUNCTION__);
    OutputDebugString( buf );
    return NULL;
  }

  bool bIsCDRom = true;

  m_nFirstTrackNum = ::cdio_get_first_track_num(cdio);
  if (m_nFirstTrackNum == CDIO_INVALID_TRACK)
  {
#ifndef __APPLE__
    ::cdio_destroy(cdio);
    return NULL;
#else
    m_nFirstTrackNum = 1;
    bIsCDRom = false;
#endif
  }

  m_nNumTracks = ::cdio_get_num_tracks(cdio);
  if (m_nNumTracks == CDIO_INVALID_TRACK)
  {
#ifndef __APPLE__
    ::cdio_destroy(cdio);
    return NULL;
#else
    m_nNumTracks = 1;
    bIsCDRom = false;
#endif
  }

  CCdInfo* info = new CCdInfo;
  info->SetFirstTrack( m_nFirstTrackNum );
  info->SetTrackCount( m_nNumTracks );

  for (i = m_nFirstTrackNum; i <= CDIO_CDROM_LEADOUT_TRACK; i++)
  {
    msf_t msf;
    if (bIsCDRom && !::cdio_get_track_msf(cdio, i, &msf))
    {
      char buf[1024];
      trackinfo ti;
      ti.nfsInfo = FS_UNKNOWN;
      ti.ms_offset = 0;
      ti.isofs_size = 0;
      ti.nJolietLevel = 0;
      ti.nFrames = 0;
      cdtext_init(&ti.cdtext);
      info->SetTrackInformation( i, ti );
      sprintf( buf, "cdio_track_msf for track %i failed, I give up.\n", i);
      OutputDebugString( buf );
      delete info;
      ::cdio_destroy(cdio);
      return NULL;
    }

    trackinfo ti_0, ti;
    cdtext_init(&ti_0.cdtext);
    cdtext_init(&ti.cdtext);
    if (bIsCDRom && TRACK_FORMAT_AUDIO == ::cdio_get_track_format(cdio, i))
    {
      m_nNumAudio++;
      ti.nfsInfo = FS_NO_DATA;
      m_nFs = FS_NO_DATA;
      int temp1 = ::cdio_get_track_lba(cdio, i) - CDIO_PREGAP_SECTORS;
      int temp2 = ::cdio_get_track_lba(cdio, i + 1) - CDIO_PREGAP_SECTORS;
      // the length is the address of the second track minus the address of the first track
      temp2 -= temp1;    // temp2 now has length of track1 in frames
      ti.nMins = temp2 / (60 * 75);    // calculate the number of minutes
      temp2 %= 60 * 75;    // calculate the left-over frames
      ti.nSecs = temp2 / 75;    // calculate the number of seconds
      if ( -1 == m_nFirstAudio)
        m_nFirstAudio = i;

      // Make sure that we have the Disc related info available
      if (i == 1)
      {
        GetCdTextInfo(&ti_0, 0);
        info->SetDiscCDTextInformation( ti_0.cdtext );
      }

      // Get this tracks info
      GetCdTextInfo(&ti, i);
    }
    else
    {
      m_nNumData++;
      if ( -1 == m_nFirstData)
        m_nFirstData = i;
    }
    ti.ms_offset = 0;
    ti.isofs_size = 0;
    ti.nJolietLevel = 0;
    ti.nFrames = ::cdio_get_track_lba(cdio, i);
    info->SetTrackInformation( i, ti );
    /* skip to leadout? */
    if (i == m_nNumTracks)
      i = CDIO_CDROM_LEADOUT_TRACK;
  }

  info->SetCddbDiscId( CddbDiscId() );
  info->SetDiscLength( ::cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC );

  info->SetAudioTrackCount( m_nNumAudio );
  info->SetDataTrackCount( m_nNumData );
  info->SetFirstAudioTrack( m_nFirstAudio );
  info->SetFirstDataTrack( m_nFirstData );

  char buf[1024];
  CLog::Log(LOGINFO, "CD Analysis Report");
  CLog::Log(LOGINFO, STRONG);

  /* try to find out what sort of CD we have */
  if (0 == m_nNumData)
  {
    /* no data track, may be a "real" audio CD or hidden track CD */

    msf_t msf;
    ::cdio_get_track_msf(cdio, 1, &msf);
    m_nStartTrack = ::cdio_msf_to_lsn(&msf);

    /* CD-I/Ready says start_track <= 30*75 then CDDA */
    if (m_nStartTrack > 100 /* 100 is just a guess */)
    {
      m_nFs = GuessFilesystem(0, 1);
      if ((m_nFs & FS_MASK) != FS_UNKNOWN)
        m_nFs |= HIDDEN_TRACK;
      else
      {
        m_nFs &= ~FS_MASK; /* del filesystem info */
        sprintf(buf, "Oops: %i unused sectors at start, "
                "but hidden track check failed.\n",
                m_nStartTrack);
        OutputDebugString( buf );
      }
    }
    PrintAnalysis(m_nFs, m_nNumAudio);
  }
  else
  {
    /* we have data track(s) */
    for (j = 2, i = m_nFirstData; i <= m_nNumTracks; i++)
    {
      msf_t msf;
      track_format_t track_format = ::cdio_get_track_format(cdio, i);

      ::cdio_get_track_msf(cdio, i, &msf);

      switch ( track_format )
      {
      case TRACK_FORMAT_AUDIO:
        trackinfo ti;
        ti.nfsInfo = FS_NO_DATA;
        m_nFs = FS_NO_DATA;
        ti.ms_offset = 0;
        ti.isofs_size = 0;
        ti.nJolietLevel = 0;
        ti.nFrames = ::cdio_get_track_lba(cdio, i);
        cdtext_init(&ti.cdtext);
        info->SetTrackInformation( i + 1, ti );
      case TRACK_FORMAT_ERROR:
        break;
      case TRACK_FORMAT_CDI:
      case TRACK_FORMAT_XA:
      case TRACK_FORMAT_DATA:
      case TRACK_FORMAT_PSX:
        break;
      }

      m_nStartTrack = (i == 1) ? 0 : ::cdio_msf_to_lsn(&msf);

      /* save the start of the data area */
      if (i == m_nFirstData)
        m_nDataStart = m_nStartTrack;

      /* skip tracks which belong to the current walked session */
      if (m_nStartTrack < m_nDataStart + m_nIsofsSize)
        continue;

      m_nFs = GuessFilesystem(m_nStartTrack, i);
      trackinfo ti;
      cdtext_init(&ti.cdtext);
      ti.nfsInfo = m_nFs;
      // valid UDF version for xbox
      if ((m_nFs & FS_MASK) == FS_UDF)
      {
        // Is UDF 1.02
        if (m_nUDFVerMajor > 0x1)
        {
          ti.nfsInfo = FS_UNKNOWN;
          m_strDiscLabel.Empty();
        }
        else if (m_nUDFVerMinor > 0x2)
        {
          ti.nfsInfo = FS_UNKNOWN;
          m_strDiscLabel.Empty();
        }
      }

      if ((m_nFs & FS_MASK) == FS_ISO_UDF)
      {
        // fallback to iso9660 if not udf 1.02
        if (m_nUDFVerMajor > 0x1)
          ti.nfsInfo = FS_ISO_9660;
        else if (m_nUDFVerMinor > 0x2)
          ti.nfsInfo = FS_ISO_9660;
      }

      ti.ms_offset = m_nMsOffset;
      ti.isofs_size = m_nIsofsSize;
      ti.nJolietLevel = m_nJolietLevel;
      ti.nFrames = ::cdio_get_track_lba(cdio, i);
      info->SetDiscLabel(m_strDiscLabel);


      if (i > 1)
      {
        /* track is beyond last session -> new session found */
        m_nMsOffset = m_nStartTrack;

        CLog::Log(LOGINFO, "Session #%d starts at track %2i, LSN: %6i,"
                  " ISO 9660 blocks: %6i",
                  j++, i, m_nStartTrack, m_nIsofsSize);

        CLog::Log(LOGINFO, "ISO 9660: %i blocks, label '%.32s'\n",
                  m_nIsofsSize, buffer[0] + 40);
        m_nFs |= MULTISESSION;
        ti.nfsInfo = m_nFs;
      }
      else
      {
        PrintAnalysis(m_nFs, m_nNumAudio);
      }

      info->SetTrackInformation( i, ti );

      // xbox does not support multisession cd's
      if (!(((m_nFs & FS_MASK) == FS_ISO_9660 ||
             (m_nFs & FS_MASK) == FS_ISO_HFS ||
             /* (fs & FS_MASK) == FS_ISO_9660_INTERACTIVE) && (fs & XA))) */
             (m_nFs & FS_MASK) == FS_ISO_9660_INTERACTIVE)))
        break; /* no method for non-iso9660 multisessions */
    }
  }
  ::cdio_destroy( cdio );
  return info;
}