Exemplo n.º 1
0
 MPCReader(FILE *fp)
 {
	fseek(fp, 0, SEEK_SET);
	lseek(fileno(fp), 0, SEEK_SET);

	memset(&MPCReaderFile, 0, sizeof(MPCReaderFile));
	memset(&MPCStreamInfo, 0, sizeof(MPCStreamInfo));
	memset(&MPCDecoder, 0, sizeof(MPCDecoder));
	memset(MPCBuffer, 0, sizeof(MPCBuffer));

	mpc_streaminfo_init(&MPCStreamInfo);
	mpc_reader_setup_file_reader(&MPCReaderFile, fp);

        if(mpc_streaminfo_read(&MPCStreamInfo, &MPCReaderFile.reader) != ERROR_CODE_OK)
        {
         throw(0);
        }

        mpc_decoder_setup(&MPCDecoder, &MPCReaderFile.reader);
        if(!mpc_decoder_initialize(&MPCDecoder, &MPCStreamInfo))
        {
         MDFN_printf(_("Error initializing MusePack decoder!\n"));
         throw(0);
        }
 }
Exemplo n.º 2
0
static gboolean
xmms_mpc_init (xmms_xform_t *xform)
{
    xmms_mpc_data_t *data;
    xmms_error_t error;

    data = g_new0 (xmms_mpc_data_t, 1);
    xmms_xform_private_data_set (xform, data);

    if (!xmms_apetag_read (xform)) {
        XMMS_DBG ("Failed to read APEv2 tag");
    }

    /* Reset to start after reading the tags */
    xmms_error_reset (&error);
    xmms_xform_seek (xform, 0, XMMS_XFORM_SEEK_SET, &error);

    data->buffer = g_string_new (NULL);

    data->reader.read = xmms_mpc_callback_read;
    data->reader.seek = xmms_mpc_callback_seek;
    data->reader.tell = xmms_mpc_callback_tell;
    data->reader.canseek = xmms_mpc_callback_canseek;
    data->reader.get_size = xmms_mpc_callback_get_size;

    data->reader.data = xform;

#ifdef HAVE_MPCDEC_OLD
    mpc_streaminfo_init (&data->info);
    if (mpc_streaminfo_read (&data->info, &data->reader) != ERROR_CODE_OK)
        return FALSE;

    mpc_decoder_setup (&data->decoder, &data->reader);

    if (mpc_decoder_initialize (&data->decoder, &data->info) == FALSE)
        return FALSE;
#else
    data->demux = mpc_demux_init (&data->reader);
    if (!data->demux) return FALSE;

    mpc_demux_get_info (data->demux,  &data->info);
#endif

    xmms_mpc_cache_streaminfo (xform);

    xmms_xform_outdata_type_add (xform,
                                 XMMS_STREAM_TYPE_MIMETYPE,
                                 "audio/pcm",
                                 XMMS_STREAM_TYPE_FMT_FORMAT,
                                 XMMS_SAMPLE_FORMAT_FLOAT,
                                 XMMS_STREAM_TYPE_FMT_CHANNELS,
                                 data->info.channels,
                                 XMMS_STREAM_TYPE_FMT_SAMPLERATE,
                                 data->info.sample_freq,
                                 XMMS_STREAM_TYPE_END);

    return TRUE;
}
Exemplo n.º 3
0
static gboolean
xmms_mpc_init (xmms_xform_t *xform)
{
	xmms_mpc_data_t *data;

	data = g_new0 (xmms_mpc_data_t, 1);
	xmms_xform_private_data_set (xform, data);

	xmms_mpc_collect_metadata (xform);


	data->buffer = g_string_new (NULL);

	data->reader.read = xmms_mpc_callback_read;
	data->reader.seek = xmms_mpc_callback_seek;
	data->reader.tell = xmms_mpc_callback_tell;
	data->reader.canseek = xmms_mpc_callback_canseek;
	data->reader.get_size = xmms_mpc_callback_get_size;

	data->reader.data = xform;

#ifdef HAVE_MPCDEC_OLD
	mpc_streaminfo_init (&data->info);
	if (mpc_streaminfo_read (&data->info, &data->reader) != ERROR_CODE_OK)
		return FALSE;

	mpc_decoder_setup (&data->decoder, &data->reader);

	if (mpc_decoder_initialize (&data->decoder, &data->info) == FALSE)
		return FALSE;
#else
	data->demux = mpc_demux_init (&data->reader);
	if (!data->demux) return FALSE;

	mpc_demux_get_info (data->demux,  &data->info);
#endif

	xmms_mpc_cache_streaminfo (xform);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_FLOAT,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->info.channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->info.sample_freq,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Exemplo n.º 4
0
int decoder_load(unsigned long id, const string sname)
{

    pstreams[id].stream.file  = _wfopen(sname, uni("rb"));

	if(!pstreams[id].stream.file) return 0;


    pstreams[id].stream.seekable = 1;
	
	fseek(pstreams[id].stream.file, 0, SEEK_END);
	pstreams[id].stream.size = ftell(pstreams[id].stream.file); 
    fseek(pstreams[id].stream.file, 0, SEEK_SET);

    /* set up an mpc_reader linked to our function implementations */
    
    pstreams[id].reader.read     = read_impl;
    pstreams[id].reader.seek     = seek_impl;
    pstreams[id].reader.tell     = tell_impl;
    pstreams[id].reader.get_size = get_size_impl;
    pstreams[id].reader.canseek  = canseek_impl;
    pstreams[id].reader.data     = &pstreams[id].stream.file;

	mpc_streaminfo_init(&pstreams[id].info);

    if(mpc_streaminfo_read(&pstreams[id].info, &pstreams[id].reader) != ERROR_CODE_OK)
	{
		fclose(pstreams[id].stream.file);
        return 0;
    }

	mpc_decoder_setup(&pstreams[id].decoder, &pstreams[id].reader);

    if (!mpc_decoder_initialize(&pstreams[id].decoder, &pstreams[id].info))
	{
        fclose(pstreams[id].stream.file);
        return 0;
    }

	pstreams[id].sample_start  = 0;

	pstreams[id].bitspersample = 32;
	pstreams[id].channels      = pstreams[id].info.channels;
	pstreams[id].frequency     = pstreams[id].info.sample_freq;
	pstreams[id].duration      = (unsigned long)(pstreams[id].info.pcm_samples / (pstreams[id].info.sample_freq / 1000));
	return 1;
}
Exemplo n.º 5
0
static gboolean
gst_musepack_stream_init (GstMusepackDec * musepackdec)
{
    mpc_streaminfo i;
    GstTagList *tags;
    GstCaps *caps;

    /* set up reading */
    gst_musepack_init_reader (musepackdec->r, musepackdec);

#ifdef MPC_IS_OLD_API
    /* streaminfo */
    mpc_streaminfo_init (&i);
    if (mpc_streaminfo_read (&i, musepackdec->r) < 0) {
        GST_ELEMENT_ERROR (musepackdec, STREAM, WRONG_TYPE, (NULL), (NULL));
        return FALSE;
    }

    /* decoding */
    mpc_decoder_setup (musepackdec->d, musepackdec->r);
    mpc_decoder_scale_output (musepackdec->d, 1.0);
    if (!mpc_decoder_initialize (musepackdec->d, &i)) {
        GST_ELEMENT_ERROR (musepackdec, STREAM, WRONG_TYPE, (NULL), (NULL));
        return FALSE;
    }
#else
    musepackdec->d = mpc_demux_init (musepackdec->r);
    if (!musepackdec->d) {
        GST_ELEMENT_ERROR (musepackdec, STREAM, WRONG_TYPE, (NULL), (NULL));
        return FALSE;
    }

    mpc_demux_get_info (musepackdec->d, &i);
#endif

    /* capsnego */
    caps = gst_caps_from_string (BASE_CAPS);
    gst_caps_set_simple (caps,
                         "endianness", G_TYPE_INT, G_BYTE_ORDER,
                         "channels", G_TYPE_INT, i.channels,
                         "rate", G_TYPE_INT, i.sample_freq, NULL);
    gst_pad_use_fixed_caps (musepackdec->srcpad);
    if (!gst_pad_set_caps (musepackdec->srcpad, caps)) {
        GST_ELEMENT_ERROR (musepackdec, CORE, NEGOTIATION, (NULL), (NULL));
        return FALSE;
    }

    g_atomic_int_set (&musepackdec->bps, 4 * i.channels);
    g_atomic_int_set (&musepackdec->rate, i.sample_freq);

    gst_segment_set_last_stop (&musepackdec->segment, GST_FORMAT_DEFAULT, 0);
    gst_segment_set_duration (&musepackdec->segment, GST_FORMAT_DEFAULT,
                              mpc_streaminfo_get_length_samples (&i));

    /* send basic tags */
    tags = gst_tag_list_new ();
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                      GST_TAG_AUDIO_CODEC, "Musepack", NULL);

    if (i.encoder[0] != '\0' && i.encoder_version > 0) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                          GST_TAG_ENCODER, i.encoder,
                          GST_TAG_ENCODER_VERSION, i.encoder_version, NULL);
    }

    if (i.bitrate > 0) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                          GST_TAG_BITRATE, i.bitrate, NULL);
    } else if (i.average_bitrate > 0.0) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                          GST_TAG_BITRATE, (guint) i.average_bitrate, NULL);
    }

    if (i.gain_title != 0 || i.gain_album != 0) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                          GST_TAG_TRACK_GAIN, (gdouble) i.gain_title / 100.0,
                          GST_TAG_ALBUM_GAIN, (gdouble) i.gain_album / 100.0, NULL);
    }

    if (i.peak_title != 0 && i.peak_title != 32767 &&
            i.peak_album != 0 && i.peak_album != 32767) {
        gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
                          GST_TAG_TRACK_PEAK, (gdouble) i.peak_title / 32767.0,
                          GST_TAG_ALBUM_PEAK, (gdouble) i.peak_album / 32767.0, NULL);
    }

    GST_LOG_OBJECT (musepackdec, "Posting tags: %" GST_PTR_FORMAT, tags);
    gst_element_found_tags (GST_ELEMENT (musepackdec), tags);

    return TRUE;
}
Exemplo n.º 6
0
CDRFile *cdrfile_open(const char *path)
{
 CDRFile *ret = (CDRFile *)calloc(1, sizeof(CDRFile));
 struct stat stat_buf;

 if(path == NULL || stat(path, &stat_buf) || !S_ISREG(stat_buf.st_mode))
 {
  CdIo *p_cdio;
  char **devices;
  char **parseit;
  cdio_init();

  GetFileBase("cdrom");

  devices = cdio_get_devices(DRIVER_DEVICE);
  parseit = devices;
  if(parseit)
  {
   MDFN_printf(_("Connected physical devices:\n"));
   MDFN_indent(1);
   while(*parseit)
   {
    MDFN_printf("%s\n", *parseit);
    parseit++;
   }
   MDFN_indent(-1);
  }
  if(!parseit || parseit == devices)
  {
   MDFN_PrintError(_("No CDROM drives detected(or no disc present)."));
   if(devices)
    cdio_free_device_list(devices);
   free(ret);
   return(NULL);
  }

  if(devices)
   cdio_free_device_list(devices);

  p_cdio = cdio_open_cd(path); //, DRIVER_UNKNOWN); //NULL, DRIVER_UNKNOWN);

  if(!p_cdio) 
  {
   free(ret);
   return(NULL);
  }
  ret->p_cdio = p_cdio;

  ret->FirstTrack = cdio_get_first_track_num(ret->p_cdio);
  ret->NumTracks = cdio_get_num_tracks(ret->p_cdio);
  ret->total_sectors = cdio_stat_size(ret->p_cdio);

  if(ret->FirstTrack > 99)
  {
   MDFN_PrintError(_("Invalid first track: %d\n"), ret->FirstTrack);
   free(ret);
   cdio_destroy(p_cdio);
   return(NULL);
  }

  if(ret->NumTracks > 100)
  {
   MDFN_PrintError(_("Invalid track count: %d\n"), ret->NumTracks);
   free(ret);
   cdio_destroy(p_cdio);
   return(NULL);
  }

  for(track_t track = ret->FirstTrack; track < (ret->FirstTrack + ret->NumTracks); track++)
  {
   memset(&ret->Tracks[track], 0, sizeof(CDRFILE_TRACK_INFO));

   ret->Tracks[track].sectors = cdio_get_track_sec_count(ret->p_cdio, track);
   ret->Tracks[track].LSN = cdio_get_track_lsn(ret->p_cdio, track);
   ret->Tracks[track].Format = cdio_get_track_format(ret->p_cdio, track);
  }

  return(ret);
 }

  FILE *fp = fopen(path, "rb");
  bool IsTOC = FALSE;

  // Assign opposite maximum values so our tests will work!
  int FirstTrack = 99;
  int LastTrack = 0;

  if(!fp)
  {
   MDFN_PrintError(_("Error opening CUE sheet/TOC \"%s\": %m\n"), path, errno);
   free(ret);
   return(NULL);
  }
  GetFileBase(path);

  char linebuf[512];
  int32 active_track = -1;
  int32 AutoTrackInc = 1; // For TOC
  CDRFILE_TRACK_INFO TmpTrack;
  memset(&TmpTrack, 0, sizeof(TmpTrack));

  while(fgets(linebuf, 512, fp) > 0)
  {
   char cmdbuf[512], raw_args[512], args[4][512];
   int argcount = 0;

   raw_args[0] = 0;
   cmdbuf[0] = 0;

   args[0][0] = args[1][0] = args[2][0] = args[3][0] = 0;

   if(!strncasecmp(linebuf, "CD_ROM", 6) || !strncasecmp(linebuf, "CD_DA", 5) || !strncasecmp(linebuf, "CD_ROM_XA", 9))
   {
    IsTOC = TRUE;
    puts("TOC file detected.");
   }

   if(IsTOC)
   {
    char *ss_loc = strstr(linebuf, "//");
    if(ss_loc)
    {
     ss_loc[0] = '\n'; // For consistency!
     ss_loc[1] = 0;
    }
   }

   trio_sscanf(linebuf, "%s %[^\r\n]", cmdbuf, raw_args);
   
   if(!strcasecmp(cmdbuf, "CD_ROM") || !strcasecmp(cmdbuf, "CD_DA"))
    IsTOC = TRUE;

   UnQuotify(UnQuotify(UnQuotify(UnQuotify(raw_args, args[0]), args[1]), args[2]), args[3]);
   if(args[0][0])
   {
    argcount++;
    if(args[1][0])
    {
     argcount++;
     if(args[2][0])
     {
      argcount++;
      if(args[3][0])
      {
       argcount++;
      }
     }
    } 
   }

   if(IsTOC)
   {
    if(!strcasecmp(cmdbuf, "TRACK"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      memset(&TmpTrack, 0, sizeof(TmpTrack));
      active_track = -1;
     }
 
     if(AutoTrackInc > 99)
     {
      MDFN_printf(_("Invalid track number: %d\n"), AutoTrackInc);
      free(ret);
      return(NULL);
     }

     active_track = AutoTrackInc++;
     if(active_track < FirstTrack)
      FirstTrack = active_track;
     if(active_track > LastTrack)
      LastTrack = active_track;

     if(!strcasecmp(args[0], "AUDIO"))
     {
      TmpTrack.Format = TRACK_FORMAT_AUDIO;
      TmpTrack.RawAudioMSBFirst = TRUE; // Silly cdrdao...
     }
     else if(!strcasecmp(args[0], "MODE1"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 0;
     }
     else if(!strcasecmp(args[0], "MODE1_RAW"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 1;
     }
    
     if(!strcasecmp(args[1], "RW"))
     {
      TmpTrack.SubchannelMode = CDRF_SUBM_RW;
      MDFN_printf(_("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!\n"));
      free(ret);
      return(0);
     }
     else if(!strcasecmp(args[1], "RW_RAW"))
      TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW;

    } // end to TRACK
    else if(!strcasecmp(cmdbuf, "SILENCE"))
    {

    }
    else if(!strcasecmp(cmdbuf, "ZERO"))
    {

    }
    else if(!strcasecmp(cmdbuf, "FILE") || !strcasecmp(cmdbuf, "AUDIOFILE"))
    {
     const char *binoffset = NULL;
     const char *msfoffset = NULL;
     const char *length = NULL;

     if(args[1][0] == '#')
     {
      binoffset = args[1] + 1;
      msfoffset = args[2];
      length = args[3];
     }
     else
     {
      msfoffset = args[1];
      length = args[2];
     }
     //printf("%s, %s, %s, %s\n", args[0], binoffset, msfoffset, length);
     if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length))
     {
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "DATAFILE"))
    {
     const char *binoffset = NULL;
     const char *length = NULL;
  
     if(args[1][0] == '#') 
     {
      binoffset = args[1] + 1;
      length = args[2];
     }
     else
      length = args[1];

     if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length))
     {
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "INDEX"))
    {

    }
    else if(!strcasecmp(cmdbuf, "PREGAP"))
    {
     if(active_track < 0)
     {
      MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf);
      free(ret);
      return(NULL);
     }
     int m,s,f;
     trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
     TmpTrack.pregap = (m * 60 + s) * 75 + f;
    } // end to PREGAP
    else if(!strcasecmp(cmdbuf, "START"))
    {
     if(active_track < 0)
     {
      MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf);
      free(ret);
      return(NULL);
     }
     int m,s,f;
     trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
     TmpTrack.pregap = (m * 60 + s) * 75 + f;
    }
   } /*********** END TOC HANDLING ************/
   else // now for CUE sheet handling
   {
    if(!strcasecmp(cmdbuf, "FILE"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      memset(&TmpTrack, 0, sizeof(TmpTrack));
      active_track = -1;
     }
     std::string efn = MDFN_MakeFName(MDFNMKF_AUX, 0, args[0]);
     if(NULL == (TmpTrack.fp = fopen(efn.c_str(), "rb")))
     {
      MDFN_printf(_("Could not open referenced file \"%s\": %m\n"), efn.c_str(), errno);
      free(ret);
      return(0);
     }
     TmpTrack.FirstFileInstance = 1;
     if(!strcasecmp(args[1], "BINARY"))
     {
      //TmpTrack.Format = TRACK_FORMAT_DATA;
      //struct stat stat_buf;
      //fstat(fileno(TmpTrack.fp), &stat_buf);
      //TmpTrack.sectors = stat_buf.st_size; // / 2048;
     }
     else if(!strcasecmp(args[1], "OGG") || !strcasecmp(args[1], "VORBIS") || !strcasecmp(args[1], "WAVE") || !strcasecmp(args[1], "WAV") || !strcasecmp(args[1], "PCM")
	|| !strcasecmp(args[1], "MPC") || !strcasecmp(args[1], "MP+"))
     {
      TmpTrack.ovfile = (OggVorbis_File *) calloc(1, sizeof(OggVorbis_File));

      if((TmpTrack.sf = sf_open_fd(fileno(TmpTrack.fp), SFM_READ, &TmpTrack.sfinfo, 0)))
      {
       free(TmpTrack.ovfile);
       TmpTrack.ovfile = NULL;
      }
      else if(!lseek(fileno(TmpTrack.fp), 0, SEEK_SET) && !ov_open(TmpTrack.fp, TmpTrack.ovfile, NULL, 0))
      {
       //TmpTrack.Format = TRACK_FORMAT_AUDIO;
       //TmpTrack.sectors = ov_pcm_total(&TmpTrack.ovfile, -1) / 588;
      }
      else
      {      
       free(TmpTrack.ovfile);
       TmpTrack.ovfile = NULL;

       fseek(TmpTrack.fp, 0, SEEK_SET);

       TmpTrack.MPCReaderFile = (mpc_reader_file *)calloc(1, sizeof(mpc_reader_file));
       TmpTrack.MPCStreamInfo = (mpc_streaminfo *)calloc(1, sizeof(mpc_streaminfo));
       TmpTrack.MPCDecoder = (mpc_decoder *)calloc(1, sizeof(mpc_decoder));
       TmpTrack.MPCBuffer = (MPC_SAMPLE_FORMAT *)calloc(MPC_DECODER_BUFFER_LENGTH, sizeof(MPC_SAMPLE_FORMAT));

       mpc_streaminfo_init(TmpTrack.MPCStreamInfo);

       mpc_reader_setup_file_reader(TmpTrack.MPCReaderFile, TmpTrack.fp);

       if(mpc_streaminfo_read(TmpTrack.MPCStreamInfo, &TmpTrack.MPCReaderFile->reader) != ERROR_CODE_OK)
       {
        MDFN_printf(_("Unsupported audio track file format: %s\n"), args[0]);
        free(TmpTrack.MPCReaderFile);
        free(TmpTrack.MPCStreamInfo);
        free(TmpTrack.MPCDecoder);
        free(TmpTrack.MPCBuffer);
        free(ret);
        return(0);
       }

       mpc_decoder_setup(TmpTrack.MPCDecoder, &TmpTrack.MPCReaderFile->reader);
       if(!mpc_decoder_initialize(TmpTrack.MPCDecoder, TmpTrack.MPCStreamInfo))
       {
        MDFN_printf(_("Error initializing MusePack decoder: %s!\n"), args[0]);
        free(TmpTrack.MPCReaderFile);
        free(TmpTrack.MPCStreamInfo);
        free(TmpTrack.MPCDecoder);
        free(TmpTrack.MPCBuffer);
        free(ret);
        return(0);
       }
      }
     }
     else
     {
      MDFN_printf(_("Unsupported track format: %s\n"), args[1]);
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "TRACK"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      TmpTrack.FirstFileInstance = 0;
      TmpTrack.pregap = 0;
     }
     active_track = atoi(args[0]);

     if(active_track < FirstTrack)
      FirstTrack = active_track;
     if(active_track > LastTrack)
      LastTrack = active_track;

     if(!strcasecmp(args[1], "AUDIO"))
      TmpTrack.Format = TRACK_FORMAT_AUDIO;
     else if(!strcasecmp(args[1], "MODE1/2048"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 0;
     }
     else if(!strcasecmp(args[1], "MODE1/2352"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 1;
     }
     TmpTrack.sectors = GetSectorCount(&TmpTrack);
     if(active_track < 0 || active_track > 99)
     {
      MDFN_printf(_("Invalid track number: %d\n"), active_track);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "INDEX"))
    {
     if(active_track >= 0 && (!strcasecmp(args[0], "01") || !strcasecmp(args[0], "1")))
     {
      int m,s,f;
      trio_sscanf(args[1], "%d:%d:%d", &m, &s, &f);
      TmpTrack.index = (m * 60 + s) * 75 + f;
     }
    }
    else if(!strcasecmp(cmdbuf, "PREGAP"))
    {
     if(active_track >= 0)
     {
      int m,s,f;
      trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
      TmpTrack.pregap = (m * 60 + s) * 75 + f;
     }
    }
   } // end of CUE sheet handling
  } // end of fgets() loop

 if(ferror(fp))
 {
  if(IsTOC)
   MDFN_printf(_("Error reading TOC file: %m\n"), errno);
  else
   MDFN_printf(_("Error reading CUE sheet: %m\n"), errno);
  return(0);
 }

 if(active_track >= 0)
  memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
 
 if(FirstTrack > LastTrack)
 {
  MDFN_printf(_("No tracks found!\n"));
  return(0);
 }

 ret->FirstTrack = FirstTrack;
 ret->NumTracks = 1 + LastTrack - FirstTrack;

 lsn_t RunningLSN = 0;
 lsn_t LastIndex = 0;
 long FileOffset = 0;

 for(int x = ret->FirstTrack; x < (ret->FirstTrack + ret->NumTracks); x++)
 {
  if(IsTOC)
  {
   RunningLSN += ret->Tracks[x].pregap;
   ret->Tracks[x].LSN = RunningLSN;
   RunningLSN += ret->Tracks[x].sectors;
  }
  else // else handle CUE sheet...
  {
   if(ret->Tracks[x].FirstFileInstance) 
   {
    LastIndex = 0;
    FileOffset = 0;
   }
   RunningLSN += ret->Tracks[x].pregap;

   ret->Tracks[x].LSN = RunningLSN;

   // Make sure this is set before the call to GetSectorCount() for the last track sector count fix.
   ret->Tracks[x].FileOffset = FileOffset;

   if((x + 1) >= (ret->FirstTrack + ret->NumTracks))
   {
    if(!(ret->Tracks[x].FirstFileInstance))
    {
     // This will fix the last sector count for CUE+BIN
     ret->Tracks[x].sectors = GetSectorCount(&ret->Tracks[x]);
    }
   }
   else if(ret->Tracks[x+1].FirstFileInstance)
   {
    //RunningLSN += ret->Tracks[x].sectors;
   }
   else
   { 
    // Fix the sector count if we're CUE+BIN
    ret->Tracks[x].sectors = ret->Tracks[x + 1].index - ret->Tracks[x].index;
   }

   //printf("Poo: %d %d\n", x, ret->Tracks[x].sectors);
   RunningLSN += ret->Tracks[x].sectors;

   //printf("%d, %ld %d %d %d %d\n", x, FileOffset, ret->Tracks[x].index, ret->Tracks[x].pregap, ret->Tracks[x].sectors, ret->Tracks[x].LSN);

   if(ret->Tracks[x].Format == TRACK_FORMAT_AUDIO || TmpTrack.IsData2352)
    FileOffset += ret->Tracks[x].sectors * 2352;
   else
    FileOffset += ret->Tracks[x].sectors * 2048;
  } // end to cue sheet handling
 } // end to track loop

 LEC_Eval = MDFN_GetSettingB("cdrom.lec_eval");
 if(LEC_Eval)
 {
  Init_LEC_Correct();
 }
 MDFN_printf(_("Raw rip data correction using L-EC: %s\n\n"), LEC_Eval ? _("Enabled") : _("Disabled"));

 ret->total_sectors = RunningLSN; // Running LBA?  Running LSN? arghafsdf...LSNBAN!#!$ -_-
 return(ret);
}