Logo Search packages:      
Sourcecode: vcdimager version File versions

image_cdrdao.c

/*
    $Id: image_cdrdao.c,v 1.6 2004/10/25 01:44:51 rocky Exp $

    Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Public headers */
#include <cdio/iso9660.h>
#include <cdio/bytesex.h>
#include <libvcd/sector.h>
#include <libvcd/logging.h>

/* Private headers */
#include "vcd_assert.h"
#include "image_sink.h"
#include "stream_stdio.h"
#include "util.h"
#include "vcd.h"

static const char _rcsid[] = "$Id: image_cdrdao.c,v 1.6 2004/10/25 01:44:51 rocky Exp $";

/* reader */

/****************************************************************************
 * writer
 */

typedef struct {
  bool sector_2336_flag;
  char *toc_fname;
  char *img_base;

  VcdDataSink *last_bin_snk;
  int last_snk_idx;
  bool last_pause;

  CdioList *vcd_cue_list;
} _img_cdrdao_snk_t;

static void
_sink_free (void *user_data)
{
  _img_cdrdao_snk_t *_obj = user_data;

  /* fixme -- destroy cue list */

  vcd_data_sink_destroy (_obj->last_bin_snk);
  free (_obj->toc_fname);
  free (_obj->img_base);
  free (_obj);
}

static int
_set_cuesheet (void *user_data, const CdioList *vcd_cue_list)
{
  _img_cdrdao_snk_t *_obj = user_data;
  VcdDataSink *toc_snk = vcd_data_sink_new_stdio (_obj->toc_fname);

  CdioListNode *node;

  int track_no, index_no;
  const vcd_cue_t *_last_cue = 0;
  unsigned last_track_lsn = 0;

  vcd_data_sink_printf (toc_snk, 
                  "// CDRDAO TOC\n"
                  "//  generated by %s\n\n"
                  "CD_ROM_XA\n", vcd_version_string (false));

  _obj->vcd_cue_list = _cdio_list_new ();

  index_no = track_no = 0;
  _CDIO_LIST_FOREACH (node, (CdioList *) vcd_cue_list)
    {
      const vcd_cue_t *_cue = _cdio_list_node_data (node);

      /* copy cue list while traversing */
      {
      vcd_cue_t *_cue2 = _vcd_malloc (sizeof (vcd_cue_t));
      *_cue2 = *_cue;
      _cdio_list_append (_obj->vcd_cue_list, _cue2);
      }
      
      switch (_cue->type)
      {
      case VCD_CUE_TRACK_START:
        track_no++;
        index_no = 0;

        last_track_lsn = _cue->lsn;

        vcd_data_sink_printf (toc_snk, 
                        "\n// Track %d\n"
                        "TRACK %s\n COPY\n",
                        track_no,
                        (_obj->sector_2336_flag ? "MODE2_FORM_MIX" : "MODE2_RAW"));

        if (_last_cue && _last_cue->type == VCD_CUE_PREGAP_START)
          vcd_data_sink_printf (toc_snk, 
                          " DATAFILE \"%s_%.2d_pregap.img\"\n"
                          " START\n",
                          _obj->img_base, track_no);

        index_no++;

        vcd_data_sink_printf (toc_snk, 
                        " DATAFILE \"%s_%.2d.img\"\n",
                        _obj->img_base, track_no);
        break;

      case VCD_CUE_PREGAP_START:
        /* handled in next iteration */
        break;

      case VCD_CUE_SUBINDEX:
        index_no++;

        {
          msf_t _msf = { 0, 0, 0 };
          char *psz_msf;

          cdio_lba_to_msf (_cue->lsn - last_track_lsn, &_msf);
          psz_msf = cdio_msf_to_str(&_msf);

          vcd_data_sink_printf (toc_snk, " INDEX %s\n", psz_msf);
          free(psz_msf);
        }
        break;

      case VCD_CUE_LEADIN:
          break;

      case VCD_CUE_END:
        vcd_data_sink_printf (toc_snk, "\n// EOF\n");

        vcd_data_sink_close (toc_snk);
        vcd_data_sink_destroy (toc_snk);

        return 0;
        break;
      }

      _last_cue = _cue;
    }

  vcd_assert_not_reached ();

  return -1;
}
 
