Blame lib/driver/image_common.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2004-2005, 2008, 2010-2011, 2013, 2017
Packit dd8086
   Rocky Bernstein <rocky@gnu.org>
Packit dd8086
Packit dd8086
  This program is free software: you can redistribute it and/or modify
Packit dd8086
  it under the terms of the GNU General Public License as published by
Packit dd8086
  the Free Software Foundation, either version 3 of the License, or
Packit dd8086
  (at your option) any later version.
Packit dd8086
Packit dd8086
  This program is distributed in the hope that it will be useful,
Packit dd8086
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit dd8086
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit dd8086
  GNU General Public License for more details.
Packit dd8086
Packit dd8086
  You should have received a copy of the GNU General Public License
Packit dd8086
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit dd8086
*/
Packit dd8086
Packit dd8086
/*! Common image routines.
Packit dd8086
Packit dd8086
  Because _img_private_t may vary over image formats, the routines are
Packit dd8086
  included into the image drivers after _img_private_t is defined.  In
Packit dd8086
  order for the below routines to work, there is a large part of
Packit dd8086
  _img_private_t that is common among image drivers. For example, see
Packit dd8086
  image.h
Packit dd8086
*/
Packit dd8086
Packit dd8086
#include "image.h"
Packit dd8086
#include "image_common.h"
Packit dd8086
#include <cdio/util.h>
Packit dd8086
#include "_cdio_stdio.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_STDLIB_H
Packit dd8086
#include <stdlib.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_STRING_H
Packit dd8086
#include <string.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Eject media -- there's nothing to do here except free resources.
Packit dd8086
  We always return DRIVER_OP_UNSUPPORTED.
Packit dd8086
 */