static int
_vcd_image_cdrdao_write (void *user_data, const void *data, lsn_t lsn)
{
  const char *buf = data;
  _img_cdrdao_snk_t *_obj = user_data;
  long offset;

  {
    CdioListNode *node;
    uint32_t _last = 0;
    uint32_t _ofs = 0;
    bool _lpregap = false;
    bool _pregap = false;

    int num = 0, in_track = 0;
    _CDIO_LIST_FOREACH (node, _obj->vcd_cue_list)
      {
      const vcd_cue_t *_cue = _cdio_list_node_data (node);
    
      switch (_cue->type) 
        {
        case VCD_CUE_PREGAP_START:
        case VCD_CUE_END:
        case VCD_CUE_TRACK_START:
          if (_cue->lsn && IN (lsn, _last, _cue->lsn - 1))
            {
            vcd_assert (in_track == 0);
            in_track = num;
            _ofs = _last;
            _pregap = _lpregap;
            }

          _last = _cue->lsn;  
          _lpregap = (_cue->type == VCD_CUE_PREGAP_START);

          if (_cue->type == VCD_CUE_TRACK_START)
            num++;
          break;

        default:
          /* noop */
          break;
        }
      }

    vcd_assert (in_track != 0);
    vcd_assert (_obj->last_snk_idx <= in_track);

    if (_obj->last_snk_idx != in_track
      || _obj->last_pause != _pregap)
      {
      char buf[4096] = { 0, };

      if (_obj->last_bin_snk)
        vcd_data_sink_destroy (_obj->last_bin_snk);

      snprintf (buf, sizeof (buf),
              "%s_%.2d%s.img",
              _obj->img_base,
              (_pregap ? in_track + 1 : in_track), 
              (_pregap ? "_pregap" : ""));
      
      _obj->last_bin_snk = vcd_data_sink_new_stdio (buf);
      _obj->last_snk_idx = in_track;
      _obj->last_pause = _pregap;
      }

    vcd_assert (lsn >= _ofs);
    offset = lsn - _ofs;
  }

  offset *= _obj->sector_2336_flag ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW;

  vcd_data_sink_seek(_obj->last_bin_snk, offset);
  
  if (_obj->sector_2336_flag)
    vcd_data_sink_write(_obj->last_bin_snk, buf + 12 + 4, M2RAW_SECTOR_SIZE, 1);
  else
    vcd_data_sink_write(_obj->last_bin_snk, buf, CDIO_CD_FRAMESIZE_RAW, 1);
  
  return 0;
}

static int
_sink_set_arg (void *user_data, const char key[], const char value[])
{
  _img_cdrdao_snk_t *_obj = user_data;

  if (!strcmp (key, "toc"))
    {
      free (_obj->toc_fname);

      if (!value)
      return -2;

      _obj->toc_fname = strdup (value);
    }
  else if (!strcmp (key, "img_base"))
    {
      free (_obj->img_base);

      if (!value)
      return -2;

      _obj->img_base = strdup (value);
    }
  else if (!strcmp (key, "sector"))
    {
      if (!strcmp (value, "2336"))
      _obj->sector_2336_flag = true;
      else if (!strcmp (value, "2352"))
      _obj->sector_2336_flag = false;
      else
      return -2;
    }
  else
    return -1;

  return 0;
}

VcdImageSink *
vcd_image_sink_new_cdrdao (void)
{
  _img_cdrdao_snk_t *_data;
  
  vcd_image_sink_funcs _funcs = {
    .set_cuesheet = _set_cuesheet,
    .write        = _vcd_image_cdrdao_write,
    .free         = _sink_free,
    .set_arg      = _sink_set_arg
  };

  _data = _vcd_malloc (sizeof (_img_cdrdao_snk_t));

  _data->toc_fname = strdup ("videocd.toc");
  _data->img_base = strdup ("videocd");

  return vcd_image_sink_new (_data, &_funcs);
}


Generated by  Doxygen 1.6.0   Back to index