Packit dd8086
driver_return_code_t
Packit dd8086
_eject_media_image(void *p_user_data)
Packit dd8086
{
Packit dd8086
  _free_image (p_user_data);
Packit dd8086
  return DRIVER_OP_UNSUPPORTED;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  We don't need the image any more. Free all memory associated with
Packit dd8086
  it.
Packit dd8086
 */
Packit dd8086
void
Packit dd8086
_free_image (void *p_user_data)
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = p_user_data;
Packit dd8086
  track_t i_track;
Packit dd8086
Packit dd8086
  if (NULL == p_env) return;
Packit dd8086
Packit dd8086
  for (i_track=0; i_track < p_env->gen.i_tracks; i_track++) {
Packit dd8086
    track_info_t *p_tocent = &(p_env->tocent[i_track]);
Packit dd8086
    CDIO_FREE_IF_NOT_NULL(p_tocent->filename);
Packit dd8086
    CDIO_FREE_IF_NOT_NULL(p_tocent->isrc);
Packit dd8086
    if (p_tocent->data_source) cdio_stdio_destroy(p_tocent->data_source);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  CDIO_FREE_IF_NOT_NULL(p_env->psz_mcn);
Packit dd8086
  CDIO_FREE_IF_NOT_NULL(p_env->psz_cue_name);
Packit dd8086
  CDIO_FREE_IF_NOT_NULL(p_env->psz_access_mode);
Packit dd8086
  cdtext_destroy(p_env->gen.cdtext);
Packit dd8086
  cdio_generic_stdio_free(p_env);
Packit dd8086
  free(p_env);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the value associated with the key "arg".
Packit dd8086
*/
Packit dd8086
const char *
Packit dd8086
_get_arg_image (void *user_data, const char key[])
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = user_data;
Packit dd8086
Packit dd8086
  if (!strcmp (key, "source")) {
Packit dd8086
    return p_env->gen.source_name;
Packit dd8086
  } else if (!strcmp (key, "cue")) {
Packit dd8086
    return p_env->psz_cue_name;
Packit dd8086
  } else if (!strcmp(key, "access-mode")) {
Packit dd8086
    return "image";
Packit dd8086
  } else if (!strcmp (key, "mmc-supported?")) {
Packit dd8086
    return "false";
Packit dd8086
  }
Packit dd8086
  return NULL;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return CD-Text object
Packit dd8086
 */
Packit dd8086
cdtext_t *
Packit dd8086
_get_cdtext_image (void *user_data)
Packit dd8086
{
Packit dd8086
  generic_img_private_t *p_env = user_data;
Packit dd8086
Packit dd8086
  if(!p_env)
Packit dd8086
    return NULL;
Packit dd8086
Packit dd8086
  return p_env->cdtext;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Get disc type associated with cd_obj.
Packit dd8086
*/
Packit dd8086
discmode_t
Packit dd8086
_get_discmode_image (void *p_user_data)
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = p_user_data;
Packit dd8086
  return p_env->disc_mode;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the the kind of drive capabilities of device.
Packit dd8086
Packit dd8086
 */
Packit dd8086
void
Packit dd8086
_get_drive_cap_image (const void *user_data,
Packit dd8086
		      cdio_drive_read_cap_t  *p_read_cap,
Packit dd8086
		      cdio_drive_write_cap_t *p_write_cap,
Packit dd8086
		      cdio_drive_misc_cap_t  *p_misc_cap)
Packit dd8086
{
Packit dd8086
Packit dd8086
  *p_read_cap  = CDIO_DRIVE_CAP_READ_CD_DA
Packit dd8086
    | CDIO_DRIVE_CAP_READ_CD_G
Packit dd8086
    | CDIO_DRIVE_CAP_READ_CD_R
Packit dd8086
    | CDIO_DRIVE_CAP_READ_CD_RW
Packit dd8086
    | CDIO_DRIVE_CAP_READ_MODE2_FORM1
Packit dd8086
    | CDIO_DRIVE_CAP_READ_MODE2_FORM2
Packit dd8086
    | CDIO_DRIVE_CAP_READ_MCN
Packit dd8086
    ;
Packit dd8086
Packit dd8086
  *p_write_cap = 0;
Packit dd8086
Packit dd8086
  /* In the future we may want to simulate
Packit dd8086
     LOCK, OPEN_TRAY, CLOSE_TRAY, SELECT_SPEED, etc.
Packit dd8086
  */
Packit dd8086
  *p_misc_cap  = CDIO_DRIVE_CAP_MISC_FILE;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the number of of the first track.
Packit dd8086
  CDIO_INVALID_TRACK is returned on error.
Packit dd8086
*/
Packit dd8086
track_t
Packit dd8086
_get_first_track_num_image(void *p_user_data)
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  if (!p_env->gen.toc_init)
Packit dd8086
    p_env->gen.cdio->op.read_toc (p_user_data);
Packit dd8086
Packit dd8086
  return p_env->gen.toc_init ? p_env->gen.i_first_track : CDIO_INVALID_TRACK;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Find out if media has changed since the last call.
Packit dd8086
  @param p_user_data the CD object to be acted upon.
Packit dd8086
  @return 1 if media has changed since last call, 0 if not. Error
Packit dd8086
  return codes are the same as driver_return_code_t
Packit dd8086
  There is no such thing as changing a media image so we will
Packit dd8086
  always return 0 - no change.
Packit dd8086
 */
Packit dd8086
int
Packit dd8086
get_media_changed_image(const void *p_user_data)
Packit dd8086
{
Packit dd8086
  return 0;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the media catalog number (MCN) from the CD or NULL if there
Packit dd8086
  is none or we don't have the ability to get it.
Packit dd8086
Packit dd8086
  Note: string is malloc'd so caller has to free() the returned
Packit dd8086
  string when done with it.
Packit dd8086
  */
Packit dd8086
char *
Packit dd8086
_get_mcn_image(const void *p_user_data)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  if (!p_env || !p_env->psz_mcn) return NULL;
Packit dd8086
  return strdup(p_env->psz_mcn);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the number of tracks.
Packit dd8086
*/
Packit dd8086
track_t
Packit dd8086
_get_num_tracks_image(void *p_user_data)
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  return p_env->gen.i_tracks;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the starting MSF (minutes/secs/frames) for the track number
Packit dd8086
  track_num in obj.  Tracks numbers start at 1.
Packit dd8086
  The "leadout" track is specified either by
Packit dd8086
  using track_num LEADOUT_TRACK or the total tracks+1.
Packit dd8086
Packit dd8086
*/
Packit dd8086
bool
Packit dd8086
_get_track_msf_image(void *p_user_data, track_t i_track, msf_t *msf)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  if (NULL == msf) return false;
Packit dd8086
Packit dd8086
  if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1;
Packit dd8086
Packit dd8086
  if (i_track <= p_env->gen.i_tracks+1 && i_track != 0) {
Packit dd8086
    *msf = p_env->tocent[i_track-p_env->gen.i_first_track].start_msf;
Packit dd8086
    return true;
Packit dd8086
  } else
Packit dd8086
    return false;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*! Return number of channels in track: 2 or 4; -2 if not
Packit dd8086
  implemented or -1 for error.
Packit dd8086
  Not meaningful if track is not an audio track.
Packit dd8086
*/
Packit dd8086
int
Packit dd8086
get_track_channels_image(const void *p_user_data, track_t i_track)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
  return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
Packit dd8086
	  & FOUR_CHANNEL_AUDIO ) ? 4 : 2;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*! Return 1 if copy is permitted on the track, 0 if not, or -1 for error.
Packit dd8086
  Is this meaningful if not an audio track?
Packit dd8086
*/
Packit dd8086
track_flag_t
Packit dd8086
get_track_copy_permit_image(void *p_user_data, track_t i_track)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
  return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
Packit dd8086
	   & COPY_PERMITTED ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*! Return 1 if track has pre-emphasis, 0 if not, or -1 for error.
Packit dd8086
  Is this meaningful if not an audio track?
Packit dd8086
Packit dd8086
  pre-emphasis is a non linear frequency response.
Packit dd8086
*/
Packit dd8086
track_flag_t
Packit dd8086
get_track_preemphasis_image(const void *p_user_data, track_t i_track)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
  return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
Packit dd8086
	   & PRE_EMPHASIS ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*! Return the starting LBA for the pregap for track number i_track.
Packit dd8086
  Track numbers start at 1.
Packit dd8086
  CDIO_INVALID_LBA is returned on error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
get_track_pregap_lba_image(const void *p_user_data, track_t i_track)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
  lba_t pregap, start_lba;
Packit dd8086
Packit dd8086
  pregap    = p_env->tocent[i_track-p_env->gen.i_first_track].pregap;
Packit dd8086
  start_lba = p_env->tocent[i_track-p_env->gen.i_first_track].start_lba;
Packit dd8086
Packit dd8086
  /* avoid initializing pregap to CDIO_INVALID_LBA by letting calloc
Packit dd8086
     do the work.  also, nero files have the pregap set equal
Packit dd8086
     to the start of the track when there is no pregap
Packit dd8086
  */
Packit dd8086
  if (!pregap || pregap == start_lba) {
Packit dd8086
    pregap = CDIO_INVALID_LBA;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  return pregap;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Return the International Standard Recording Code (ISRC) for track number
Packit dd8086
  i_track in p_cdio.  Track numbers start at 1.
Packit dd8086
Packit dd8086
  Note: string is malloc'd so caller has to free() the returned
Packit dd8086
  string when done with it.
Packit dd8086
*/
Packit dd8086
char *
Packit dd8086
get_track_isrc_image(const void *p_user_data, track_t i_track)
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
  char *isrc = p_env->tocent[i_track-p_env->gen.i_first_track].isrc;
Packit dd8086
Packit dd8086
  if (isrc && isrc[0]) {
Packit dd8086
    return strdup(isrc);
Packit dd8086
  } else {
Packit dd8086
    return NULL;
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Read a data sector
Packit dd8086
Packit dd8086
  @param p_cdio object to read from
Packit dd8086
Packit dd8086
  @param p_buf place to read data into.  The caller should make sure
Packit dd8086
  this location can store at least ISO_BLOCKSIZE, M2RAW_SECTOR_SIZE,
Packit dd8086
  or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If
Packit dd8086
  you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless
Packit dd8086
  sector best to reserve space for the maximum, M2RAW_SECTOR_SIZE.
Packit dd8086
Packit dd8086
  @param i_lsn sector to read
Packit dd8086
Packit dd8086
  @param i_blocksize size of block. Should be either ISO_BLOCKSIZE
Packit dd8086
  M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under
Packit dd8086
  p_buf.
Packit dd8086
  */
Packit dd8086
driver_return_code_t
Packit dd8086
read_data_sectors_image ( void *p_user_data, void *p_buf,
Packit dd8086
			  lsn_t i_lsn,  uint16_t i_blocksize,
Packit dd8086
			  uint32_t i_blocks )
Packit dd8086
{
Packit dd8086
  const _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  if (!p_env || !p_env->gen.cdio) return DRIVER_OP_UNINIT;
Packit dd8086
Packit dd8086
  {
Packit dd8086
    CdIo_t *p_cdio                = p_env->gen.cdio;
Packit dd8086
    track_t i_track               = cdio_get_track(p_cdio, i_lsn);
Packit dd8086
    track_format_t e_track_format = cdio_get_track_format(p_cdio, i_track);
Packit dd8086
Packit dd8086
    switch(e_track_format) {
Packit dd8086
    case TRACK_FORMAT_PSX:
Packit dd8086
    case TRACK_FORMAT_AUDIO:
Packit dd8086
    case TRACK_FORMAT_ERROR:
Packit dd8086
      return DRIVER_OP_ERROR;
Packit dd8086
    case TRACK_FORMAT_DATA:
Packit dd8086
      return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
Packit dd8086
    case TRACK_FORMAT_CDI:
Packit dd8086
    case TRACK_FORMAT_XA:
Packit dd8086
      return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
  return DRIVER_OP_ERROR;
Packit dd8086
}
Packit dd8086
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Set the arg "key" with "value" in the source device.
Packit dd8086
  Currently "source" to set the source device in I/O operations
Packit dd8086
  is the only valid key.
Packit dd8086
Packit dd8086
*/
Packit dd8086
driver_return_code_t
Packit dd8086
_set_arg_image (void *p_user_data, const char key[], const char value[])
Packit dd8086
{
Packit dd8086
  _img_private_t *p_env = p_user_data;
Packit dd8086
Packit dd8086
  if (!strcmp (key, "source"))
Packit dd8086
    {
Packit dd8086
      CDIO_FREE_IF_NOT_NULL(p_env->gen.source_name);
Packit dd8086
      if (!value) return DRIVER_OP_ERROR;
Packit dd8086
      p_env->gen.source_name = strdup (value);
Packit dd8086
    }
Packit dd8086
  else if (!strcmp (key, "cue"))
Packit dd8086
    {
Packit dd8086
      CDIO_FREE_IF_NOT_NULL(p_env->psz_cue_name);
Packit dd8086
      if (!value) return DRIVER_OP_ERROR;
Packit dd8086
      p_env->psz_cue_name = strdup (value);
Packit dd8086
    }
Packit dd8086
  else if (!strcmp (key, "access-mode"))
Packit dd8086
    {
Packit dd8086
      CDIO_FREE_IF_NOT_NULL(p_env->psz_access_mode);
Packit dd8086
      if (!value) return DRIVER_OP_ERROR;
Packit dd8086
      p_env->psz_access_mode = strdup (value);
Packit dd8086
    }
Packit dd8086
  else
Packit dd8086
    return DRIVER_OP_ERROR;
Packit dd8086
Packit dd8086
  return DRIVER_OP_SUCCESS;
Packit dd8086
}