paranoia code removed. Is now in separate tree under GPL v2+.

realpath.c: patch from Debian and N. Boullis
This commit is contained in:
rocky
2012-02-19 22:11:14 -05:00
parent c742eed87d
commit f9bd26cbc2
46 changed files with 60 additions and 10129 deletions

View File

@@ -38,10 +38,6 @@ EXTRA_DIST = \
SUBDIRS = doc include lib src test example
if BUILD_CD_PARANOIA
paranoiapcs = libcdio_paranoia.pc libcdio_cdda.pc
endif
# pkg-config(1) related rules
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcdio.pc \

View File

@@ -51,20 +51,10 @@ AC_ARG_WITH(cd-info,
AC_HELP_STRING([--without-cd-info], [don't build program cd-info (default with)]),
enable_cd_info="${withval}", enable_cd_info=yes)
AC_ARG_WITH(cd-paranoia,
AC_HELP_STRING([--without-cd-paranoia], [don't build program cd-paranoia and paranoia libraries (default with)]),
enable_cd_paranoia="${withval}", enable_cd_paranoia=yes)
AC_ARG_WITH(cdda-player,
AC_HELP_STRING([--without-cdda-player], [don't build program cdda-player (default with)]),
enable_cdda_player="${withval}", enable_cdda_player=yes)
AC_ARG_WITH(cd-paranoia-name,
AC_HELP_STRING([--with-cd-paranoia-name], [name to use as the cd-paranoia program name (default cd-paranoia)]),
cd_paranoia_name="${withval}", cd_paranoia_name="cd-paranoia")
CDPARANOIA_NAME="$cd_paranoia_name"
AC_SUBST(CDPARANOIA_NAME)
AC_ARG_WITH(cd-read,
AC_HELP_STRING([--without-cd-read], [don't build program cd-read (default with)]),
enable_cd_read="${withval}", enable_cd_read=yes)
@@ -175,13 +165,6 @@ if test "x$ac_cv_sys_largefiles" = "xyes"; then
CPPFLAGS="$CPPFLAGS $LIBCDIO_LARGEFILE_FLAGS"
fi
# We use cmp and cdparanoia in cd-paranoia regression testing
AC_PATH_PROG(CMP, cmp, no)
AC_SUBST(CMP)
AC_PATH_PROG(OLD_CDPARANOIA, cdparanoia, no)
AC_SUBST(OLD_CDPARANOIA)
AC_DEFINE(LIBCDIO_CONFIG_H, 1,
[Is set when libcdio's config.h has been included. Applications wishing to sue their own config.h values (such as set by the application's configure script can define this before including any of libcdio's headers.])
@@ -322,7 +305,6 @@ AM_CONDITIONAL(CYGWIN, test "x$CYGWIN" = "xyes")
AM_CONDITIONAL(BUILD_CD_DRIVE, test "x$enable_cd_drive" = "xyes")
AM_CONDITIONAL(BUILD_CDINFO, test "x$enable_cd_info" = "xyes")
AM_CONDITIONAL(BUILD_CD_READ, test "x$enable_cd_read" = "xyes")
AM_CONDITIONAL(BUILD_CD_PARANOIA, test "x$enable_cd_paranoia" = "xyes")
AM_CONDITIONAL(BUILD_ISO_INFO, test "x$enable_iso_info" = "xyes")
AM_CONDITIONAL(BUILD_ISO_READ, test "x$enable_iso_read" = "xyes")
AM_CONDITIONAL(BUILD_CDINFO_LINUX, test "x$enable_cd_info_linux" = "xyes")
@@ -338,7 +320,6 @@ LIBCDIO_LIBS='$(top_builddir)/lib/driver/libcdio.la'
LIBCDIO_DEPS="$LIBCDIO_LIBS"
LIBCDIOPP_LIBS='$(top_builddir)/lib/cdio++/libcdio++.la'
LIBISO9660PP_LIBS='$(top_builddir)/lib/cdio++/libiso9660++.la'
LIBCDIO_PARANOIA_LIBS='$(top_builddir)/lib/paranoia/libcdio_paranoia.la'
LIBISO9660_CFLAGS='-I$(top_srcdir)/lib/iso9660/'
LIBISO9660_LIBS='$(top_builddir)/lib/iso9660/libiso9660.la'
LIBUDF_CFLAGS='-I$(top_srcdir)/lib/udf/'
@@ -350,7 +331,6 @@ AC_SUBST(LIBISO9660PP_LIBS)
AC_SUBST(LIBCDIO_LIBS)
AC_SUBST(LIBCDIOPP_LIBS)
AC_SUBST(LIBCDIO_DEPS)
AC_SUBST(LIBCDIO_PARANOIA_LIBS)
AC_SUBST(LIBISO9660_LIBS)
AC_SUBST(LIBUDF_LIBS)
@@ -652,27 +632,17 @@ AC_CONFIG_FILES([
doc/doxygen/Doxyfile \
doc/Makefile \
lib/Makefile \
lib/cdda_interface/Makefile \
lib/cdio++/Makefile \
lib/driver/Makefile \
lib/iso9660/Makefile \
lib/paranoia/Makefile \
lib/udf/Makefile \
libcdio.pc \
libcdio++.pc \
libcdio_cdda.pc \
libcdio_paranoia.pc \
libiso9660.pc \
libiso9660++.pc \
libudf.pc \
package/libcdio.spec \
src/cd-paranoia/Makefile \
src/cd-paranoia/usage.txt \
src/cd-paranoia/doc/Makefile \
src/cd-paranoia/doc/en/cd-paranoia.1 \
src/cd-paranoia/doc/en/Makefile \
src/cd-paranoia/doc/ja/cd-paranoia.1 \
src/cd-paranoia/doc/ja/Makefile \
src/Makefile \
test/check_common_fn \
test/data/Makefile \
@@ -690,12 +660,10 @@ AC_CONFIG_FILES([
AC_CONFIG_FILES([test/check_cue.sh], [chmod +x test/check_cue.sh])
AC_CONFIG_FILES([test/check_iso.sh], [chmod +x test/check_iso.sh])
AC_CONFIG_FILES([test/check_nrg.sh], [chmod +x test/check_nrg.sh])
AC_CONFIG_FILES([test/check_paranoia.sh], [chmod +x test/check_paranoia.sh])
AC_OUTPUT
AC_MSG_NOTICE([
Using CD-ROM drivers : $cd_drivers
Building cd-paranoia : $(test "x$enable_cd_paranoia" = "xyes" && echo yes || echo no)
Building cd-info : $(test "x$enable_cd_info" = "xyes" && echo yes || echo no)
Building cd-read : $(test "x$enable_cd_read" = "xyes" && echo yes || echo no)
Building cdda-player : $(test "x$enable_cdda_player" = "xyes" && echo yes || echo no)

View File

@@ -1,8 +1,10 @@
/*.o
/*~
/.deps
/.libs
/Makefile
/Makefile.in
/copying
/device
/eject
/isofile

View File

@@ -19,12 +19,9 @@
#
SUBDIRS = OO
if BUILD_CD_PARANOIA
paranoia_progs = paranoia paranoia2
endif
if BUILD_EXAMPLES
noinst_PROGRAMS = device eject isofile isofile2 isolist \
mmc1 mmc2 $(paranoia_progs)
mmc1 mmc2
endif
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
@@ -37,15 +34,6 @@ eject_DEPENDENCIES = $(LIBCDIO_DEPS)
eject_SOURCES = eject.cpp
eject_LDADD = $(LIBCDIO_LIBS)
if BUILD_CD_PARANOIA
paranoia_SOURCES = paranoia.cpp
paranoia_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) \
$(LIBCDIO_LIBS)
paranoia2_SOURCES = paranoia.cpp
paranoia2_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) \
$(LIBCDIO_LIBS)
endif
isofile_SOURCES = isofile.cpp
isofile_LDADD = $(LIBISO9660_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
isofile2_SOURCES = isofile2.cpp

View File

@@ -1,8 +1,10 @@
/*.o
/.deps
/.libs
/Makefile
/Makefile.in
/cdtext
/copying
/device
/drives
/eject

View File

@@ -21,13 +21,10 @@
if ENABLE_CPP
SUBDIRS = C++
endif
if BUILD_CD_PARANOIA
paranoia_progs = paranoia paranoia2
endif
if BUILD_EXAMPLES
noinst_PROGRAMS = audio cdchange cdtext device discid drives eject \
isofile isofile2 isofuzzy isolist isolsn \
mmc1 mmc2 mmc2a mmc3 $(paranoia_progs) tracks \
mmc1 mmc2 mmc2a mmc3 tracks \
sample3 sample4 udf1 udffile cdio-eject
endif
@@ -57,11 +54,6 @@ eject_LDADD = $(LIBCDIO_LIBS) $(LTLIBICONV)
cdio_eject_DEPENDENCIES = $(LIBCDIO_DEPS)
cdio_eject_LDADD = $(LIBCDIO_LIBS) $(LTLIBICONV)
if BUILD_CD_PARANOIA
paranoia_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
paranoia2_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
endif
isofile_LDADD = $(LIBISO9660_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
isofile2_LDADD = $(LIBISO9660_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
isofuzzy_LDADD = $(LIBISO9660_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)

View File

@@ -1,180 +0,0 @@
/*
Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011
Rocky Bernstein <rocky@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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* Simple program to show using libcdio's version of the CD-DA paranoia.
library. */
/* config.h has to come first else _FILE_OFFSET_BITS are redefined in
say opensolaris. */
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include <cdio/paranoia.h>
#include <cdio/cd_types.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <fcntl.h>
static void
put_num(long int num, int f, int bytes)
{
unsigned int i;
unsigned char c;
for (i=0; bytes--; i++) {
c = (num >> (i<<3)) & 0xff;
if (write(f, &c, 1)==-1) {
perror("Could not write to output.");
exit(1);
}
}
}
#define writestr(fd, s) \
write(fd, s, sizeof(s)-1) /* Subtract 1 for trailing '\0'. */
/* Write a the header for a WAV file. */
static void
write_WAV_header(int fd, int32_t i_bytecount){
ssize_t bytes_ret;
/* quick and dirty */
bytes_ret = writestr(fd, "RIFF"); /* 0-3 */
put_num(i_bytecount+44-8, fd, 4); /* 4-7 */
bytes_ret = writestr(fd, "WAVEfmt "); /* 8-15 */
put_num(16, fd, 4); /* 16-19 */
put_num(1, fd, 2); /* 20-21 */
put_num(2, fd, 2); /* 22-23 */
put_num(44100, fd, 4); /* 24-27 */
put_num(44100*2*2, fd, 4); /* 28-31 */
put_num(4, fd, 2); /* 32-33 */
put_num(16, fd, 2); /* 34-35 */
bytes_ret = writestr(fd, "data"); /* 36-39 */
put_num(i_bytecount, fd, 4); /* 40-43 */
}
int
main(int argc, const char *argv[])
{
cdrom_drive_t *d = NULL; /* Place to store handle given by cd-paranoia. */
char **ppsz_cd_drives; /* List of all drives with a loaded CDDA in it. */
/* See if we can find a device with a loaded CD-DA in it. */
ppsz_cd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
if (ppsz_cd_drives) {
/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in
the list. */
d=cdda_identify(*ppsz_cd_drives, 1, NULL);
} else {
printf("Unable find or access a CD-ROM drive with an audio CD in it.\n");
exit(77);
}
/* Don't need a list of CD's with CD-DA's any more. */
cdio_free_device_list(ppsz_cd_drives);
if ( !d ) {
printf("Unable to identify audio CD disc.\n");
exit(77);
}
/* We'll set for verbose paranoia messages. */
cdda_verbose_set(d, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);
if ( 0 != cdda_open(d) ) {
printf("Unable to open disc.\n");
exit(77);
}
/* Okay now set up to read up to the first 300 frames of the first
audio track of the Audio CD. */
{
cdrom_paranoia_t *p = paranoia_init(d);
lsn_t i_first_lsn = cdda_disc_firstsector(d);
if ( -1 == i_first_lsn ) {
printf("Trouble getting starting LSN\n");
} else {
lsn_t i_cursor;
ssize_t bytes_ret;
track_t i_track = cdda_sector_gettrack(d, i_first_lsn);
lsn_t i_last_lsn = cdda_track_lastsector(d, i_track);
int fd = creat("track1s.wav", 0644);
if (-1 == fd) {
printf("Unable to create track1s.wav\n");
exit(1);
}
/* For demo purposes we'll read only 300 frames (about 4
seconds). We don't want this to take too long. On the other
hand, I suppose it should be something close to a real test.
*/
if ( i_last_lsn - i_first_lsn > 300) i_last_lsn = i_first_lsn + 299;
printf("Reading track %d from LSN %ld to LSN %ld\n", i_track,
(long int) i_first_lsn, (long int) i_last_lsn);
/* Set reading mode for full paranoia, but allow skipping sectors. */
paranoia_modeset(p, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);
paranoia_seek(p, i_first_lsn, SEEK_SET);
write_WAV_header(fd, (i_last_lsn-i_first_lsn+1) * CDIO_CD_FRAMESIZE_RAW);
for ( i_cursor = i_first_lsn; i_cursor <= i_last_lsn; i_cursor ++) {
/* read a sector */
int16_t *p_readbuf=paranoia_read(p, NULL);
char *psz_err=cdda_errors(d);
char *psz_mes=cdda_messages(d);
if (psz_mes || psz_err)
printf("%s%s\n", psz_mes ? psz_mes: "", psz_err ? psz_err: "");
free(psz_err);
free(psz_mes);
if( !p_readbuf ) {
printf("paranoia read error. Stopping.\n");
break;
}
bytes_ret = write(fd, p_readbuf, CDIO_CD_FRAMESIZE_RAW);
}
close(fd);
}
paranoia_free(p);
}
cdda_close(d);
exit(0);
}

View File

@@ -1,96 +0,0 @@
/*
Copyright (C) 2005, 2006, 2008, 2009 Rocky Bernstein <rocky@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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* Simple program to show using libcdio's version of the CD-DA
paranoia library. But in this version, we'll open a cdio object before
calling paranoia's open. I imagine in many cases such as media
players this may be what will be done since, one may want to get
CDDB/CD-Text info beforehand.
*/
#include <cdio/cdda.h>
#include <cdio/cd_types.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
int
main(int argc, const char *argv[])
{
cdrom_drive_t *d = NULL; /* Place to store handle given by cd-paranoia. */
char **ppsz_cd_drives; /* List of all drives with a loaded CDDA in it. */
CdIo_t *p_cdio = NULL;
/* See if we can find a device with a loaded CD-DA in it. */
ppsz_cd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
if (ppsz_cd_drives) {
/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in
the list. */
p_cdio = cdio_open(*ppsz_cd_drives, DRIVER_UNKNOWN);
d=cdio_cddap_identify_cdio(p_cdio, 1, NULL);
} else {
printf("Unable find or access a CD-ROM drive with an audio CD in it.\n");
exit(77);
}
/* Don't need a list of CD's with CD-DA's any more. */
cdio_free_device_list(ppsz_cd_drives);
if ( !d ) {
printf("Unable to identify audio CD disc.\n");
exit(77);
}
/* We'll set for verbose paranoia messages. */
cdio_cddap_verbose_set(d, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);
if ( 0 != cdio_cddap_open(d) ) {
printf("Unable to open disc.\n");
exit(77);
}
/* In the paranoia example was a reading. Here we are going to do
something trivial (but I think neat any way - get the Endian-ness
of the drive. */
{
const int i_endian = data_bigendianp(d);
switch (i_endian) {
case 0:
printf("Drive returns audio data Little Endian."
" Your drive is like most.\n");
break;
case 1:
printf("Drive returns audio data Big Endian.\n");
break;
case -1:
printf("Don't know whether drive is Big or Little Endian.\n");
break;
default:
printf("Whoah - got a return result I'm not expecting %d.\n",
i_endian);
break;
}
}
cdio_cddap_close_no_free_cdio(d);
cdio_destroy( p_cdio );
exit(0);
}

View File

@@ -18,10 +18,6 @@
########################################################
#
if BUILD_CD_PARANOIA
paranoiaheaders = cdda.h cdtext.h
endif
cdio_config.h: $(top_builddir)/config.h
echo '#ifndef __CDIO_CONFIG_H__' > cdio_config.h
echo '#define __CDIO_CONFIG_H__' >> cdio_config.h

View File

@@ -1,6 +1,4 @@
# $Id: Makefile.am,v 1.70 2008/03/20 19:02:38 karl Exp $
#
# Copyright (C) 2003, 2004, 2006, 2008 Rocky Bernstein <rocky@gnu.org>
# Copyright (C) 2003, 2004, 2006, 2008, 2012 Rocky Bernstein <rocky@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
@@ -19,12 +17,8 @@
# make all libraries
########################################################
if BUILD_CD_PARANOIA
paranoiadirs = cdda_interface paranoia
endif
if ENABLE_CXX_BINDINGS
cxxdirs = cdio++
endif
SUBDIRS = driver iso9660 udf $(paranoiadirs) $(cxxdirs)
SUBDIRS = driver iso9660 udf $(cxxdirs)

View File

@@ -1,8 +0,0 @@
.deps
.libs
Makefile
Makefile.in
*.o
*.lo
*.la
*.la.ver

View File

@@ -1,8 +0,0 @@
/*.lo
/*.o
/.deps
/.libs
/Makefile
/Makefile.in
/libcdio_cdda.la
/libcdio_cdda.la.ver

View File

@@ -1,151 +0,0 @@
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011
# Rocky Bernstein <rocky@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 3 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, see <http://www.gnu.org/licenses/>.
########################################################
# Things to make the cdda_interface library
########################################################
#
# From libtool documentation amended with guidance from N. Boullis:
#
# 1. Start with version information of `0:0:0' for each libtool library.
#
# 2. It is probably not a good idea to update the version information
# several times between public releases, but rather once per public
# release. (This seems to be more an aesthetic consideration than
# a hard technical one.)
#
# 3. If the library source code has changed at all since the last
# update, then increment REVISION (`C:R:A' becomes `C:R+1:A').
#
# 4. If any interfaces have been added, removed, or changed since the
# last update, increment CURRENT, and set REVISION to 0.
#
# 5. If any interfaces have been added since the last public release,
# then increment AGE.
#
# 6. If any interfaces have been removed or changed since the last
# public release, then set AGE to 0. A changed interface means an
# incompatibility with previous versions.
EXTRA_DIST = libcdio_cdda.sym
libcdio_cdda_la_CURRENT = 1
libcdio_cdda_la_REVISION = 0
libcdio_cdda_la_AGE = 0
noinst_HEADERS = common_interface.h drive_exceptions.h low_interface.h \
smallft.h utils.h
libcdio_cdda_sources = common_interface.c cddap_interface.c interface.c \
scan_devices.c smallft.c toc.c utils.c drive_exceptions.c
lib_LTLIBRARIES = libcdio_cdda.la
libcdio_cdda_la_SOURCES = $(libcdio_cdda_sources)
libcdio_cdda_la_ldflags = -version-info $(libcdio_cdda_la_CURRENT):$(libcdio_cdda_la_REVISION):$(libcdio_cdda_la_AGE) @LT_NO_UNDEFINED@
INCLUDES = $(LIBCDIO_CFLAGS)
FLAGS=@LIBCDIO_CFLAGS@ @UCDROM_H@ @TYPESIZES@ @CFLAGS@
OPT=$(FLAGS)
DEBUG=$(FLAGS) -DCDDA_TEST
## test:
## $(MAKE) libcdio_cdda.a CFLAGS="$(DEBUG)"
## $(CC) $(DEBUG) -c test_interface.c
## $(LD) $(DEBUG) test_interface.o $(LDFLAGS) -o cdda_test $(LIBS) libcdio_cdda.a
LIBS = $(LIBCDIO_LIBS) @COS_LIB@
########################################################
# Things to version the symbols in the libraries
########################################################
# An explanation of the versioning problem from Nicolas Boullis and
# the versioned symbol solution he uses below...
#
# Currently, libvcdinfo uses the cdio_open function from libcdio.
# Let's imagine a program foobar that uses both the vcdinfo_open
# function from libvcdinfo and the cdio_open function from libcdio.
# Currently, libcdio has SONAME libcdio.so.0, libvcdinfo has SONAME
# libvcdinfo.so.0 and requires libcdio.so.0, and foobar requires both
# libvcdinfo.so.0 and libcdio.so.0. Everything looks fine.
#
# Now, for some reason, you decide to change the cdio_open function.
# That's your right, but you have to bump the CURRENT version and (if I
# understand it correctly, athough this is not that clear in libtool's
# documentation) set the AGE to 0. Anyway, this bumps the SONAME, which is
# sane since the interface changes incompatibly.
# Now, you have a new libcdio with SONAME libcdio.so.1. But libvcdinfo and
# foobar still require libcdio.so.0. Everything is still fine.
# Now, after some minor changes, the author of foobar recompiles foobar.
# Then, foobar now requires libvcdinfo.so.0 and libcdio.so.1. And foobar
# now segfaults...
# What is happening? When you run foobar, if brings both libvcdinfo.so.0
# and libcdio.so.1, but libvcdinfo.so.0 also brings libcdio.so.0. So you
# have both libcdio.so.0 and libcdio.so.1 that bring their symbols to the
# global namespace. Hence, you have to incompatible versions of the
# cdio_open function in the name space. When foobar calls cdio_open, it
# may choose the wrong function, and segfaults...
# With versioned symbols, the cdio_open function from libcdio.so.0 may be
# known as (something that looks like) cdio_open@@CDIO_0. An the cdio_open
# function from libcdio.so.1 as cdio_open@@CDIO_1. Both versions of
# libcdio would still be brought in by the most recent foobar, but foobar
# (and libvcdinfo) know which versioned function to use and then use the
# good one.
# This is some simple versioning where every symbol is versioned with
# something that looks like the SONAME of the library. More complex (and
# better) versioning is possible; it is for example what is used by glibc.
# But good complex versioning is something that requires much more
# work...
# The below is a impliments symbol versioning. First of all, I
# compute MAJOR as CURENT - AGE; that is what is used within libtool
# (at least on GNU/Linux systems) for the number in the SONAME. The
# nm command gives the list of symbols known in each of the object
# files that will be part of the shared library. And the sed command
# extracts from this list those symbols that will be shared. (This sed
# command comes from libtool.)
libcdio_cdda_la_MAJOR = $(shell expr $(libcdio_cdda_la_CURRENT) - $(libcdio_cdda_la_AGE))
if BUILD_VERSIONED_LIBS
libcdio_cdda_la_LDFLAGS = $(libcdio_cdda_la_ldflags) -Wl,--version-script=libcdio_cdda.la.ver
libcdio_cdda_la_DEPENDENCIES = libcdio_cdda.la.ver
libcdio_cdda.la.ver: $(libcdio_cdda_la_OBJECTS) $(srcdir)/libcdio_cdda.sym
echo 'CDIO_CDDA_$(libcdio_cdda_la_MAJOR) { ' > $@
objs=`for obj in $(libcdio_cdda_la_OBJECTS); do sed -ne "s/^pic_object='\(.*\)'$$/\1/p" $$obj; done`; \
if test -n "$$objs" ; then \
nm $${objs} | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/\1/p' | sort -u | { first=true; while read symbol; do if grep -q "^$${symbol}\$$" $(srcdir)/libcdio_cdda.sym; then if test $$first = true; then echo " global:"; first=false; fi; echo " $${symbol};"; fi; done; } >> $@; \
nm $${objs} | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/\1/p' | sort -u | { first=true; while read symbol; do if grep -q "^$${symbol}\$$" $(srcdir)/libcdio_cdda.sym; then :; else if test $$first = true; then echo " local:"; first=false; fi; echo " $${symbol};"; fi; done; } >> $@; \
fi
echo '};' >> $@
else
libcdio_cdda_la_LDFLAGS = $(libcdio_cdda_la_ldflags)
endif
MOSTLYCLEANFILES = libcdio_cdda.la.ver

View File

@@ -1,402 +0,0 @@
/*
$Id: cddap_interface.c,v 1.8 2008/06/13 19:26:22 flameeyes Exp $
Copyright (C) 2004, 2005, 2007, 2008 Rocky Bernstein <rocky@gnu.org>
Original interface.c Copyright (C) 1994-1997
Eissfeldt heiko@colossus.escape.de
Current blenderization Copyright (C) 1998-1999 Monty xiphmont@mit.edu
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/**
CD-ROM code which interfaces between user-level visible CD paranoia
routines and libddio routines. (There is some GNU/Linux-specific
code here too that should probably be removed.
**/
#include "config.h"
#include "common_interface.h"
#include "low_interface.h"
#include "utils.h"
/** The below variables are trickery to force the above enum symbol
values to be recorded in debug symbol tables. They are used to
allow one to refer to the enumeration value names in the typedefs
above in a debugger and debugger expressions
*/
paranoia_jitter_t debug_paranoia_jitter;
paranoia_cdda_enums_t debug_paranoia_cdda_enums;
/*! reads TOC via libcdio and returns the number of tracks in the disc.
0 is returned if there was an error.
*/
static int
cddap_readtoc (cdrom_drive_t *d)
{
int i;
track_t i_track;
/* Save TOC Entries */
d->tracks = cdio_get_num_tracks(d->p_cdio) ;
if (CDIO_INVALID_TRACK == d->tracks) return 0;
i_track = cdio_get_first_track_num(d->p_cdio);
for ( i=0; i < d->tracks; i++) {
d->disc_toc[i].bTrack = i_track;
d->disc_toc[i].dwStartSector = cdio_get_track_lsn(d->p_cdio, i_track);
i_track++;
}
d->disc_toc[i].bTrack = i_track;
d->disc_toc[i].dwStartSector = cdio_get_track_lsn(d->p_cdio,
CDIO_CDROM_LEADOUT_TRACK);
d->cd_extra=FixupTOC(d, i_track);
return --i_track; /* without lead-out */
}
/* Set operating speed */
static int
cddap_setspeed(cdrom_drive_t *d, int i_speed)
{
return cdio_set_speed(d->p_cdio, i_speed);
}
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
read_blocks (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
int retry_count = 0;
int err;
char *buffer=(char *)p;
do {
err = cdio_read_audio_sectors( d->p_cdio, buffer, begin, i_sectors);
if ( DRIVER_OP_SUCCESS != err ) {
if (!d->error_retry) return -7;
if (i_sectors==1) {
/* *Could* be I/O or media error. I think. If we're at
30 retries, we better skip this unhappy little
sector. */
if (retry_count>MAX_RETRIES-1) {
char b[256];
snprintf(b, sizeof(b),
"010: Unable to access sector %ld: skipping...\n",
(long int) begin);
cderror(d, b);
return -10;
}
}
if(retry_count>4)
if(i_sectors>1)
i_sectors=i_sectors*3/4;
retry_count++;
if (retry_count>MAX_RETRIES) {
cderror(d,"007: Unknown, unrecoverable error reading data\n");
return(-7);
}
} else
break;
} while (err);
return(i_sectors);
}
typedef enum {
JITTER_NONE = 0,
JITTER_SMALL= 1,
JITTER_LARGE= 2,
JITTER_MASSIVE=3
} jitter_baddness_t;
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
jitter_read (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors,
jitter_baddness_t jitter_badness)
{
static int i_jitter=0;
int jitter_flag;
long i_sectors_orig = i_sectors;
long i_jitter_offset = 0;
char *p_buf=malloc(CDIO_CD_FRAMESIZE_RAW*(i_sectors+1));
if (d->i_test_flags & CDDA_TEST_ALWAYS_JITTER)
jitter_flag = 1;
else
#ifdef HAVE_DRAND48
jitter_flag = (drand48() > .9) ? 1 : 0;
#else
jitter_flag = (rand() > .9) ? 1 : 0;
#endif
if (jitter_flag) {
int i_coeff = 0;
int i_jitter_sectors = 0;
switch(jitter_badness) {
case JITTER_SMALL : i_coeff = 4; break;
case JITTER_LARGE : i_coeff = 32; break;
case JITTER_MASSIVE: i_coeff = 128; break;
case JITTER_NONE :
default : ;
}
#ifdef HAVE_DRAND48
i_jitter = i_coeff * (int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
i_jitter = i_coeff * (int)((rand()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#endif
/* We may need to add another sector to compensate for the bytes that
will be dropped off when jittering, and the begin location may
be a little different.
*/
i_jitter_sectors = i_jitter / CDIO_CD_FRAMESIZE_RAW;
if (i_jitter >= 0)
i_jitter_offset = i_jitter % CDIO_CD_FRAMESIZE_RAW;
else {
i_jitter_offset = CDIO_CD_FRAMESIZE_RAW -
(-i_jitter % CDIO_CD_FRAMESIZE_RAW);
i_jitter_sectors--;
}
if (begin + i_jitter_sectors > 0) {
#if !TRACE_PARANOIA
char buffer[256];
sprintf(buffer, "jittering by %d, offset %ld\n", i_jitter,
i_jitter_offset);
cdmessage(d,buffer);
#endif
begin += i_jitter_sectors;
i_sectors ++;
} else
i_jitter_offset = 0;
}
i_sectors = read_blocks(d, p_buf, begin, i_sectors);
if (i_sectors < 0) return i_sectors;
if (i_sectors < i_sectors_orig)
/* Had to reduce # of sectors due to read errors. So give full amount,
with no jittering. */
memcpy(p, p_buf, i_sectors*CDIO_CD_FRAMESIZE_RAW);
else {
/* Got full amount, but now adjust size for jittering. */
memcpy(p, p_buf+i_jitter_offset, i_sectors_orig*CDIO_CD_FRAMESIZE_RAW);
i_sectors = i_sectors_orig;
}
free(p_buf);
return(i_sectors);
}
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
cddap_read (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
jitter_baddness_t jitter_badness = d->i_test_flags & 0x3;
/* read d->nsectors at a time, max. */
i_sectors = ( i_sectors > d->nsectors && d->nsectors > 0 )
? d->nsectors : i_sectors;
/* If we are testing under-run correction, we will deliberately set
what we read a frame short. */
if (d->i_test_flags & CDDA_TEST_UNDERRUN )
i_sectors--;
if (jitter_badness) {
return jitter_read(d, p, begin, i_sectors, jitter_badness);
} else
return read_blocks(d, p, begin, i_sectors);
}
static int
verify_read_command(cdrom_drive_t *d)
{
int i;
int16_t *buff=malloc(CDIO_CD_FRAMESIZE_RAW);
int audioflag=0;
int i_test_flags = d->i_test_flags;
d->i_test_flags = 0;
cdmessage(d,"Verifying drive can read CDDA...\n");
d->enable_cdda(d,1);
for(i=1;i<=d->tracks;i++){
if(cdda_track_audiop(d,i)==1){
long firstsector=cdda_track_firstsector(d,i);
long lastsector=cdda_track_lastsector(d,i);
long sector=(firstsector+lastsector)>>1;
audioflag=1;
if(d->read_audio(d,buff,sector,1)>0){
cdmessage(d,"\tExpected command set reads OK.\n");
d->enable_cdda(d,0);
free(buff);
d->i_test_flags = i_test_flags;
return(0);
}
}
}
d->enable_cdda(d,0);
if(!audioflag){
cdmessage(d,"\tCould not find any audio tracks on this disk.\n");
free(buff);
return(-403);
}
cdmessage(d,"\n\tUnable to read any data; "
"drive probably not CDDA capable.\n");
cderror(d,"006: Could not read any data from drive\n");
free(buff);
return(-6);
}
#include "drive_exceptions.h"
#ifdef HAVE_LINUX_MAJOR_H
static void
check_exceptions(cdrom_drive_t *d, const exception_t *list)
{
int i=0;
while(list[i].model){
if(!strncmp(list[i].model,d->drive_model,strlen(list[i].model))){
if(list[i].bigendianp!=-1)d->bigendianp=list[i].bigendianp;
return;
}
i++;
}
}
#endif /* HAVE_LINUX_MAJOR_H */
/* set function pointers to use the ioctl routines */
int
cddap_init_drive (cdrom_drive_t *d)
{
int ret;
#if HAVE_LINUX_MAJOR_H
switch(d->drive_type){
case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */
case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */
case MATSUSHITA_CDROM3_MAJOR: /* sbpcd 3 */
case MATSUSHITA_CDROM4_MAJOR: /* sbpcd 4 */
/* don't make the buffer too big; this sucker don't preempt */
cdmessage(d,"Attempting to set sbpcd buffer size...\n");
d->nsectors=8;
#if BUFSIZE_DETERMINATION_FIXED
while(1){
/* this ioctl returns zero on error; exactly wrong, but that's
what it does. */
if (ioctl(d->ioctl_fd, CDROMAUDIOBUFSIZ, d->nsectors)==0) {
d->nsectors>>=1;
if(d->nsectors==0){
char buffer[256];
d->nsectors=8;
sprintf(buffer,"\tTrouble setting buffer size. Defaulting to %d sectors.\n",
d->nsectors);
cdmessage(d,buffer);
break; /* Oh, well. Try to read anyway.*/
}
} else {
char buffer[256];
sprintf(buffer,"\tSetting read block size at %d sectors (%ld bytes).\n",
d->nsectors,(long)d->nsectors*CDIO_CD_FRAMESIZE_RAW);
cdmessage(d,buffer);
break;
}
}
#endif /* BUFSIZE_DETERMINATION_FIXED */
break;
case IDE0_MAJOR:
case IDE1_MAJOR:
case IDE2_MAJOR:
case IDE3_MAJOR:
d->nsectors=8; /* it's a define in the linux kernel; we have no
way of determining other than this guess tho */
d->bigendianp=0;
d->is_atapi=1;
check_exceptions(d, atapi_list);
break;
default:
d->nsectors=25; /* The max for SCSI MMC2 */
}
#else
{
char buffer[256];
d->nsectors = 8;
sprintf(buffer,"\tSetting read block size at %d sectors (%ld bytes).\n",
d->nsectors,(long)d->nsectors*CDIO_CD_FRAMESIZE_RAW);
cdmessage(d,buffer);
}
#endif /*HAVE_LINUX_MAJOR_H*/
d->enable_cdda = dummy_exception;
d->set_speed = cddap_setspeed;
d->read_toc = cddap_readtoc;
d->read_audio = cddap_read;
ret = d->tracks = d->read_toc(d);
if(d->tracks<1)
return(ret);
d->opened=1;
if( (ret=verify_read_command(d)) ) return(ret);
d->error_retry=1;
return(0);
}

View File

@@ -1,271 +0,0 @@
/*
Copyright (C) 2004, 2005, 2007, 2008, 2010, 2011
Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998, 2002 Monty monty@xiph.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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
*
* CDROM communication common to all interface methods is done here
* (mostly ioctl stuff, but not ioctls specific to the 'cooked'
* interface)
*
******************************************************************/
/* common_interface.h has to come first else _FILE_OFFSET_BITS are
redefined in say opensolaris. */
#include "common_interface.h"
#include <math.h>
#include "utils.h"
#include "smallft.h"
/* Variables to hold debugger-helping enumerations */
enum paranoia_cdda_enums;
enum paranoia_jitter_enums;
/*! Determine Endian-ness of the CD-drive based on reading data from
it. Some drives return audio data Big Endian while some (most)
return data Little Endian. Drives known to return data bigendian are
SCSI drives from Kodak, Ricoh, HP, Philips, Plasmon, Grundig
CDR100IPW, and Mitsumi CD-R. ATAPI and MMC drives are little endian.
rocky: As someone who didn't write the code, I have to say this is
nothing less than brilliant. An FFT is done both ways and the the
transform is looked at to see which has data in the FFT (or audible)
portion. (Or so that's how I understand it.)
@return 1 if big-endian, 0 if little-endian, -1 if we couldn't
figure things out or some error.
*/
int
data_bigendianp(cdrom_drive_t *d)
{
float lsb_votes=0;
float msb_votes=0;
int i,checked;
int endiancache=d->bigendianp;
float *a=calloc(1024,sizeof(float));
float *b=calloc(1024,sizeof(float));
long readsectors=5;
int16_t *buff=malloc(readsectors*CDIO_CD_FRAMESIZE_RAW*sizeof(int16_t));
memset(buff, 0, readsectors*CDIO_CD_FRAMESIZE_RAW*sizeof(int16_t));
/* look at the starts of the audio tracks */
/* if real silence, tool in until some static is found */
/* Force no swap for now */
d->bigendianp=-1;
cdmessage(d,"\nAttempting to determine drive endianness from data...");
d->enable_cdda(d,1);
for(i=0,checked=0;i<d->tracks;i++){
float lsb_energy=0;
float msb_energy=0;
if(cdda_track_audiop(d,i+1)==1){
long firstsector=cdda_track_firstsector(d,i+1);
long lastsector=cdda_track_lastsector(d,i+1);
int zeroflag=-1;
long beginsec=0;
/* find a block with nonzero data */
while(firstsector+readsectors<=lastsector){
int j;
if(d->read_audio(d,buff,firstsector,readsectors)>0){
/* Avoid scanning through jitter at the edges */
for(beginsec=0;beginsec<readsectors;beginsec++){
int offset=beginsec*CDIO_CD_FRAMESIZE_RAW/2;
/* Search *half* */
for(j=460;j<128+460;j++)
if(buff[offset+j]!=0){
zeroflag=0;
break;
}
if(!zeroflag)break;
}
if(!zeroflag)break;
firstsector+=readsectors;
}else{
d->enable_cdda(d,0);
free(a);
free(b);
free(buff);
return(-1);
}
}
beginsec*=CDIO_CD_FRAMESIZE_RAW/2;
/* un-interleave for an FFT */
if(!zeroflag){
int j;
for(j=0;j<128;j++)
a[j] = le16_to_cpu(buff[j*2+beginsec+460]);
for(j=0;j<128;j++)
b[j] = le16_to_cpu(buff[j*2+beginsec+461]);
fft_forward(128,a,NULL,NULL);
fft_forward(128,b,NULL,NULL);
for(j=0;j<128;j++)
lsb_energy+=fabs(a[j])+fabs(b[j]);
for(j=0;j<128;j++)
a[j] = be16_to_cpu(buff[j*2+beginsec+460]);
for(j=0;j<128;j++)
b[j] = be16_to_cpu(buff[j*2+beginsec+461]);
fft_forward(128,a,NULL,NULL);
fft_forward(128,b,NULL,NULL);
for(j=0;j<128;j++)
msb_energy+=fabs(a[j])+fabs(b[j]);
}
}
if(lsb_energy<msb_energy){
lsb_votes+=msb_energy/lsb_energy;
checked++;
}else
if(lsb_energy>msb_energy){
msb_votes+=lsb_energy/msb_energy;
checked++;
}
if(checked==5 && (lsb_votes==0 || msb_votes==0))break;
cdmessage(d,".");
}
free(buff);
free(a);
free(b);
d->bigendianp=endiancache;
d->enable_cdda(d,0);
/* How did we vote? Be potentially noisy */
if (lsb_votes>msb_votes) {
char buffer[256];
cdmessage(d,"\n\tData appears to be coming back Little Endian.\n");
sprintf(buffer,"\tcertainty: %d%%\n",(int)
(100.*lsb_votes/(lsb_votes+msb_votes)+.5));
cdmessage(d,buffer);
return(0);
} else {
if(msb_votes>lsb_votes){
char buffer[256];
cdmessage(d,"\n\tData appears to be coming back Big Endian.\n");
sprintf(buffer,"\tcertainty: %d%%\n",(int)
(100.*msb_votes/(lsb_votes+msb_votes)+.5));
cdmessage(d,buffer);
return(1);
}
cdmessage(d,"\n\tCannot determine CDROM drive endianness.\n");
return(bigendianp());
}
}
/************************************************************************/
/*! Here we fix up a couple of things that will never happen. yeah,
right.
The multisession stuff is from Hannu code; it assumes it knows the
leadout/leadin size. [I think Hannu refers to Hannu Savolainen
from GNU/Linux Kernel code.]
@return -1 if we can't get multisession info, 0 if there is one
session only or the last session LBA is the same as the first audio
track and 1 if the multi-session lba is higher than first audio track
*/
int
FixupTOC(cdrom_drive_t *d, track_t i_tracks)
{
int j;
/* First off, make sure the 'starting sector' is >=0 */
for( j=0; j<i_tracks; j++){
if (d->disc_toc[j].dwStartSector<0 ) {
cdmessage(d,"\n\tTOC entry claims a negative start offset: massaging"
".\n");
d->disc_toc[j].dwStartSector=0;
}
if( j<i_tracks-1 && d->disc_toc[j].dwStartSector>
d->disc_toc[j+1].dwStartSector ) {
cdmessage(d,"\n\tTOC entry claims an overly large start offset: massaging"
".\n");
d->disc_toc[j].dwStartSector=0;
}
}
/* Make sure the listed 'starting sectors' are actually increasing.
Flag things that are blatant/stupid/wrong */
{
lsn_t last=d->disc_toc[0].dwStartSector;
for ( j=1; j<i_tracks; j++){
if ( d->disc_toc[j].dwStartSector<last ) {
cdmessage(d,"\n\tTOC entries claim non-increasing offsets: massaging"
".\n");
d->disc_toc[j].dwStartSector=last;
}
last=d->disc_toc[j].dwStartSector;
}
}
d->audio_last_sector = CDIO_INVALID_LSN;
{
lsn_t last_ses_lsn;
if (cdio_get_last_session (d->p_cdio, &last_ses_lsn) < 0)
return -1;
/* A Red Book Disc must have only one session, otherwise this is a
* CD Extra */
if (last_ses_lsn > d->disc_toc[0].dwStartSector) {
/* CD Extra discs have two session, the first one ending after
* the last audio track
* Thus the need to fix the length of the the audio data portion to
* not cross the lead-out of this session */
for (j = i_tracks-1; j > 1; j--) {
if (cdio_get_track_format(d->p_cdio, j+1) != TRACK_FORMAT_AUDIO &&
cdio_get_track_format(d->p_cdio, j) == TRACK_FORMAT_AUDIO) {
/* First session lead-out is 1:30
* Lead-ins are 1:00
* Every session's first track have a 0:02 pregap
*
* That makes a control data section of (90+60+2)*75 sectors in the
* last audio track */
const int gap = ((90+60+2) * CDIO_CD_FRAMES_PER_SEC);
if ((last_ses_lsn - gap >= d->disc_toc[j-1].dwStartSector) &&
(last_ses_lsn - gap < d->disc_toc[j].dwStartSector)) {
d->audio_last_sector = last_ses_lsn - gap - 1;
break;
}
}
}
return 1;
}
}
return 0;
}

View File

@@ -1,54 +0,0 @@
/*
Copyright (C) 2004, 2005, 2008, 2009, 2010, 2011
Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CDDA_COMMON_INTERFACE_H_
#define _CDDA_COMMON_INTERFACE_H_
#if defined(HAVE_CONFIG_H) && !defined(__CDIO_CONFIG_H__)
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include <cdio/types.h>
#include "low_interface.h"
#if defined(HAVE_LSTAT) && !defined(HAVE_WIN32_CDROM) && !defined(HAVE_OS2_CDROM)
/* Define this if the CD-ROM device is a file in the filesystem
that can be lstat'd
*/
#define DEVICE_IN_FILESYSTEM 1
#else
#undef DEVICE_IN_FILESYSTEM
#endif
/** Test for presence of a cdrom by pinging with the 'CDROMVOLREAD' ioctl() */
extern int ioctl_ping_cdrom(int fd);
extern char *atapi_drive_info(int fd);
/*! Here we fix up a couple of things that will never happen. yeah,
right.
rocky OMITTED FOR NOW:
The multisession stuff is from Hannu's code; it assumes it knows
the leadout/leadin size.
*/
extern int FixupTOC(cdrom_drive_t *d, track_t tracks);
#endif /*_CDDA_COMMON_INTERFACE_H_*/

View File

@@ -1,82 +0,0 @@
/*
Copyright (C) 2004, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "common_interface.h"
#include "drive_exceptions.h"
int dummy_exception (cdrom_drive_t *d,int Switch)
{
return(0);
}
#if HAVE_LINUX_MAJOR_H
/* list of drives that affect autosensing in ATAPI specific portions of code
(force drives to detect as ATAPI or SCSI, force ATAPI read command */
const exception_t atapi_list[]={
{"SAMSUNG SCR-830 REV 2.09 2.09 ", 1, 0, dummy_exception,scsi_read_mmc2,0},
{"Memorex CR-622", 1, 0, dummy_exception, NULL,0},
{"SONY CD-ROM CDU-561", 0, 0, dummy_exception, NULL,0},
{"Chinon CD-ROM CDS-525", 0, 0, dummy_exception, NULL,0},
{NULL,0,0,NULL,NULL,0}};
#endif /*HAVE_LINUX_MAJOR_H*/
/* list of drives that affect MMC default settings */
#ifdef NEED_MMC_LIST
static exception_t mmc_list[]={
{"SAMSUNG SCR-830 REV 2.09 2.09 ", 1, 0, dummy_exception,scsi_read_mmc2,0},
{"Memorex CR-622", 1, 0, dummy_exception, NULL,0},
{"SONY CD-ROM CDU-561", 0, 0, dummy_exception, NULL,0},
{"Chinon CD-ROM CDS-525", 0, 0, dummy_exception, NULL,0},
{"KENWOOD CD-ROM UCR", -1, 0, NULL,scsi_read_D8, 0},
{NULL,0,0,NULL,NULL,0}};
#endif /*NEED_MMC_LIST*/
/* list of drives that affect SCSI default settings */
#ifdef NEED_SCSI_LIST
static exception_t scsi_list[]={
{"TOSHIBA", -1,0x82,scsi_enable_cdda,scsi_read_28, 0},
{"IBM", -1,0x82,scsi_enable_cdda,scsi_read_28, 0},
{"DEC", -1,0x82,scsi_enable_cdda,scsi_read_28, 0},
{"IMS", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"KODAK", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"RICOH", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"HP", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"PHILIPS", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"PLASMON", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"GRUNDIG CDR100IPW", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"MITSUMI CD-R ", -1, 0,scsi_enable_cdda,scsi_read_28, 1},
{"KENWOOD CD-ROM UCR", -1, 0, NULL,scsi_read_D8, 0},
{"YAMAHA", -1, 0,scsi_enable_cdda, NULL, 0},
{"PLEXTOR", -1, 0, NULL, NULL, 0},
{"SONY", -1, 0, NULL, NULL, 0},
{"NEC", -1, 0, NULL,scsi_read_D4_10,0},
/* the 7501 locks up if hit with the 10 byte version from the
autoprobe first */
{"MATSHITA CD-R CW-7501", -1, 0, NULL,scsi_read_D4_12,-1},
{NULL,0,0,NULL,NULL,0}};
#endif /* NEED_SCSI_LIST*/

View File

@@ -1,58 +0,0 @@
/*
$Id: drive_exceptions.h,v 1.6 2008/06/13 19:26:23 flameeyes Exp $
Copyright (C) 2004, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
extern int scsi_enable_cdda(cdrom_drive_t *d, int);
extern long scsi_read_mmc(cdrom_drive_t *d, void *,long,long);
extern long scsi_read_D4_10(cdrom_drive_t *, void *,long,long);
extern long scsi_read_D4_12(cdrom_drive_t *, void *,long,long);
extern long scsi_read_D8(cdrom_drive_t *, void *,long,long);
extern long scsi_read_28(cdrom_drive_t *, void *,long,long);
extern long scsi_read_A8(cdrom_drive_t *, void *,long,long);
typedef struct exception {
const char *model;
int atapi; /* If the ioctl doesn't work */
unsigned char density;
int (*enable)(cdrom_drive_t *,int);
long (*read)(cdrom_drive_t *,void *, long, long);
int bigendianp;
} exception_t;
/* specific to general */
#ifdef FINISHED_DRIVE_EXCEPTIONS
extern long scsi_read_mmc2(cdrom_drive_t *d, void *,long,long);
#else
#define scsi_read_mmc2 NULL
#endif
int dummy_exception (cdrom_drive_t *d,int Switch);
#if HAVE_LINUX_MAJOR_H
extern const exception_t atapi_list[];
#endif
#ifdef NEED_MMC_LIST
extern const exception_t mmc_list[];
#endif
#ifdef NEED_SCSI_LIST
extern const exception_t scsi_list[];
#endif

View File

@@ -1,188 +0,0 @@
/*
$Id: interface.c,v 1.26 2008/04/16 17:00:40 karl Exp $
Copyright (C) 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
* Top-level interface module for cdrom drive access. SCSI, ATAPI, etc
* specific stuff are in other modules. Note that SCSI does use
* specialized ioctls; these appear in common_interface.c where the
* generic_scsi stuff is in scsi_interface.c.
*
******************************************************************/
#include "common_interface.h"
#include "low_interface.h"
#include "utils.h"
#include <cdio/bytesex.h>
#include <cdio/mmc.h>
static void _clean_messages(cdrom_drive_t *d)
{
if(d){
if(d->messagebuf)free(d->messagebuf);
if(d->errorbuf)free(d->errorbuf);
d->messagebuf=NULL;
d->errorbuf=NULL;
}
}
/*!
Closes d and releases all storage associated with it except
the internal p_cdio pointer.
@param d cdrom_drive_t object to be closed.
@return 0 if passed a null pointer and 1 if not in which case
some work was probably done.
@see cdio_cddap_close
*/
bool
cdio_cddap_close_no_free_cdio(cdrom_drive_t *d)
{
if(d){
if(d->opened)
d->enable_cdda(d,0);
_clean_messages(d);
if (d->cdda_device_name) free(d->cdda_device_name);
if (d->drive_model) free(d->drive_model);
d->cdda_device_name = d->drive_model = NULL;
free(d);
return true;
}
return false;
}
/*!
Closes d and releases all storage associated with it.
Doubles as "cdrom_drive_free()".
@param d cdrom_drive_t object to be closed.
@return 0 if passed a null pointer and 1 if not in which case
some work was probably done.
@see cdio_cddap_close_no_free_cdio
*/
int
cdio_cddap_close(cdrom_drive_t *d)
{
if (d) {
CdIo_t *p_cdio = d->p_cdio;
cdio_cddap_close_no_free_cdio(d);
cdio_destroy (p_cdio);
return 1;
}
return 0;
}
/* finish initializing the drive! */
int
cdio_cddap_open(cdrom_drive_t *d)
{
int ret;
if(d->opened)return(0);
if ( (ret=cddap_init_drive(d)) )
return(ret);
/* Check TOC, enable for CDDA */
/* Some drives happily return a TOC even if there is no disc... */
{
int i;
for(i=0; i<d->tracks; i++)
if(d->disc_toc[i].dwStartSector<0 ||
d->disc_toc[i+1].dwStartSector==0){
d->opened=0;
cderror(d,"009: CDROM reporting illegal table of contents\n");
return(-9);
}
}
if((ret=d->enable_cdda(d,1)))
return(ret);
/* d->select_speed(d,d->maxspeed); most drives are full speed by default */
if ( -1 == d->bigendianp ) {
d->bigendianp = data_bigendianp(d);
}
return(0);
}
int
cdio_cddap_speed_set(cdrom_drive_t *d, int speed)
{
return d->set_speed ? d->set_speed(d, speed) : 0;
}
long
cdio_cddap_read(cdrom_drive_t *d, void *buffer, lsn_t beginsector,
long sectors)
{
if (d->opened) {
if (sectors>0) {
sectors=d->read_audio(d, buffer, beginsector, sectors);
if (sectors > 0) {
/* byteswap? */
if ( d->bigendianp == -1 ) /* not determined yet */
d->bigendianp = data_bigendianp(d);
if ( d->b_swap_bytes && d->bigendianp != bigendianp() ) {
int i;
uint16_t *p=(uint16_t *)buffer;
long els=sectors*CDIO_CD_FRAMESIZE_RAW/2;
for(i=0;i<els;i++)
p[i]=UINT16_SWAP_LE_BE_C(p[i]);
}
}
}
return(sectors);
}
cderror(d,"400: Device not open\n");
return(-400);
}
void
cdio_cddap_verbose_set(cdrom_drive_t *d,int err_action, int mes_action)
{
d->messagedest=mes_action;
d->errordest=err_action;
}
extern char *
cdio_cddap_messages(cdrom_drive_t *d)
{
char *ret=d->messagebuf;
d->messagebuf=NULL;
return(ret);
}
extern char *
cdio_cddap_errors(cdrom_drive_t *d)
{
char *ret=d->errorbuf;
d->errorbuf=NULL;
return(ret);
}

View File

@@ -1,23 +0,0 @@
cdio_cddap_find_a_cdrom
cdio_cddap_identify
cdio_cddap_identify_cdio
cdio_cddap_speed_set
cdio_cddap_verbose_set
cdio_cddap_messages
cdio_cddap_errors
cdio_cddap_close_no_free_cdio
cdio_cddap_close
cdio_cddap_open
cdio_cddap_read
cdio_cddap_track_firstsector
cdio_cddap_track_lastsector
cdio_cddap_tracks
cdio_cddap_sector_gettrack
cdio_cddap_track_channels
cdio_cddap_track_audiop
cdio_cddap_track_copyp
cdio_cddap_track_preemp
cdio_cddap_disc_firstsector
cdio_cddap_disc_lastsector
data_bigendianp
fft_forward

View File

@@ -1,66 +0,0 @@
/*
$Id: low_interface.h,v 1.9 2008/04/16 17:00:40 karl Exp $
Copyright (C) 2004, 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/** internal include file for cdda interface kit for Linux */
#ifndef _CDDA_LOW_INTERFACE_
#define _CDDA_LOW_INTERFACE_
#ifdef HAVE_STDIO_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LINUX_VERSION_H
#include <linux/version.h>
#endif
#include <cdio/paranoia.h>
#include <cdio/cdda.h>
/* some include file locations have changed with newer kernels */
#ifndef CDROMAUDIOBUFSIZ
#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
#endif
#ifdef HAVE_LINUX_CDROM_H
#include <linux/cdrom.h>
#endif
#ifdef HAVE_LINUX_MAJOR_H
#include <linux/major.h>
#endif
#define MAX_RETRIES 8
#define MAX_BIG_BUFF_SIZE 65536
#define MIN_BIG_BUFF_SIZE 4096
#define SG_OFF sizeof(struct sg_header)
extern int cddap_init_drive (cdrom_drive_t *d);
#endif /*_CDDA_LOW_INTERFACE_*/

View File

@@ -1,343 +0,0 @@
/*
$Id: scan_devices.c,v 1.33 2008/06/16 19:45:44 flameeyes Exp $
Copyright (C) 2004, 2005, 2007, 2008, 2009 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
*
* Autoscan for or verify presence of a CD-ROM device
*
******************************************************************/
#include "common_interface.h"
#include "low_interface.h"
#include "utils.h"
#include "cdio/mmc.h"
#include "cdio/util.h"
#include <limits.h>
#include <ctype.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define MAX_DEV_LEN 20 /* Safe because strings only come from below */
/* must be absolute paths! */
static const char scsi_cdrom_prefixes[][16]={
"/dev/scd",
"/dev/sr",
""};
static const char scsi_generic_prefixes[][16]={
"/dev/sg",
""};
static const char devfs_scsi_test[]="/dev/scsi/";
static const char devfs_scsi_cd[]="cd";
static const char devfs_scsi_generic[]="generic";
static const char cdrom_devices[][32]={
"/dev/cdrom",
"/dev/cdroms/cdrom?",
"/dev/hd?",
"/dev/sg?",
"/dev/cdu31a",
"/dev/cdu535",
"/dev/sbpcd",
"/dev/sbpcd?",
"/dev/sonycd",
"/dev/mcd",
"/dev/sjcd",
/* "/dev/aztcd", timeout is too long */
"/dev/cm206cd",
"/dev/gscd",
"/dev/optcd",
""};
static cdrom_drive_t *
cdda_identify_device_cdio(CdIo_t *p_cdio, const char *psz_device,
int messagedest, char **ppsz_messages);
/* Functions here look for a cdrom drive; full init of a drive type
happens in interface.c */
cdrom_drive_t *
cdio_cddap_find_a_cdrom(int messagedest, char **ppsz_messages){
/* Brute force... */
int i=0;
cdrom_drive_t *d;
while(*cdrom_devices[i]!='\0'){
/* is it a name or a pattern? */
char *pos;
if((pos=strchr(cdrom_devices[i],'?'))){
int j;
/* try first eight of each device */
for(j=0;j<4;j++){
char *buffer=strdup(cdrom_devices[i]);
/* number, then letter */
buffer[pos-(cdrom_devices[i])]=j+48;
if((d=cdda_identify(buffer, messagedest, ppsz_messages)))
return(d);
idmessage(messagedest, ppsz_messages, "", NULL);
buffer[pos-(cdrom_devices[i])]=j+97;
if((d=cdda_identify(buffer, messagedest, ppsz_messages)))
return(d);
idmessage(messagedest, ppsz_messages, "", NULL);
free(buffer);
}
}else{
/* Name. Go for it. */
if((d=cdda_identify(cdrom_devices[i], messagedest, ppsz_messages)))
return(d);
idmessage(messagedest, ppsz_messages, "", NULL);
}
i++;
}
{
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
struct passwd *temp;
temp=getpwuid(geteuid());
idmessage(messagedest, ppsz_messages,
"\n\nNo cdrom drives accessible to %s found.\n",
temp->pw_name);
#else
idmessage(messagedest, ppsz_messages,
"\n\nNo cdrom drives accessible found.\n", NULL);
#endif
}
return(NULL);
}
#ifdef DEVICE_IN_FILESYSTEM
static char *
test_resolve_symlink(const char *file, int messagedest, char **ppsz_messages)
{
char resolved[PATH_MAX];
struct stat st;
if (lstat(file,&st)){
idperror(messagedest, ppsz_messages, "\t\tCould not stat %s",file);
return(NULL);
}
if (cdio_realpath(file,resolved))
return(strdup(resolved));
idperror(messagedest, ppsz_messages, "\t\tCould not resolve symlink %s",
file);
return(NULL);
}
#endif
/** Returns a paranoia CD-ROM drive object with a CD-DA in it or NULL
if there was an error.
@see cdio_cddap_identify_cdio
*/
cdrom_drive_t *
cdio_cddap_identify(const char *psz_dev, int messagedest,
char **ppsz_messages)
{
CdIo_t *p_cdio = NULL;
if (psz_dev)
idmessage(messagedest, ppsz_messages, "Checking %s for cdrom...",
psz_dev);
else
idmessage(messagedest, ppsz_messages, "Checking for cdrom...", NULL);
#ifdef DEVICE_IN_FILESYSTEM
if (psz_dev) {
char *psz_device = test_resolve_symlink(psz_dev, messagedest,
ppsz_messages);
if ( psz_device ) {
cdrom_drive_t *d=NULL;
p_cdio = cdio_open(psz_device, DRIVER_UNKNOWN);
d = cdda_identify_device_cdio(p_cdio, psz_device, messagedest,
ppsz_messages);
free(psz_device);
return d;
}
}
#endif
p_cdio = cdio_open(psz_dev, DRIVER_UNKNOWN);
if (p_cdio) {
if (!psz_dev) {
psz_dev = cdio_get_arg(p_cdio, "source");
}
return cdda_identify_device_cdio(p_cdio, psz_dev, messagedest,
ppsz_messages);
}
return NULL;
}
/** Returns a paranoia CD-ROM drive object with a CD-DA in it or NULL
if there was an error. In contrast to cdio_cddap_identify, we
start out with an initialized p_cdio object. For example you may
have used that for other purposes such as to get CDDB/CD-Text
information. @see cdio_cddap_identify
*/
cdrom_drive_t *
cdio_cddap_identify_cdio(CdIo_t *p_cdio, int messagedest, char **ppsz_messages)
{
if (!p_cdio) return NULL;
{
const char *psz_device = cdio_get_arg(p_cdio, "source");
idmessage(messagedest, ppsz_messages, "Checking %s for cdrom...",
psz_device);
return cdda_identify_device_cdio(p_cdio, psz_device, messagedest,
ppsz_messages);
}
}
static cdrom_drive_t *
cdda_identify_device_cdio(CdIo_t *p_cdio, const char *psz_device,
int messagedest, char **ppsz_messages)
{
cdrom_drive_t *d=NULL;
int drive_type = 0;
char *description=NULL;
#ifdef HAVE_LINUX_MAJOR_H
struct stat st;
#endif
if (!p_cdio) {
idperror(messagedest, ppsz_messages, "\t\tUnable to open %s", psz_device);
return NULL;
}
#ifdef HAVE_LINUX_MAJOR_H
if ( 0 == stat(psz_device, &st) ) {
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
drive_type=(int)(st.st_rdev>>8);
switch (drive_type) {
case IDE0_MAJOR:
case IDE1_MAJOR:
case IDE2_MAJOR:
case IDE3_MAJOR:
/* Yay, ATAPI... */
description=strdup("ATAPI compatible ");
break;
case CDU31A_CDROM_MAJOR:
/* major indicates this is a cdrom; no ping necessary. */
description=strdup("Sony CDU31A or compatible");
break;
case CDU535_CDROM_MAJOR:
/* major indicates this is a cdrom; no ping necessary. */
description=strdup("Sony CDU535 or compatible");
break;
case MATSUSHITA_CDROM_MAJOR:
case MATSUSHITA_CDROM2_MAJOR:
case MATSUSHITA_CDROM3_MAJOR:
case MATSUSHITA_CDROM4_MAJOR:
/* major indicates this is a cdrom; no ping necessary. */
description=strdup("non-ATAPI IDE-style Matsushita/Panasonic CR-5xx or compatible");
break;
case SANYO_CDROM_MAJOR:
description=strdup("Sanyo proprietary or compatible: NOT CDDA CAPABLE");
break;
case MITSUMI_CDROM_MAJOR:
case MITSUMI_X_CDROM_MAJOR:
description=strdup("Mitsumi proprietary or compatible: NOT CDDA CAPABLE");
break;
case OPTICS_CDROM_MAJOR:
description=strdup("Optics Dolphin or compatible: NOT CDDA CAPABLE");
break;
case AZTECH_CDROM_MAJOR:
description=strdup("Aztech proprietary or compatible: NOT CDDA CAPABLE");
break;
case GOLDSTAR_CDROM_MAJOR:
description=strdup("Goldstar proprietary: NOT CDDA CAPABLE");
break;
case CM206_CDROM_MAJOR:
description=strdup("Philips/LMS CM206 proprietary: NOT CDDA CAPABLE");
break;
case SCSI_CDROM_MAJOR:
case SCSI_GENERIC_MAJOR:
/* Nope nope nope */
description=strdup("SCSI CD-ROM");
break;
default:
/* What the hell is this? */
idmessage(messagedest, ppsz_messages,
"\t\t%s is not a cooked ioctl CDROM.",
psz_device);
return(NULL);
}
}
}
#endif /*HAVE_LINUX_MAJOR_H*/
/* Minimum init */
d=calloc(1, sizeof(cdrom_drive_t));
d->p_cdio = p_cdio;
d->cdda_device_name = strdup(psz_device);
d->drive_type = drive_type;
d->bigendianp = -1; /* We don't know yet... */
d->nsectors = -1; /* We don't know yet... */
d->messagedest = messagedest;
d->b_swap_bytes = true;
{
cdio_hwinfo_t hw_info = {
"UNKNOWN", "Unknown model", "????"
};
if ( mmc_get_hwinfo( p_cdio, &hw_info ) ) {
unsigned int i_len = strlen(hw_info.psz_vendor)
+ strlen(hw_info.psz_model)
+ strlen(hw_info.psz_revision) + 5;
if (description) {
i_len += strlen(description);
d->drive_model=malloc( i_len );
snprintf( d->drive_model, i_len, "%s %s %s %s",
hw_info.psz_vendor, hw_info.psz_model, hw_info.psz_revision,
description );
} else {
d->drive_model=malloc( i_len );
snprintf( d->drive_model, i_len, "%s %s %s",
hw_info.psz_vendor, hw_info.psz_model, hw_info.psz_revision
);
}
idmessage(messagedest, ppsz_messages, "\t\tCDROM sensed: %s\n",
d->drive_model);
}
}
if (description)
free(description);
return(d);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,561 +0,0 @@
/*
$Id: smallft.c,v 1.2 2008/04/16 17:00:40 karl Exp $
Copyright (C) 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
* FFT implementation from OggSquish, minus cosine transforms,
* minus all but radix 2/4 case
*
* See OggSquish or NetLib for the version that can do other than just
* power-of-two sized vectors.
******************************************************************/
#include <stdlib.h>
#include <math.h>
#include "smallft.h"
static void drfti1(int n, float *wa, int *ifac){
static int ntryh[4] = { 4,2,3,5 };
static float tpi = 6.28318530717958647692528676655900577;
float arg,argh,argld,fi;
int ntry=0,i,j=-1;
int k1, l1, l2, ib;
int ld, ii, ip, is, nq, nr;
int ido, ipm, nfm1;
int nl=n;
int nf=0;
L101:
j++;
if (j < 4)
ntry=ntryh[j];
else
ntry+=2;
L104:
nq=nl/ntry;
nr=nl-ntry*nq;
if (nr!=0) goto L101;
nf++;
ifac[nf+1]=ntry;
nl=nq;
if(ntry!=2)goto L107;
if(nf==1)goto L107;
for (i=1;i<nf;i++){
ib=nf-i+1;
ifac[ib+1]=ifac[ib];
}
ifac[2] = 2;
L107:
if(nl!=1)goto L104;
ifac[0]=n;
ifac[1]=nf;
argh=tpi/n;
is=0;
nfm1=nf-1;
l1=1;
if(nfm1==0)return;
for (k1=0;k1<nfm1;k1++){
ip=ifac[k1+2];
ld=0;
l2=l1*ip;
ido=n/l2;
ipm=ip-1;
for (j=0;j<ipm;j++){
ld+=l1;
i=is;
argld=(float)ld*argh;
fi=0.;
for (ii=2;ii<ido;ii+=2){
fi+=1.;
arg=fi*argld;
wa[i++]=cos(arg);
wa[i++]=sin(arg);
}
is+=ido;
}
l1=l2;
}
}
static void fdrffti(int n, float *wsave, int *ifac){
if (n == 1) return;
drfti1(n, wsave+n, ifac);
}
static void dradf2(int ido,int l1,float *cc,float *ch,float *wa1){
int i,k;
float ti2,tr2;
int t0,t1,t2,t3,t4,t5,t6;
t1=0;
t0=(t2=l1*ido);
t3=ido<<1;
for(k=0;k<l1;k++){
ch[t1<<1]=cc[t1]+cc[t2];
ch[(t1<<1)+t3-1]=cc[t1]-cc[t2];
t1+=ido;
t2+=ido;
}
if(ido<2)return;
if(ido==2)goto L105;
t1=0;
t2=t0;
for(k=0;k<l1;k++){
t3=t2;
t4=(t1<<1)+(ido<<1);
t5=t1;
t6=t1+t1;
for(i=2;i<ido;i+=2){
t3+=2;
t4-=2;
t5+=2;
t6+=2;
tr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
ti2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
ch[t6]=cc[t5]+ti2;
ch[t4]=ti2-cc[t5];
ch[t6-1]=cc[t5-1]+tr2;
ch[t4-1]=cc[t5-1]-tr2;
}
t1+=ido;
t2+=ido;
}
if(ido%2==1)return;
L105:
t3=(t2=(t1=ido)-1);
t2+=t0;
for(k=0;k<l1;k++){
ch[t1]=-cc[t2];
ch[t1-1]=cc[t3];
t1+=ido<<1;
t2+=ido;
t3+=ido;
}
}
static void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
float *wa2,float *wa3){
static float hsqt2 = .70710678118654752440084436210485;
int i,k,t0,t1,t2,t3,t4,t5,t6;
float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
t0=l1*ido;
t1=t0;
t4=t1<<1;
t2=t1+(t1<<1);
t3=0;
for(k=0;k<l1;k++){
tr1=cc[t1]+cc[t2];
tr2=cc[t3]+cc[t4];
ch[t5=t3<<2]=tr1+tr2;
ch[(ido<<2)+t5-1]=tr2-tr1;
ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4];
ch[t5]=cc[t2]-cc[t1];
t1+=ido;
t2+=ido;
t3+=ido;
t4+=ido;
}
if(ido<2)return;
if(ido==2)goto L105;
t1=0;
for(k=0;k<l1;k++){
t2=t1;
t4=t1<<2;
t5=(t6=ido<<1)+t4;
for(i=2;i<ido;i+=2){
t3=(t2+=2);
t4+=2;
t5-=2;
t3+=t0;
cr2=wa1[i-2]*cc[t3-1]+wa1[i-1]*cc[t3];
ci2=wa1[i-2]*cc[t3]-wa1[i-1]*cc[t3-1];
t3+=t0;
cr3=wa2[i-2]*cc[t3-1]+wa2[i-1]*cc[t3];
ci3=wa2[i-2]*cc[t3]-wa2[i-1]*cc[t3-1];
t3+=t0;
cr4=wa3[i-2]*cc[t3-1]+wa3[i-1]*cc[t3];
ci4=wa3[i-2]*cc[t3]-wa3[i-1]*cc[t3-1];
tr1=cr2+cr4;
tr4=cr4-cr2;
ti1=ci2+ci4;
ti4=ci2-ci4;
ti2=cc[t2]+ci3;
ti3=cc[t2]-ci3;
tr2=cc[t2-1]+cr3;
tr3=cc[t2-1]-cr3;
ch[t4-1]=tr1+tr2;
ch[t4]=ti1+ti2;
ch[t5-1]=tr3-ti4;
ch[t5]=tr4-ti3;
ch[t4+t6-1]=ti4+tr3;
ch[t4+t6]=tr4+ti3;
ch[t5+t6-1]=tr2-tr1;
ch[t5+t6]=ti1-ti2;
}
t1+=ido;
}
if(ido&1)return;
L105:
t2=(t1=t0+ido-1)+(t0<<1);
t3=ido<<2;
t4=ido;
t5=ido<<1;
t6=ido;
for(k=0;k<l1;k++){
ti1=-hsqt2*(cc[t1]+cc[t2]);
tr1=hsqt2*(cc[t1]-cc[t2]);
ch[t4-1]=tr1+cc[t6-1];
ch[t4+t5-1]=cc[t6-1]-tr1;
ch[t4]=ti1-cc[t1+t0];
ch[t4+t5]=ti1+cc[t1+t0];
t1+=ido;
t2+=ido;
t4+=t3;
t6+=ido;
}
}
static void drftf1(int n,float *c,float *ch,float *wa,int *ifac){
int i,k1,l1,l2;
int na,kh,nf;
int ip,iw,ido,ix2,ix3;
nf=ifac[1];
na=1;
l2=n;
iw=n;
for(k1=0;k1<nf;k1++){
kh=nf-k1;
ip=ifac[kh+1];
l1=l2/ip;
ido=n/l2;
iw-=(ip-1)*ido;
na=1-na;
if(ip!=4)goto L102;
ix2=iw+ido;
ix3=ix2+ido;
if(na!=0)
dradf4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
else
dradf4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
goto L110;
L102:
if(ip!=2)goto L104;
if(na!=0)goto L103;
dradf2(ido,l1,c,ch,wa+iw-1);
goto L110;
L103:
dradf2(ido,l1,ch,c,wa+iw-1);
goto L110;
L104:
return; /* We're restricted to powers of two. just fail */
L110:
l2=l1;
}
if(na==1)return;
for(i=0;i<n;i++)c[i]=ch[i];
}
static void fdrfftf(int n,float *r,float *wsave,int *ifac){
if(n==1)return;
drftf1(n,r,wsave,wsave+n,ifac);
}
static void dradb2(int ido,int l1,float *cc,float *ch,float *wa1){
int i,k,t0,t1,t2,t3,t4,t5,t6;
float ti2,tr2;
t0=l1*ido;
t1=0;
t2=0;
t3=(ido<<1)-1;
for(k=0;k<l1;k++){
ch[t1]=cc[t2]+cc[t3+t2];
ch[t1+t0]=cc[t2]-cc[t3+t2];
t2=(t1+=ido)<<1;
}
if(ido<2)return;
if(ido==2)goto L105;
t1=0;
t2=0;
for(k=0;k<l1;k++){
t3=t1;
t5=(t4=t2)+(ido<<1);
t6=t0+t1;
for(i=2;i<ido;i+=2){
t3+=2;
t4+=2;
t5-=2;
t6+=2;
ch[t3-1]=cc[t4-1]+cc[t5-1];
tr2=cc[t4-1]-cc[t5-1];
ch[t3]=cc[t4]-cc[t5];
ti2=cc[t4]+cc[t5];
ch[t6-1]=wa1[i-2]*tr2-wa1[i-1]*ti2;
ch[t6]=wa1[i-2]*ti2+wa1[i-1]*tr2;
}
t2=(t1+=ido)<<1;
}
if(ido%2==1)return;
L105:
t1=ido-1;
t2=ido-1;
for(k=0;k<l1;k++){
ch[t1]=cc[t2]+cc[t2];
ch[t1+t0]=-(cc[t2+1]+cc[t2+1]);
t1+=ido;
t2+=ido<<1;
}
}
static void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
float *wa2,float *wa3){
static float sqrt2=1.4142135623730950488016887242097;
int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8;
float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4;
t0=l1*ido;
t1=0;
t2=ido<<2;
t3=0;
t6=ido<<1;
for(k=0;k<l1;k++){
t4=t3+t6;
t5=t1;
tr3=cc[t4-1]+cc[t4-1];
tr4=cc[t4]+cc[t4];
tr1=cc[t3]-cc[(t4+=t6)-1];
tr2=cc[t3]+cc[t4-1];
ch[t5]=tr2+tr3;
ch[t5+=t0]=tr1-tr4;
ch[t5+=t0]=tr2-tr3;
ch[t5+=t0]=tr1+tr4;
t1+=ido;
t3+=t2;
}
if(ido<2)return;
if(ido==2)goto L105;
t1=0;
for(k=0;k<l1;k++){
t5=(t4=(t3=(t2=t1<<2)+t6))+t6;
t7=t1;
for(i=2;i<ido;i+=2){
t2+=2;
t3+=2;
t4-=2;
t5-=2;
t7+=2;
ti1=cc[t2]+cc[t5];
ti2=cc[t2]-cc[t5];
ti3=cc[t3]-cc[t4];
tr4=cc[t3]+cc[t4];
tr1=cc[t2-1]-cc[t5-1];
tr2=cc[t2-1]+cc[t5-1];
ti4=cc[t3-1]-cc[t4-1];
tr3=cc[t3-1]+cc[t4-1];
ch[t7-1]=tr2+tr3;
cr3=tr2-tr3;
ch[t7]=ti2+ti3;
ci3=ti2-ti3;
cr2=tr1-tr4;
cr4=tr1+tr4;
ci2=ti1+ti4;
ci4=ti1-ti4;
ch[(t8=t7+t0)-1]=wa1[i-2]*cr2-wa1[i-1]*ci2;
ch[t8]=wa1[i-2]*ci2+wa1[i-1]*cr2;
ch[(t8+=t0)-1]=wa2[i-2]*cr3-wa2[i-1]*ci3;
ch[t8]=wa2[i-2]*ci3+wa2[i-1]*cr3;
ch[(t8+=t0)-1]=wa3[i-2]*cr4-wa3[i-1]*ci4;
ch[t8]=wa3[i-2]*ci4+wa3[i-1]*cr4;
}
t1+=ido;
}
if(ido%2 == 1)return;
L105:
t1=ido;
t2=ido<<2;
t3=ido-1;
t4=ido+(ido<<1);
for(k=0;k<l1;k++){
t5=t3;
ti1=cc[t1]+cc[t4];
ti2=cc[t4]-cc[t1];
tr1=cc[t1-1]-cc[t4-1];
tr2=cc[t1-1]+cc[t4-1];
ch[t5]=tr2+tr2;
ch[t5+=t0]=sqrt2*(tr1-ti1);
ch[t5+=t0]=ti2+ti2;
ch[t5+=t0]=-sqrt2*(tr1+ti1);
t3+=ido;
t1+=t2;
t4+=t2;
}
}
static void drftb1(int n, float *c, float *ch, float *wa, int *ifac){
int i,k1,l1,l2;
int na;
int nf,ip,iw,ix2,ix3,ido;
nf=ifac[1];
na=0;
l1=1;
iw=1;
for(k1=0;k1<nf;k1++){
ip=ifac[k1 + 2];
l2=ip*l1;
ido=n/l2;
if(ip!=4)goto L103;
ix2=iw+ido;
ix3=ix2+ido;
if(na!=0)
dradb4(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1);
else
dradb4(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1);
na=1-na;
goto L115;
L103:
if(ip!=2)goto L106;
if(na!=0)
dradb2(ido,l1,ch,c,wa+iw-1);
else
dradb2(ido,l1,c,ch,wa+iw-1);
na=1-na;
goto L115;
L106:
return; /* silently fail. we only do powers of two in this version */
L115:
l1=l2;
iw+=(ip-1)*ido;
}
if(na==0)return;
for(i=0;i<n;i++)c[i]=ch[i];
}
static void fdrfftb(int n, float *r, float *wsave, int *ifac){
if (n == 1)return;
drftb1(n, r, wsave, wsave+n, ifac);
}
void fft_forward(int n, float *buf,float *trigcache,int *splitcache){
int flag=0;
if(!trigcache || !splitcache){
trigcache=calloc(3*n,sizeof(float));
splitcache=calloc(32,sizeof(int));
fdrffti(n, trigcache, splitcache);
flag=1;
}
fdrfftf(n, buf, trigcache, splitcache);
if(flag){
free(trigcache);
free(splitcache);
}
}
void fft_backward(int n, float *buf, float *trigcache,int *splitcache){
int i;
int flag=0;
if(!trigcache || !splitcache){
trigcache=calloc(3*n,sizeof(float));
splitcache=calloc(32,sizeof(int));
fdrffti(n, trigcache, splitcache);
flag=1;
}
fdrfftb(n, buf, trigcache, splitcache);
for(i=0;i<n;i++)buf[i]/=n;
if(flag){
free(trigcache);
free(splitcache);
}
}
void fft_i(int n, float **trigcache, int **splitcache){
*trigcache=calloc(3*n,sizeof(float));
*splitcache=calloc(32,sizeof(int));
fdrffti(n, *trigcache, *splitcache);
}

View File

@@ -1,28 +0,0 @@
/*
$Id: smallft.h,v 1.2 2008/04/16 17:00:40 karl Exp $
Copyright (C) 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
* FFT implementation from OggSquish, minus cosine transforms.
* Only convenience functions exposed
******************************************************************/
extern void fft_forward(int n, float *buf, float *trigcache, int *sp);
extern void fft_backward(int n, float *buf, float *trigcache, int *sp);
extern void fft_i(int n, float **trigcache, int **splitcache);

View File

@@ -1,234 +0,0 @@
/*
$Id: test_interface.c,v 1.4 2008/06/13 19:26:23 flameeyes Exp $
Copyright (C) 2004, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
*
* Fake interface backend for testing paranoia layer
* NOTE: THIS CODE HAVE BEEN FOLDED INTO THE MAINLINE CODE SO IT IS
* NOT USED ANYMORE. (It's not clear that it had been used
* for a while in the non-libcdio cdparaonoia either.)
*
******************************************************************/
#ifdef CDDA_TEST
#include "low_interface.h"
#include "utils.h"
/* Build which test model? */
#define CDDA_TEST_OK
#undef CDDA_TEST_JITTER_SMALL
#undef CDDA_TEST_JITTER_LARGE
#undef CDDA_TEST_JITTER_MASSIVE
#undef CDDA_TEST_FRAG_SMALL
#undef CDDA_TEST_FRAG_LARGE
#undef CDDA_TEST_FRAG_MASSIVE
#undef CDDA_TEST_BOGUS_BYTES
#undef CDDA_TEST_DROPDUPE_BYTES
#undef CDDA_TEST_SCRATCH
#undef CDDA_TEST_UNDERRUN
#undef CDDA_TEST_ALLJITTER
#undef CDDA_TEST_SOMEJITTER
#undef CDDA_TEST_SEEKJITTER
static int test_readtoc (cdrom_drive *d){
int tracks=0;
long bytes;
long sectors;
/* only one track, as many sectors as the file */
bytes=lseek(d->cdda_fd,0,SEEK_END);
lseek(d->cdda_fd,0,SEEK_SET);
sectors=bytes/CDIO_CD_FRAMESIZE_RAW;
d->disc_toc[0].bFlags = 0;
d->disc_toc[0].bTrack = 1;
d->disc_toc[0].dwStartSector = 37;
d->disc_toc[1].bFlags = 0x4;
d->disc_toc[1].bTrack = CDROM_LEADOUT;
d->disc_toc[1].dwStartSector = sectors+37;
tracks=2;
d->cd_extra=0;
return(--tracks); /* without lead-out */
}
/* we emulate jitter, scratches, atomic jitter and bogus bytes on
boundaries, etc */
static long
test_read(cdrom_drive *d, void *p, long begin, long sectors)
{
#if defined(CDDA_TEST_SEEKJITTER) \
|| defined(CDDA_TEST_ALLJITTER) \
|| defined(CDDA_TEST_SOMEJITTER)
int jitter_flag;
#endif
int los_flag;
static int jitter=0;
int bytes_so_far=0;
long bytestotal;
static FILE *fd=NULL;
static long lastread=0;
if(!fd)fd=fdopen(d->cdda_fd,"r");
#ifdef CDDA_TEST_UNDERRUN
sectors-=1;
#endif
#ifdef CDDA_TEST_SEEKJITTER
if(lastread!=begin)jitter_flag=1;
#else
#ifdef CDDA_TEST_ALLJITTER
jitter_flag=1;
#else
#ifdef CDDA_TEST_SOMEJITTER
jitter_flag=(drand48()>.9?1:0);
los_flag=(drand48()>.9?1:0);
#else
los_flag=1;
#endif
#endif
#endif
lastread=begin+sectors;
bytestotal=sectors*CDIO_CD_FRAMESIZE_RAW;
begin*=CDIO_CD_FRAMESIZE_RAW;
while(bytes_so_far<bytestotal){
int inner_bytes=bytestotal-bytes_so_far;
char *inner_buf=(char *)p + bytes_so_far;
long seeki;
long rbytes;
long this_bytes=inner_bytes;
#ifdef CDDA_TEST_OK
#else
#ifdef CDDA_TEST_JITTER_SMALL
if(jitter_flag)jitter=4*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_JITTER_LARGE
if(jitter_flag)jitter=32*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_JITTER_MASSIVE
if(jitter_flag)jitter=128*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_FRAG_SMALL
if(los_flag)this_bytes=256*(int)(drand48()*CDIO_CD_FRAMESIZE_RAW/8);
if(jitter_flag)jitter=4*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_FRAG_LARGE
if(los_flag)this_bytes=16*(int)(drand48()*CDIO_CD_FRAMESIZE_RAW/8);
if(jitter_flag)jitter=4*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_FRAG_MASSIVE
if(los_flag)this_bytes=8*(int)(drand48()*CDIO_CD_FRAMESIZE_RAW/8);
if(jitter_flag)jitter=32*(int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
#else
#ifdef CDDA_TEST_DROPDUPE_BYTES
if(los_flag)this_bytes=CDIO_CD_FRAMESIZE_RAW;
if(jitter_flag)
if (drand48()>.8)
this_jitter=32;
else
this_jitter=0;
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
if(begin+jitter+bytes_so_far<0)jitter=0;
seeki=begin+bytes_so_far+jitter;
if(fseek(fd,seeki,SEEK_SET)<0){
return(0);
}
rbytes=fread(inner_buf,1,this_bytes,fd);
bytes_so_far+=rbytes;
if(rbytes==0)break;
#ifdef CDDA_TEST_SEEKJITTER
jitter_flag=0;
los_flag=0;
#else
#ifdef CDDA_TEST_ALLJITTER
jitter_flag=1;
los_flag=0;
#else
#ifdef CDDA_TEST_SOMEJITTER
jitter_flag=(drand48()>.9?1:0);
los_flag=(drand48()>.9?1:0);
#else
los_flag=1;
#endif
#endif
#endif
}
#ifdef CDDA_TEST_SCRATCH
{
long location=300*CDIO_CD_FRAMESIZE_RAW+(drand48()*56)+512;
if(begin<=location && begin+bytestotal>location){
memset(p+location-begin,(int)(drand48()*256),1100);
}
}
#endif
return(sectors);
}
/* set function pointers to use the ioctl routines */
int test_init_drive (cdrom_drive *d){
d->nsectors=13;
d->enable_cdda = dummy_exception;
d->read_audio = test_read;
d->read_toc = test_readtoc;
d->set_speed = dummy_exception;
d->tracks=d->read_toc(d);
if(d->tracks==-1)
return(d->tracks);
d->opened=1;
srand48(0);
return(0);
}
#endif

View File

@@ -1,211 +0,0 @@
/*
$Id: toc.c,v 1.7 2008/04/16 17:00:40 karl Exp $
Copyright (C) 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
derived from code (C) 1994-1996 Heiko Eissfeldt
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************
* Table of contents convenience functions
******************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include "low_interface.h"
#include "utils.h"
/*! Return the lsn for the start of track i_track */
lsn_t
cdda_track_firstsector(cdrom_drive_t *d, track_t i_track)
{
if(!d->opened){
cderror(d,"400: Device not open\n");
return(-1);
}
if (i_track == 0) {
if (d->disc_toc[0].dwStartSector == 0) {
/* first track starts at lsn 0 -> no pre-gap */
cderror(d,"401: Invalid track number\n");
return(-1);
}
else {
return 0; /* pre-gap of first track always starts at lba 0 */
}
}
if( i_track>d->tracks) {
cderror(d,"401: Invalid track number\n");
return(-1);
}
{
const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
return(d->disc_toc[i_track-i_first_track].dwStartSector);
}
}
/*! Get first lsn of the first audio track. -1 is returned on error. */
lsn_t
cdda_disc_firstsector(cdrom_drive_t *d)
{
int i;
if(!d->opened){
cderror(d,"400: Device not open\n");
return(-1);
}
/* look for an audio track */
for ( i=0; i<d->tracks; i++ )
if( cdda_track_audiop(d, i+1)==1 ) {
if (i == 0) /* disc starts at lba 0 if first track is an audio track */
return 0;
else
return cdda_track_firstsector(d, i+1);
}
cderror(d,"403: No audio tracks on disc\n");
return(-1);
}
/*! Get last lsn of the track. The lsn is generally one less than the
start of the next track. -1 is returned on error. */
lsn_t
cdda_track_lastsector(cdrom_drive_t *d, track_t i_track)
{
if (!d->opened) {
cderror(d,"400: Device not open\n");
return -1;
}
if (i_track == 0) {
if (d->disc_toc[0].dwStartSector == 0) {
/* first track starts at lba 0 -> no pre-gap */
cderror(d,"401: Invalid track number\n");
return(-1);
}
else {
return d->disc_toc[0].dwStartSector-1;
}
}
if ( i_track<1 || i_track>d->tracks ) {
cderror(d,"401: Invalid track number\n");
return -1;
}
/* CD Extra have their first session ending at the last audio track */
if (d->cd_extra > 0 && i_track+1 <= d->tracks) {
if (d->audio_last_sector >= d->disc_toc[i_track-1].dwStartSector &&
d->audio_last_sector < d->disc_toc[i_track].dwStartSector) {
return d->audio_last_sector;
}
}
/* Safe, we've always the leadout at disc_toc[tracks] */
return(d->disc_toc[i_track].dwStartSector-1);
}
/*! Get last lsn of the last audio track. The last lssn generally one
less than the start of the next track after the audio track. -1 is
returned on error. */
lsn_t
cdda_disc_lastsector(cdrom_drive_t *d)
{
if (!d->opened) {
cderror(d,"400: Device not open\n");
return -1;
} else {
/* look for an audio track */
const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
track_t i = cdio_get_last_track_num(d->p_cdio);
for ( ; i >= i_first_track; i-- )
if ( cdda_track_audiop(d,i) )
return (cdda_track_lastsector(d,i));
}
cderror(d,"403: No audio tracks on disc\n");
return -1;
}
/*! Return the number of tracks on the CD. */
track_t
cdda_tracks(cdrom_drive_t *d)
{
if (!d->opened){
cderror(d,"400: Device not open\n");
return -1;
}
return(d->tracks);
}
/*! Return the track containing the given LSN. If the LSN is before
the first track (in the pregap), 0 is returned. If there was an
error or the LSN after the LEADOUT (beyond the end of the CD), then
CDIO_INVALID_TRACK is returned.
*/
int
cdda_sector_gettrack(cdrom_drive_t *d, lsn_t lsn)
{
if (!d->opened) {
cderror(d,"400: Device not open\n");
return -1;
} else {
if (lsn < d->disc_toc[0].dwStartSector)
return 0; /* We're in the pre-gap of first track */
return cdio_get_track(d->p_cdio, lsn);
}
}
/*! Return the number of channels in track: 2 or 4; -2 if not
implemented or -1 for error.
Not meaningful if track is not an audio track.
*/
int
cdda_track_channels(cdrom_drive_t *d, track_t i_track)
{
return(cdio_get_track_channels(d->p_cdio, i_track));
}
/*! Return 1 is track is an audio track, 0 otherwise. */
int
cdda_track_audiop(cdrom_drive_t *d, track_t i_track)
{
track_format_t track_format = cdio_get_track_format(d->p_cdio, i_track);
return TRACK_FORMAT_AUDIO == track_format ? 1 : 0;
}
/*! Return 1 is track is an audio track, 0 otherwise. */
int
cdda_track_copyp(cdrom_drive_t *d, track_t i_track)
{
track_flag_t track_flag = cdio_get_track_copy_permit(d->p_cdio, i_track);
return CDIO_TRACK_FLAG_TRUE == track_flag ? 1 : 0;
}
/*! Return 1 is audio track has linear preemphasis set, 0 otherwise.
Only makes sense for audio tracks.
*/
int
cdda_track_preemp(cdrom_drive_t *d, track_t i_track)
{
track_flag_t track_flag = cdio_get_track_preemphasis(d->p_cdio, i_track);
return CDIO_TRACK_FLAG_TRUE == track_flag ? 1 : 0;
}

View File

@@ -1,162 +0,0 @@
/*
Copyright (C) 2004, 2008, 2010, 2011 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include "common_interface.h"
#include "utils.h"
void
cderror(cdrom_drive_t *d,const char *s)
{
ssize_t bytes_ret;
if(s && d){
switch(d->errordest){
case CDDA_MESSAGE_PRINTIT:
bytes_ret = write(STDERR_FILENO, s, strlen(s));
if (strlen(s) != bytes_ret)
break;
case CDDA_MESSAGE_LOGIT:
d->errorbuf=catstring(d->errorbuf,s);
break;
case CDDA_MESSAGE_FORGETIT:
default: ;
}
}
}
void
cdmessage(cdrom_drive_t *d, const char *s)
{
ssize_t bytes_ret;
if(s && d){
switch(d->messagedest){
case CDDA_MESSAGE_PRINTIT:
bytes_ret = write(STDERR_FILENO, s, strlen(s));
break;
case CDDA_MESSAGE_LOGIT:
d->messagebuf=catstring(d->messagebuf,s);
break;
case CDDA_MESSAGE_FORGETIT:
default: ;
}
}
}
void
idperror(int messagedest,char **messages,const char *f,
const char *s)
{
char *buffer;
int malloced=0;
if(!f)
buffer=(char *)s;
else
if(!s)
buffer=(char *)f;
else{
buffer=malloc(strlen(f)+strlen(s)+9);
sprintf(buffer,f,s);
malloced=1;
}
if(buffer){
ssize_t bytes_ret;
switch(messagedest){
case CDDA_MESSAGE_PRINTIT:
bytes_ret = write(STDERR_FILENO,buffer,strlen(buffer));
if(errno){
bytes_ret = write(STDERR_FILENO,": ",2);
bytes_ret = write(STDERR_FILENO,strerror(errno),strlen(strerror(errno)));
bytes_ret = write(STDERR_FILENO,"\n",1);
}
break;
case CDDA_MESSAGE_LOGIT:
if(messages){
*messages=catstring(*messages,buffer);
if(errno){
*messages=catstring(*messages,": ");
*messages=catstring(*messages,strerror(errno));
*messages=catstring(*messages,"\n");
}
}
break;
case CDDA_MESSAGE_FORGETIT:
default: ;
}
}
if(malloced)free(buffer);
}
void
idmessage(int messagedest,char **messages,const char *f,
const char *s)
{
char *buffer;
int malloced=0;
if(!f)
buffer=(char *)s;
else
if(!s)
buffer=(char *)f;
else{
const unsigned int i_buffer=strlen(f)+strlen(s)+10;
buffer=malloc(i_buffer);
sprintf(buffer,f,s);
strncat(buffer,"\n", i_buffer);
malloced=1;
}
if(buffer) {
ssize_t bytes_ret;
switch(messagedest){
case CDDA_MESSAGE_PRINTIT:
bytes_ret = write(STDERR_FILENO,buffer,strlen(buffer));
if(!malloced)
bytes_ret = write(STDERR_FILENO,"\n",1);
break;
case CDDA_MESSAGE_LOGIT:
if(messages){
*messages=catstring(*messages,buffer);
if(!malloced)*messages=catstring(*messages,"\n");
}
break;
case CDDA_MESSAGE_FORGETIT:
default: ;
}
}
if(malloced)free(buffer);
}
char *
catstring(char *buff, const char *s) {
if (s) {
const unsigned int add_len = strlen(s) + 9;
if(buff) {
buff = realloc(buff, strlen(buff) + add_len);
} else {
buff=calloc(add_len, 1);
}
strncat(buff, s, add_len);
}
return(buff);
}

View File

@@ -1,79 +0,0 @@
/*
$Id: utils.h,v 1.8 2008/04/16 17:00:41 karl Exp $
Copyright (C) 2004, 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <cdio/bytesex.h>
#include <stdio.h>
/* I wonder how many alignment issues this is gonna trip in the
future... it shouldn't trip any... I guess we'll find out :) */
static inline int
bigendianp(void)
{
int test=1;
char *hack=(char *)(&test);
if(hack[0])return(0);
return(1);
}
extern char *catstring(char *buff, const char *s);
/*#if BYTE_ORDER == LITTLE_ENDIAN*/
#ifndef WORDS_BIGENDIAN
static inline int16_t be16_to_cpu(int16_t x){
return(UINT16_SWAP_LE_BE_C(x));
}
static inline int16_t le16_to_cpu(int16_t x){
return(x);
}
#else
static inline int16_t be16_to_cpu(int16_t x){
return(x);
}
static inline int16_t le16_to_cpu(int16_t x){
return(UINT16_SWAP_LE_BE_C(x));
}
#endif
static inline int16_t cpu_to_be16(int16_t x){
return(be16_to_cpu(x));
}
static inline int16_t cpu_to_le16(int16_t x){
return(le16_to_cpu(x));
}
void cderror(cdrom_drive_t *d, const char *s);
void cdmessage(cdrom_drive_t *d,const char *s);
void idperror(int messagedest, char **messages, const char *f, const char *s);
void idmessage(int messagedest, char **messages, const char *f, const char *s);

View File

@@ -4,5 +4,6 @@
/.libs
/Makefile
/Makefile.in
/*~
/libiso9660.la
/libiso9660.la.ver

View File

@@ -1,8 +0,0 @@
.deps
.libs
Makefile
Makefile.in
*.o
*.lo
*.la
*.la.ver

View File

@@ -1,8 +0,0 @@
/*.lo
/*.o
/.deps
/.libs
/Makefile
/Makefile.in
/libcdio_paranoia.la
/libcdio_paranoia.la.ver

View File

@@ -1,152 +0,0 @@
# Copyright (C) 2004, 2006, 2008, 2011 Rocky Bernstein <rocky@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 3 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, see <http://www.gnu.org/licenses/>.
########################################################
# Things to make the libcdio_paranoia library
########################################################
#
# From libtool documentation amended with guidance from N. Boullis:
#
# 1. Start with version information of `0:0:0' for each libtool library.
#
# 2. It is probably not a good idea to update the version information
# several times between public releases, but rather once per public
# release. (This seems to be more an aesthetic consideration than
# a hard technical one.)
#
# 3. If the library source code has changed at all since the last
# update, then increment REVISION (`C:R:A' becomes `C:R+1:A').
#
# 4. If any interfaces have been added, removed, or changed since the
# last update, increment CURRENT, and set REVISION to 0.
#
# 5. If any interfaces have been added since the last public release,
# then increment AGE.
#
# 6. If any interfaces have been removed or changed since the last
# public release, then set AGE to 0. A changed interface means an
# incompatibility with previous versions.
EXTRA_DIST = libcdio_paranoia.sym
libcdio_paranoia_la_CURRENT = 1
libcdio_paranoia_la_REVISION = 0
libcdio_paranoia_la_AGE = 0
noinst_HEADERS = gap.h isort.h overlap.h p_block.h
libcdio_paranoia_sources = gap.c isort.c overlap.c overlap.h \
p_block.c paranoia.c
lib_LTLIBRARIES = libcdio_paranoia.la
libcdio_paranoia_la_SOURCES = $(libcdio_paranoia_sources)
libcdio_paranoia_la_ldflags = -version-info $(libcdio_paranoia_la_CURRENT):$(libcdio_paranoia_la_REVISION):$(libcdio_paranoia_la_AGE) @LT_NO_UNDEFINED@
INCLUDES = $(LIBCDIO_CFLAGS)
FLAGS=@LIBCDIO_CFLAGS@ @TYPESIZES@ @CFLAGS@ -I.. -I../..
OPT=$(FLAGS)
DEBUG=$(FLAGS)
## SUFFIXES = .t
## TFILES = isort.t gap.t p_block.t paranoia.t
##test: $(TFILES)
##.c.t:
## $(CC) -g -DTEST $(DEBUG) -o $@ $< $(LIBS)
## $@
##debug:
## $(MAKE) libcdio_paranoia.a CFLAGS="$(DEBUG)"
LIBS = $(LIBCDIO_LIBS) $(LIBCDIO_CDDA_LIBS)
########################################################
# Things to version the symbols in the libraries
########################################################
# An explanation of the versioning problem from Nicolas Boullis and
# the versioned symbol solution he uses below...
#
# Currently, libvcdinfo uses the cdio_open function from libcdio.
# Let's imagine a program foobar that uses both the vcdinfo_open
# function from libvcdinfo and the cdio_open function from libcdio.
# Currently, libcdio has SONAME libcdio.so.0, libvcdinfo has SONAME
# libvcdinfo.so.0 and requires libcdio.so.0, and foobar requires both
# libvcdinfo.so.0 and libcdio.so.0. Everything looks fine.
#
# Now, for some reason, you decide to change the cdio_open function.
# That's your right, but you have to bump the CURRENT version and (if I
# understand it correctly, athough this is not that clear in libtool's
# documentation) set the AGE to 0. Anyway, this bumps the SONAME, which is
# sane since the interface changes incompatibly.
# Now, you have a new libcdio with SONAME libcdio.so.1. But libvcdinfo and
# foobar still require libcdio.so.0. Everything is still fine.
# Now, after some minor changes, the author of foobar recompiles foobar.
# Then, foobar now requires libvcdinfo.so.0 and libcdio.so.1. And foobar
# now segfaults...
# What is happening? When you run foobar, if brings both libvcdinfo.so.0
# and libcdio.so.1, but libvcdinfo.so.0 also brings libcdio.so.0. So you
# have both libcdio.so.0 and libcdio.so.1 that bring their symbols to the
# global namespace. Hence, you have to incompatible versions of the
# cdio_open function in the name space. When foobar calls cdio_open, it
# may choose the wrong function, and segfaults...
# With versioned symbols, the cdio_open function from libcdio.so.0 may be
# known as (something that looks like) cdio_open@@CDIO_0. An the cdio_open
# function from libcdio.so.1 as cdio_open@@CDIO_1. Both versions of
# libcdio would still be brought in by the most recent foobar, but foobar
# (and libvcdinfo) know which versioned function to use and then use the
# good one.
# This is some simple versioning where every symbol is versioned with
# something that looks like the SONAME of the library. More complex (and
# better) versioning is possible; it is for example what is used by glibc.
# But good complex versioning is something that requires much more
# work...
# The below is a impliments symbol versioning. First of all, I
# compute MAJOR as CURENT - AGE; that is what is used within libtool
# (at least on GNU/Linux systems) for the number in the SONAME. The
# nm command gives the list of symbols known in each of the object
# files that will be part of the shared library. And the sed command
# extracts from this list those symbols that will be shared. (This sed
# command comes from libtool.)
libcdio_paranoia_la_MAJOR = $(shell expr $(libcdio_paranoia_la_CURRENT) - $(libcdio_paranoia_la_AGE))
if BUILD_VERSIONED_LIBS
libcdio_paranoia_la_LDFLAGS = $(libcdio_paranoia_la_ldflags) -Wl,--version-script=libcdio_paranoia.la.ver
libcdio_paranoia_la_DEPENDENCIES = libcdio_paranoia.la.ver
libcdio_paranoia.la.ver: $(libcdio_paranoia_la_OBJECTS) $(srcdir)/libcdio_paranoia.sym
echo 'CDIO_PARANOIA_$(libcdio_paranoia_la_MAJOR) { ' > $@
objs=`for obj in $(libcdio_paranoia_la_OBJECTS); do sed -ne "s/^pic_object='\(.*\)'$$/\1/p" $$obj; done`; \
if test -n "$$objs" ; then \
nm $${objs} | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/\1/p' | sort -u | { first=true; while read symbol; do if grep -q "^$${symbol}\$$" $(srcdir)/libcdio_paranoia.sym; then if test $$first = true; then echo " global:"; first=false; fi; echo " $${symbol};"; fi; done; } >> $@; \
nm $${objs} | sed -n -e 's/^.*[ ][ABCDGIRSTW][ABCDGIRSTW]*[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$$/\1/p' | sort -u | { first=true; while read symbol; do if grep -q "^$${symbol}\$$" $(srcdir)/libcdio_paranoia.sym; then :; else if test $$first = true; then echo " local:"; first=false; fi; echo " $${symbol};"; fi; done; } >> $@; \
fi
echo '};' >> $@
else
libcdio_paranoia_la_LDFLAGS = $(libcdio_paranoia_la_ldflags)
endif
MOSTLYCLEANFILES = libcdio_paranoia.la.ver

View File

@@ -1,551 +0,0 @@
/*
Copyright (C) 2004, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***
* Gap analysis support code for paranoia
*
***/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#include "p_block.h"
#include <cdio/paranoia.h>
#include "gap.h"
#include <string.h>
/**** Gap analysis code ***************************************************/
/* ===========================================================================
* i_paranoia_overlap_r (internal)
*
* This function seeks backward through two vectors (starting at the given
* offsets) to determine how many consecutive samples agree. It returns
* the number of matching samples, which may be 0.
*
* Unlike its sibling, i_paranoia_overlap_f, this function doesn't need to
* be given the size of the vectors (all vectors stop at offset 0).
*
* This function is used by i_analyze_rift_r() below to find where a
* leading rift ends.
*/
long int
i_paranoia_overlap_r(int16_t *buffA,int16_t *buffB,
long offsetA, long offsetB)
{
long beginA=offsetA;
long beginB=offsetB;
/* Start at the given offsets and work our way backwards until we hit
* the beginning of one of the vectors.
*/
for( ; beginA>=0 && beginB>=0; beginA--,beginB-- )
if (buffA[beginA] != buffB[beginB]) break;
/* These values will either point to the first mismatching sample, or
* -1 if we hit the beginning of a vector. So increment to point to the
* last matching sample.
*
* ??? Why? This would appear to return one less sample than actually
* matched. E.g., no matching samples returns -1! Is this a bug?
*/
beginA++;
beginB++;
return(offsetA-beginA);
}
/* ===========================================================================
* i_paranoia_overlap_f (internal)
*
* This function seeks forward through two vectors (starting at the given
* offsets) to determine how many consecutive samples agree. It returns
* the number of matching samples, which may be 0.
*
* Unlike its sibling, i_paranoia_overlap_r, this function needs to given
* the size of the vectors.
*
* This function is used by i_analyze_rift_f() below to find where a
* trailing rift ends.
*/
long int
i_paranoia_overlap_f(int16_t *buffA,int16_t *buffB,
long offsetA, long offsetB,
long sizeA,long sizeB)
{
long endA=offsetA;
long endB=offsetB;
/* Start at the given offsets and work our way forward until we hit
* the end of one of the vectors.
*/
for(;endA<sizeA && endB<sizeB;endA++,endB++)
if(buffA[endA]!=buffB[endB])break;
/* ??? Note that we don't do any post-loop tweaking of endA. Why the
* asymmetry with i_paranoia_overlap_r?
*/
return(endA-offsetA);
}
/* ===========================================================================
* i_stutter_or_gap (internal)
*
* This function compares (gap) samples of two vectors at the given offsets.
* It returns 0 if all the samples are identical, or nonzero if they differ.
*
* This is used by i_analyze_rift_[rf] below to determine whether a rift
* contains samples dropped by the other vector (that should be inserted),
* or whether the rift contains a stutter (that should be dropped). See
* i_analyze_rift_[rf] for more details.
*/
int
i_stutter_or_gap(int16_t *A, int16_t *B,long offA, long offB, long int gap)
{
long a1=offA;
long b1=offB;
/* If the rift was so big that there aren't enough samples in the other
* vector to compare against the full gap, then just compare what we
* have available. E.g.:
*
* (5678)|(newly matching run ...)
* (... 12345678)| (345678) |(newly matching run ...)
*
* In this case, a1 would be -2, since we'd want to compare 6 samples
* against a vector that had only 4. So we start 2 samples later, and
* compare the 4 available samples.
*
* Again, this approach to identifying stutters is simply a heuristic,
* so this may not produce correct results in all cases.
*/
if(a1<0){
/* Note that a1 is negative, so we're increasing b1 and decreasing (gap).
*/
b1-=a1;
gap+=a1;
a1=0;
}
/* Note that we don't have an equivalent adjustment for leading rifts.
* Thus, it's possible for the following memcmp() to run off the end
* of A. See the bug note in i_analyze_rift_r().
*/
/* Multiply gap by 2 because samples are 2 bytes long and memcmp compares
* at the byte level.
*/
return(memcmp(A+a1,B+b1,gap*2));
}
/* riftv is the first value into the rift -> or <- */
/* ===========================================================================
* i_analyze_rift_f (internal)
*
* This function examines a trailing rift to see how far forward the rift goes
* and to determine what kind of rift it is. This function is called by
* i_stage2_each() when a trailing rift is detected. (aoffset,boffset) are
* the offsets into (A,B) of the first mismatching sample.
*
* This function returns:
* matchA > 0 if there are (matchA) samples missing from A
* matchA < 0 if there are (-matchA) duplicate samples (stuttering) in A
* matchB > 0 if there are (matchB) samples missing from B
* matchB < 0 if there are (-matchB) duplicate samples in B
* matchC != 0 if there are (matchC) samples of garbage, after which
* both A and B are in sync again
*/
void
i_analyze_rift_f(int16_t *A,int16_t *B,
long sizeA, long sizeB,
long aoffset, long boffset,
long *matchA,long *matchB,long *matchC)
{
long apast=sizeA-aoffset;
long bpast=sizeB-boffset;
long i;
*matchA=0, *matchB=0, *matchC=0;
/* Look forward to see where we regain agreement between vectors
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of
* the following possible matches:
*
* edge
* v
* (1) (... A matching run)|(aoffset matches ...)
* (... B matching run)| (rift) |(boffset+i matches ...)
*
* (2) (... A matching run)| (rift) |(aoffset+i matches ...)
* (... B matching run)|(boffset matches ...)
*
* (3) (... A matching run)| (rift) |(aoffset+i matches ...)
* (... B matching run)| (rift) |(boffset+i matches ...)
*
* Anything that doesn't match one of these three is too corrupt to
* for us to recover from. E.g.:
*
* (... A matching run)| (rift) |(eventual match ...)
* (... B matching run)| (big rift) |(eventual match ...)
*
* We won't find the eventual match, since we wouldn't be sure how
* to fix the rift.
*/
for(i=0;;i++){
/* Search for whatever case we hit first, so as to end up with the
* smallest rift.
*
* ??? Why do we start at 0? It should never match.
*/
/* Don't search for (1) past the end of B */
if (i<bpast)
/* See if we match case (1) above, which either means that A dropped
* samples at the rift, or that B stuttered.
*/
if(i_paranoia_overlap_f(A,B,aoffset,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){
*matchA=i;
break;
}
/* Don't search for (2) or (3) past the end of A */
if (i<apast) {
/* See if we match case (2) above, which either means that B dropped
* samples at the rift, or that A stuttered.
*/
if(i_paranoia_overlap_f(A,B,aoffset+i,boffset,sizeA,sizeB)>=MIN_WORDS_RIFT){
*matchB=i;
break;
}
/* Don't search for (3) past the end of B */
if (i<bpast)
/* See if we match case (3) above, which means that a fixed-length
* rift of samples is getting read unreliably.
*/
if(i_paranoia_overlap_f(A,B,aoffset+i,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){
*matchC=i;
break;
}
}else
/* Stop searching when we've reached the end of both vectors.
* In theory we could stop when there aren't MIN_WORDS_RIFT samples
* left in both vectors, but this case should happen fairly rarely.
*/
if(i>=bpast)break;
/* Try the search again with a larger tentative rift. */
}
if(*matchA==0 && *matchB==0 && *matchC==0)return;
if(*matchC)return;
/* For case (1) or (2), we need to determine whether the rift contains
* samples dropped by the other vector (that should be inserted), or
* whether the rift contains a stutter (that should be dropped). To
* distinguish, we check the contents of the rift against the good samples
* just before the rift. If the contents match, then the rift contains
* a stutter.
*
* A stutter in the second vector:
* (...good samples... 1234)|(567 ...newly matched run...)
* (...good samples... 1234)| (1234) | (567 ...newly matched run)
*
* Samples missing from the first vector:
* (...good samples... 1234)|(901 ...newly matched run...)
* (...good samples... 1234)| (5678) |(901 ...newly matched run...)
*
* Of course, there's no theoretical guarantee that a non-stutter
* truly represents missing samples, but given that we're dealing with
* verified fragments in stage 2, we can have some confidence that this
* is the case.
*/
if(*matchA){
/* For case (1), we need to determine whether A dropped samples at the
* rift or whether B stuttered.
*
* If the rift doesn't match the good samples in A (and hence in B),
* it's not a stutter, and the rift should be inserted into A.
*/
if(i_stutter_or_gap(A,B,aoffset-*matchA,boffset,*matchA))
return;
/* It is a stutter, so we need to signal that we need to remove
* (matchA) bytes from B.
*/
*matchB = -*matchA;
*matchA=0;
return;
}else{
/* Case (2) is the inverse of case (1) above. */
if(i_stutter_or_gap(B,A,boffset-*matchB,aoffset,*matchB))
return;
*matchA = -*matchB;
*matchB=0;
return;
}
}
/* riftv must be first even val of rift moving back */
/* ===========================================================================
* i_analyze_rift_r (internal)
*
* This function examines a leading rift to see how far back the rift goes
* and to determine what kind of rift it is. This function is called by
* i_stage2_each() when a leading rift is detected. (aoffset,boffset) are
* the offsets into (A,B) of the first mismatching sample.
*
* This function returns:
* matchA > 0 if there are (matchA) samples missing from A
* matchA < 0 if there are (-matchA) duplicate samples (stuttering) in A
* matchB > 0 if there are (matchB) samples missing from B
* matchB < 0 if there are (-matchB) duplicate samples in B
* matchC != 0 if there are (matchC) samples of garbage, after which
* both A and B are in sync again
*/
void
i_analyze_rift_r(int16_t *A,int16_t *B,
long sizeA, long sizeB,
long aoffset, long boffset,
long *matchA,long *matchB,long *matchC)
{
long apast=aoffset+1;
long bpast=boffset+1;
long i;
*matchA=0, *matchB=0, *matchC=0;
/* Look backward to see where we regain agreement between vectors
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of
* the following possible matches:
*
* edge
* v
* (1) (... aoffset matches)|(A matching run ...)
* (... boffset-i matches)| (rift) |(B matching run ...)
*
* (2) (... aoffset-i matches)| (rift) |(A matching run ...)
* (... boffset matches)|(B matching run ...)
*
* (3) (... aoffset-i matches)| (rift) |(A matching run ...)
* (... boffset-i matches)| (rift) |(B matching run ...)
*
* Anything that doesn't match one of these three is too corrupt to
* for us to recover from. E.g.:
*
* (... eventual match)| (rift) |(A matching run ...)
* (... eventual match) | (big rift) |(B matching run ...)
*
* We won't find the eventual match, since we wouldn't be sure how
* to fix the rift.
*/
for(i=0;;i++){
/* Search for whatever case we hit first, so as to end up with the
* smallest rift.
*
* ??? Why do we start at 0? It should never match.
*/
/* Don't search for (1) past the beginning of B */
if (i<bpast)
/* See if we match case (1) above, which either means that A dropped
* samples at the rift, or that B stuttered.
*/
if(i_paranoia_overlap_r(A,B,aoffset,boffset-i)>=MIN_WORDS_RIFT){
*matchA=i;
break;
}
/* Don't search for (2) or (3) past the beginning of A */
if (i<apast) {
/* See if we match case (2) above, which either means that B dropped
* samples at the rift, or that A stuttered.
*/
if(i_paranoia_overlap_r(A,B,aoffset-i,boffset)>=MIN_WORDS_RIFT){
*matchB=i;
break;
}
/* Don't search for (3) past the beginning of B */
if (i<bpast)
/* See if we match case (3) above, which means that a fixed-length
* rift of samples is getting read unreliably.
*/
if(i_paranoia_overlap_r(A,B,aoffset-i,boffset-i)>=MIN_WORDS_RIFT){
*matchC=i;
break;
}
}else
/* Stop searching when we've reached the end of both vectors.
* In theory we could stop when there aren't MIN_WORDS_RIFT samples
* left in both vectors, but this case should happen fairly rarely.
*/
if(i>=bpast)break;
/* Try the search again with a larger tentative rift. */
}
if(*matchA==0 && *matchB==0 && *matchC==0)return;
if(*matchC)return;
/* For case (1) or (2), we need to determine whether the rift contains
* samples dropped by the other vector (that should be inserted), or
* whether the rift contains a stutter (that should be dropped). To
* distinguish, we check the contents of the rift against the good samples
* just after the rift. If the contents match, then the rift contains
* a stutter.
*
* A stutter in the second vector:
* (...newly matched run... 234)|(5678 ...good samples...)
* (...newly matched run... 234)| (5678) |(5678 ...good samples...)
*
* Samples missing from the first vector:
* (...newly matched run... 890)|(5678 ...good samples...)
* (...newly matched run... 890)| (1234) |(5678 ...good samples...)
*
* Of course, there's no theoretical guarantee that a non-stutter
* truly represents missing samples, but given that we're dealing with
* verified fragments in stage 2, we can have some confidence that this
* is the case.
*/
if(*matchA){
/* For case (1), we need to determine whether A dropped samples at the
* rift or whether B stuttered.
*
* If the rift doesn't match the good samples in A (and hence in B),
* it's not a stutter, and the rift should be inserted into A.
*
* ???BUG??? It's possible for aoffset+1+*matchA to be > sizeA, in
* which case the comparison in i_stutter_or_gap() will extend beyond
* the bounds of A. Thankfully, this isn't writing data and thus
* trampling memory, but it's still a memory access error that should
* be fixed.
*
* This bug is not fixed yet.
*/
if(i_stutter_or_gap(A,B,aoffset+1,boffset-*matchA+1,*matchA))
return;
/* It is a stutter, so we need to signal that we need to remove
* (matchA) bytes from B.
*/
*matchB = -*matchA;
*matchA=0;
return;
}else{
/* Case (2) is the inverse of case (1) above. */
if(i_stutter_or_gap(B,A,boffset+1,aoffset-*matchB+1,*matchB))
return;
*matchA = -*matchB;
*matchB=0;
return;
}
}
/* ===========================================================================
* analyze_rift_silence_f (internal)
*
* This function examines the fragment and root from the rift onward to
* see if they have a rift's worth of silence (or if they end with silence).
* It sets (*matchA) to -1 if A's rift is silence, (*matchB) to -1 if B's
* rift is silence, and sets them to 0 otherwise.
*
* Note that, unlike every other function in cdparanoia, this function
* considers any repeated value to be silence (which, in effect, it is).
* All other functions only consider repeated zeroes to be silence.
*
* ??? Is this function name just a misnomer, as it's really looking for
* repeated garbage?
*
* This function is called by i_stage2_each() if it runs into a trailing rift
* that i_analyze_rift_f couldn't diagnose. This checks for another variant:
* where one vector has silence and the other doesn't. We then assume
* that the silence (and anything following it) is garbage.
*
* Note that while this function checks both A and B for silence, the caller
* assumes that only one or the other has silence.
*/
void
analyze_rift_silence_f(int16_t *A,int16_t *B,long sizeA,long sizeB,
long aoffset, long boffset,
long *matchA, long *matchB)
{
*matchA=-1;
*matchB=-1;
/* Search for MIN_WORDS_RIFT samples, or to the end of the vector,
* whichever comes first.
*/
sizeA=min(sizeA,aoffset+MIN_WORDS_RIFT);
sizeB=min(sizeB,boffset+MIN_WORDS_RIFT);
aoffset++;
boffset++;
/* Check whether A has only "silence" within the search range. Note
* that "silence" here is a single, repeated value (zero or not).
*/
while(aoffset<sizeA){
if(A[aoffset]!=A[aoffset-1]){
*matchA=0;
break;
}
aoffset++;
}
/* Check whether B has only "silence" within the search range. Note
* that "silence" here is a single, repeated value (zero or not).
*
* Also note that while the caller assumes that only matchA or matchB
* is set, we check both vectors here.
*/
while(boffset<sizeB){
if(B[boffset]!=B[boffset-1]){
*matchB=0;
break;
}
boffset++;
}
}

View File

@@ -1,43 +0,0 @@
/*
$Id: gap.h,v 1.2 2008/04/17 17:39:48 karl Exp $
Copyright (C) 2004, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GAP_H_
#define _GAP_H_
extern long i_paranoia_overlap_r(int16_t *buffA,int16_t *buffB,
long offsetA, long offsetB);
extern long i_paranoia_overlap_f(int16_t *buffA,int16_t *buffB,
long offsetA, long offsetB,
long sizeA,long sizeB);
extern int i_stutter_or_gap(int16_t *A, int16_t *B,long offA, long offB,
long gap);
extern void i_analyze_rift_f(int16_t *A,int16_t *B,
long sizeA, long sizeB,
long aoffset, long boffset,
long *matchA,long *matchB,long *matchC);
extern void i_analyze_rift_r(int16_t *A,int16_t *B,
long sizeA, long sizeB,
long aoffset, long boffset,
long *matchA,long *matchB,long *matchC);
extern void analyze_rift_silence_f(int16_t *A,int16_t *B,long sizeA,long sizeB,
long aoffset, long boffset,
long *matchA, long *matchB);
#endif /*_GAP_H*/

View File

@@ -1,301 +0,0 @@
/*
Copyright (C) 2004, 2005, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* sorted vector abstraction for paranoia */
/* Old isort got a bit complex. This re-constrains complexity to
give a go at speed through a more alpha-6-like mechanism. */
/* "Sort" is a bit of a misnomer in this implementation. It's actually
* basically a hash table of sample values (with a linked-list collision
* resolution), which lets you quickly determine where in a vector a
* particular sample value occurs.
*
* Collisions aren't due to hash collisions, as the table has one bucket
* for each possible sample value. Instead, the "collisions" represent
* multiple occurrences of a given value.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "p_block.h"
#include "isort.h"
/* ===========================================================================
* sort_alloc()
*
* Allocates and initializes a new, empty sort_info object, which can be
* used to index up to (size) samples from a vector.
*/
sort_info_t *
sort_alloc(long size)
{
sort_info_t *ret=calloc(1, sizeof(sort_info_t));
ret->vector=NULL;
ret->sortbegin=-1;
ret->size=-1;
ret->maxsize=size;
ret->head=calloc(65536,sizeof(sort_link_t *));
ret->bucketusage=calloc(1, 65536*sizeof(long));
ret->revindex=calloc(size,sizeof(sort_link_t));
ret->lastbucket=0;
return(ret);
}
/* ===========================================================================
* sort_unsortall() (internal)
*
* This function resets the index for further use with a different vector
* or range, without the overhead of an unnecessary free/alloc.
*/
void
sort_unsortall(sort_info_t *i)
{
/* If there were few enough different samples encountered (and hence few
* enough buckets used), we can just zero out those buckets. If there
* were many (2000 is picked somewhat arbitrarily), it's faster simply to
* zero out all buckets with a memset() rather than walking the data
* structure and zeroing them out one by one.
*/
if (i->lastbucket>2000) { /* a guess */
memset(i->head,0,65536*sizeof(sort_link_t *));
} else {
long b;
for (b=0; b<i->lastbucket; b++)
i->head[i->bucketusage[b]]=NULL;
}
i->lastbucket=0;
i->sortbegin=-1;
/* Curiously, this function preserves the vector association created
* by sort_setup(), but it is used only internally by sort_setup, so
* preserving this association is unnecessary.
*/
}
/* ===========================================================================
* sort_free()
*
* Releases all memory consumed by a sort_info object.
*/
void
sort_free(sort_info_t *i)
{
free(i->revindex);
free(i->head);
free(i->bucketusage);
free(i);
}
/* ===========================================================================
* sort_sort() (internal)
*
* This function builds the index to allow for fast searching for sample
* values within a portion (sortlo - sorthi) of the object's associated
* vector. It is called internally and only when needed.
*/
static void
sort_sort(sort_info_t *i,long sortlo,long sorthi)
{
long j;
/* We walk backward through the range to index because we insert new
* samples at the head of each bucket's list. At the end, they'll be
* sorted from first to last occurrence.
*/
for (j=sorthi-1; j>=sortlo; j--) {
/* i->vector[j] = the signed 16-bit sample to index.
* hv = pointer to the head of the sorted list of occurences
* of this sample
* l = the node to associate with this sample
*
* We add 32768 to convert the signed 16-bit integer to an unsigned
* range from 0 to 65535.
*
* Note that l is located within i->revindex at a position
* corresponding to the sample's position in the vector. This allows
* ipos() to determine the sample position from a returned sort_link.
*/
sort_link_t **hv = i->head+i->vector[j]+32768;
sort_link_t *l = i->revindex+j;
/* If this is the first time we've encountered this sample, add its
* bucket to the list of buckets used. This list is used only for
* resetting the index quickly.
*/
if(*hv==NULL){
i->bucketusage[i->lastbucket] = i->vector[j]+32768;
i->lastbucket++;
}
/* Point the new node at the old head, then assign the new node as
* the new head.
*/
l->next=*hv;
*hv=l;
}
/* Mark the index as initialized.
*/
i->sortbegin=0;
}
/* ===========================================================================
* sort_setup()
*
* This function initializes a previously allocated sort_info_t. The
* sort_info_t is associated with a vector of samples of length
* (size), whose position begins at (*abspos) within the CD's stream
* of samples. Only the range of samples between (sortlo, sorthi)
* will eventually be indexed for fast searching. (sortlo, sorthi)
* are absolute sample positions.
*
* ???: Why is abspos a pointer? Why not just store a copy?
*
* Note: size *must* be <= the size given to the preceding sort_alloc(),
* but no error checking is done here.
*/
void
sort_setup(sort_info_t *i, int16_t *vector, long int *abspos,
long int size, long int sortlo, long int sorthi)
{
/* Reset the index if it has already been built.
*/
if (i->sortbegin!=-1)
sort_unsortall(i);
i->vector=vector;
i->size=size;
i->abspos=abspos;
/* Convert the absolute (sortlo, sorthi) to offsets within the vector.
* Note that the index will not be built until sort_getmatch() is called.
* Here we're simply hanging on to the range to index until then.
*/
i->lo = min(size, max(sortlo - *abspos, 0));
i->hi = max(0, min(sorthi - *abspos, size));
}
/* ===========================================================================
* sort_getmatch()
*
* This function returns a sort_link_t pointer which refers to the
* first sample equal to (value) in the vector. It only searches for
* hits within (overlap) samples of (post), where (post) is an offset
* within the vector. The caller can determine the position of the
* matched sample using ipos(sort_info *, sort_link *).
*
* This function returns NULL if no matches were found.
*/
sort_link_t *
sort_getmatch(sort_info_t *i, long post, long overlap, int value)
{
sort_link_t *ret;
/* If the vector hasn't been indexed yet, index it now.
*/
if (i->sortbegin==-1)
sort_sort(i,i->lo,i->hi);
/* Now we reuse lo and hi */
/* We'll only return samples within (overlap) samples of (post).
* Clamp the boundaries to search to the boundaries of the array,
* convert the signed sample to an unsigned offset, and store the
* state so that future calls to sort_nextmatch do the right thing.
*
* Reusing lo and hi this way is awful.
*/
post=max(0,min(i->size,post));
i->val=value+32768;
i->lo=max(0,post-overlap); /* absolute position */
i->hi=min(i->size,post+overlap); /* absolute position */
/* Walk through the linked list of samples with this value, until
* we find the first one within the bounds specified. If there
* aren't any, return NULL.
*/
ret=i->head[i->val];
while (ret) {
/* ipos() calculates the offset (in terms of the original vector)
* of this hit.
*/
if (ipos(i,ret)<i->lo) {
ret=ret->next;
} else {
if (ipos(i,ret)>=i->hi)
ret=NULL;
break;
}
}
/*i->head[i->val]=ret;*/
return(ret);
}
/* ===========================================================================
* sort_nextmatch()
*
* This function returns a sort_link_t pointer which refers to the next sample
* matching the criteria previously passed to sort_getmatch(). See
* sort_getmatch() for details.
*
* This function returns NULL if no further matches were found.
*/
sort_link_t *
sort_nextmatch(sort_info_t *i, sort_link_t *prev)
{
sort_link_t *ret=prev->next;
/* If there aren't any more hits, or we've passed the boundary requested
* of sort_getmatch(), we're done.
*/
if (!ret || ipos(i,ret)>=i->hi)
return(NULL);
return(ret);
}

View File

@@ -1,161 +0,0 @@
/*
$Id: isort.h,v 1.6 2008/04/17 17:39:48 karl Exp $
Copyright (C) 2004, 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ISORT_H_
#define _ISORT_H_
typedef struct sort_link{
struct sort_link *next;
} sort_link_t;
typedef struct sort_info {
int16_t *vector; /* vector (storage doesn't belong to us) */
long *abspos; /* pointer for side effects */
long size; /* vector size */
long maxsize; /* maximum vector size */
long sortbegin; /* range of contiguous sorted area */
long lo,hi; /* current post, overlap range */
int val; /* ...and val */
/* sort structs */
sort_link_t **head; /* sort buckets (65536) */
long *bucketusage; /* of used buckets (65536) */
long lastbucket;
sort_link_t *revindex;
} sort_info_t;
/*! ========================================================================
* sort_alloc()
*
* Allocates and initializes a new, empty sort_info object, which can
* be used to index up to (size) samples from a vector.
*/
extern sort_info_t *sort_alloc(long int size);
/*! ========================================================================
* sort_unsortall() (internal)
*
* This function resets the index for further use with a different
* vector or range, without the overhead of an unnecessary free/alloc.
*/
extern void sort_unsortall(sort_info_t *i);
/*! ========================================================================
* sort_setup()
*
* This function initializes a previously allocated sort_info_t. The
* sort_info_t is associated with a vector of samples of length
* (size), whose position begins at (*abspos) within the CD's stream
* of samples. Only the range of samples between (sortlo, sorthi)
* will eventually be indexed for fast searching. (sortlo, sorthi)
* are absolute sample positions.
*
* ???: Why is abspos a pointer? Why not just store a copy?
*
* Note: size *must* be <= the size given to the preceding sort_alloc(),
* but no error checking is done here.
*/
extern void sort_setup(sort_info_t *i, int16_t *vector, long int *abspos,
long int size, long int sortlo, long int sorthi);
/* =========================================================================
* sort_free()
*
* Releases all memory consumed by a sort_info object.
*/
extern void sort_free(sort_info_t *i);
/*! ========================================================================
* sort_getmatch()
*
* This function returns a sort_link_t pointer which refers to the
* first sample equal to (value) in the vector. It only searches for
* hits within (overlap) samples of (post), where (post) is an offset
* within the vector. The caller can determine the position of the
* matched sample using ipos(sort_info *, sort_link *).
*
* This function returns NULL if no matches were found.
*/
extern sort_link_t *sort_getmatch(sort_info_t *i, long post, long overlap,
int value);
/*! ========================================================================
* sort_nextmatch()
*
* This function returns a sort_link_t pointer which refers to the
* next sample matching the criteria previously passed to
* sort_getmatch(). See sort_getmatch() for details.
*
* This function returns NULL if no further matches were found.
*/
extern sort_link_t *sort_nextmatch(sort_info_t *i, sort_link_t *prev);
/* ===========================================================================
* is()
*
* This macro returns the size of the vector indexed by the given sort_info_t.
*/
#define is(i) (i->size)
/* ===========================================================================
* ib()
*
* This macro returns the absolute position of the first sample in the vector
* indexed by the given sort_info_t.
*/
#define ib(i) (*i->abspos)
/* ===========================================================================
* ie()
*
* This macro returns the absolute position of the sample after the last
* sample in the vector indexed by the given sort_info_t.
*/
#define ie(i) (i->size+*i->abspos)
/* ===========================================================================
* iv()
*
* This macro returns the vector indexed by the given sort_info_t.
*/
#define iv(i) (i->vector)
/* ===========================================================================
* ipos()
*
* This macro returns the relative position (offset) within the indexed vector
* at which the given match was found.
*
* It uses a little-known and frightening aspect of C pointer arithmetic:
* subtracting a pointer is not an arithmetic subtraction, but rather the
* additive inverse. In other words, since
* q = p + n returns a pointer to the nth object in p,
* q - p = p + n - p, and
* q - p = n, not the difference of the two addresses.
*/
#define ipos(i,l) (l-i->revindex)
#endif /* _ISORT_H_ */

View File

@@ -1,9 +0,0 @@
cdio_paranoia_init
cdio_paranoia_free
cdio_paranoia_modeset
cdio_paranoia_seek
cdio_paranoia_read
cdio_paranoia_read_limited
cdio_paranoia_overlapset
cdio_paranoia_set_range
paranoia_cb_mode2str

View File

@@ -1,255 +0,0 @@
/*
Copyright (C) 2004, 2005, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***
*
* Statistic code and cache management for overlap settings
*
***/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <cdio/paranoia.h>
#include "p_block.h"
#include "overlap.h"
#include "isort.h"
/**** Internal cache management *****************************************/
void
paranoia_resetcache(cdrom_paranoia_t *p)
{
c_block_t *c=c_first(p);
v_fragment_t *v;
while(c){
free_c_block(c);
c=c_first(p);
}
v=v_first(p);
while(v){
free_v_fragment(v);
v=v_first(p);
}
}
void
paranoia_resetall(cdrom_paranoia_t *p)
{
p->root.returnedlimit=0;
p->dyndrift=0;
p->root.lastsector=0;
if(p->root.vector){
i_cblock_destructor(p->root.vector);
p->root.vector=NULL;
}
paranoia_resetcache(p);
}
void
i_paranoia_trim(cdrom_paranoia_t *p, long int beginword, long int endword)
{
root_block *root=&(p->root);
if(root->vector!=NULL){
long target=beginword-MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
long rbegin=cb(root->vector);
long rend=ce(root->vector);
if(rbegin>beginword)
goto rootfree;
if(rbegin+MAX_SECTOR_OVERLAP*CD_FRAMEWORDS<beginword){
if(target+MIN_WORDS_OVERLAP>rend)
goto rootfree;
{
long int offset=target-rbegin;
c_removef(root->vector,offset);
}
}
{
c_block_t *c=c_first(p);
while(c){
c_block_t *next=c_next(c);
if(ce(c)<beginword-MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)
free_c_block(c);
c=next;
}
}
}
return;
rootfree:
i_cblock_destructor(root->vector);
root->vector=NULL;
root->returnedlimit=-1;
root->lastsector=0;
}
/**** Statistical and heuristic[al? :-] management ************************/
/* ===========================================================================
* offset_adjust_settings (internal)
*
* This function is called by offset_add_value() every time 10 samples have
* been accumulated. This function updates the internal statistics for
* paranoia (dynoverlap, dyndrift) that compensate for jitter and drift.
*
* (dynoverlap) influences how far stage 1 and stage 2 search for matching
* runs. In low-jitter conditions, it will be very small (or even 0),
* narrowing our search. In high-jitter conditions, it will be much larger,
* widening our search at the cost of speed.
*
* ???: To be studied further.
*/
void
offset_adjust_settings(cdrom_paranoia_t *p,
void(*callback)(long int, paranoia_cb_mode_t))
{
if(p->stage2.offpoints>=10){
/* drift: look at the average offset value. If it's over one
sector, frob it. We just want a little hysteresis [sp?]*/
long av=(p->stage2.offpoints?p->stage2.offaccum/p->stage2.offpoints:0);
if(abs(av)>p->dynoverlap/4){
av=(av/MIN_SECTOR_EPSILON)*MIN_SECTOR_EPSILON;
if(callback)(*callback)(ce(p->root.vector),PARANOIA_CB_DRIFT);
p->dyndrift+=av;
/* Adjust all the values in the cache otherwise we get a
(potentially unstable) feedback loop */
{
c_block_t *c=c_first(p);
v_fragment_t *v=v_first(p);
while(v && v->one){
/* safeguard beginning bounds case with a hammer */
if(fb(v)<av || cb(v->one)<av){
v->one=NULL;
}else{
fb(v)-=av;
}
v=v_next(v);
}
while(c){
long adj=min(av,cb(c));
c_set(c,cb(c)-adj);
c=c_next(c);
}
}
p->stage2.offaccum=0;
p->stage2.offmin=0;
p->stage2.offmax=0;
p->stage2.offpoints=0;
p->stage2.newpoints=0;
p->stage2.offdiff=0;
}
}
if(p->stage1.offpoints>=10){
/* dynoverlap: we arbitrarily set it to 4x the running difference
value, unless min/max are more */
p->dynoverlap=(p->stage1.offpoints?p->stage1.offdiff/
p->stage1.offpoints*3:CD_FRAMEWORDS);
if(p->dynoverlap<-p->stage1.offmin*1.5)
p->dynoverlap=-p->stage1.offmin*1.5;
if(p->dynoverlap<p->stage1.offmax*1.5)
p->dynoverlap=p->stage1.offmax*1.5;
if(p->dynoverlap<MIN_SECTOR_EPSILON)p->dynoverlap=MIN_SECTOR_EPSILON;
if(p->dynoverlap>MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)
p->dynoverlap=MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
if(callback)(*callback)(p->dynoverlap,PARANOIA_CB_OVERLAP);
if(p->stage1.offpoints>600){ /* bit of a bug; this routine is
called too often due to the overlap
mesh alg we use in stage 1 */
p->stage1.offpoints/=1.2;
p->stage1.offaccum/=1.2;
p->stage1.offdiff/=1.2;
}
p->stage1.offmin=0;
p->stage1.offmax=0;
p->stage1.newpoints=0;
}
}
/* ===========================================================================
* offset_add_value (internal)
*
* This function adds the given jitter detected (value) to the statistics
* for the given stage (o). It is called whenever jitter has been identified
* by stage 1 or 2. After every 10 samples, we update the overall jitter-
* compensation settings (e.g. dynoverlap). This allows us to narrow our
* search for matching runs (in both stages) in low-jitter conditions
* and also widen our search appropriately when there is jitter.
*
* ???BUG???:
* Note that there is a bug in the way that this is called by try_sort_sync().
* Silence looks like zero jitter, and dynoverlap may be incorrectly reduced
* when there's lots of silence but also jitter.
*
* See the bug notes in try_sort_sync() for details.
*/
void
offset_add_value(cdrom_paranoia_t *p,offsets *o,long value,
void(*callback)(long int, paranoia_cb_mode_t))
{
if(o->offpoints!=-1){
/* Track the average magnitude of jitter (in either direction) */
o->offdiff+=abs(value);
o->offpoints++;
o->newpoints++;
/* Track the net value of the jitter (to track drift) */
o->offaccum+=value;
/* Track the largest jitter we've encountered in each direction */
if(value<o->offmin)o->offmin=value;
if(value>o->offmax)o->offmax=value;
/* After 10 samples, update dynoverlap, etc. */
if(o->newpoints>=10)offset_adjust_settings(p,callback);
}
}

View File

@@ -1,33 +0,0 @@
/*
$Id: overlap.h,v 1.2 2008/04/17 17:39:48 karl Exp $
Copyright (C) 2004, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _OVERLAP_H_
#define _OVERLAP_H_
extern void offset_add_value(cdrom_paranoia_t *p,offsets *o,long value,
void(*callback)(long int, paranoia_cb_mode_t));
extern void offset_clear_settings(offsets *o);
extern void offset_adjust_settings(cdrom_paranoia_t *p,
void(*callback)(long, paranoia_cb_mode_t));
extern void i_paranoia_trim(cdrom_paranoia_t *p,long beginword,long endword);
extern void paranoia_resetall(cdrom_paranoia_t *p);
extern void paranoia_resetcache(cdrom_paranoia_t *p);
#endif /*_OVERLAP_H_*/

View File

@@ -1,458 +0,0 @@
/*
Copyright (C) 2004, 2005, 2007, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) 1998 Monty xiphmont@mit.edu
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <limits.h>
#include "p_block.h"
#include <cdio/cdda.h>
#include <cdio/paranoia.h>
linked_list_t *new_list(void *(*newp)(void),void (*freep)(void *))
{
linked_list_t *ret=calloc(1,sizeof(linked_list_t));
ret->new_poly=newp;
ret->free_poly=freep;
return(ret);
}
linked_element *add_elem(linked_list_t *l,void *elem)
{
linked_element *ret=calloc(1,sizeof(linked_element));
ret->stamp=l->current++;
ret->ptr=elem;
ret->list=l;
if(l->head)
l->head->prev=ret;
else
l->tail=ret;
ret->next=l->head;
ret->prev=NULL;
l->head=ret;
l->active++;
return(ret);
}
linked_element *
new_elem(linked_list_t *p_list)
{
void *p_new=p_list->new_poly();
return(add_elem(p_list,p_new));
}
void
free_elem(linked_element *e,int free_ptr)
{
linked_list_t *l=e->list;
if(free_ptr)l->free_poly(e->ptr);
if(e==l->head)
l->head=e->next;
if(e==l->tail)
l->tail=e->prev;
if(e->prev)
e->prev->next=e->next;
if(e->next)
e->next->prev=e->prev;
l->active--;
free(e);
}
void
free_list(linked_list_t *list,int free_ptr)
{
while(list->head)
free_elem(list->head,free_ptr);
free(list);
}
void *get_elem(linked_element *e)
{
return(e->ptr);
}
linked_list_t *copy_list(linked_list_t *list)
{
linked_list_t *new=new_list(list->new_poly,list->free_poly);
linked_element *i=list->tail;
while(i){
add_elem(new,i->ptr);
i=i->prev;
}
return(new);
}
/**** C_block stuff ******************************************************/
static c_block_t *
i_cblock_constructor(cdrom_paranoia_t *p)
{
c_block_t *ret=calloc(1,sizeof(c_block_t));
return(ret);
}
void
i_cblock_destructor(c_block_t *c)
{
if(c){
if(c->vector)free(c->vector);
if(c->flags)free(c->flags);
c->e=NULL;
free(c);
}
}
c_block_t *
new_c_block(cdrom_paranoia_t *p)
{
linked_element *e=new_elem(p->cache);
c_block_t *c=e->ptr;
c->e=e;
c->p=p;
return(c);
}
void free_c_block(c_block_t *c)
{
/* also rid ourselves of v_fragments that reference this block */
v_fragment_t *v=v_first(c->p);
while(v){
v_fragment_t *next=v_next(v);
if(v->one==c)free_v_fragment(v);
v=next;
}
free_elem(c->e,1);
}
static v_fragment_t *
i_vfragment_constructor(void)
{
v_fragment_t *ret=calloc(1,sizeof(v_fragment_t));
return(ret);
}
static void
i_v_fragment_destructor(v_fragment_t *v)
{
free(v);
}
v_fragment_t *
new_v_fragment(cdrom_paranoia_t *p, c_block_t *one,
long int begin, long int end, int last)
{
linked_element *e=new_elem(p->fragments);
v_fragment_t *b=e->ptr;
b->e=e;
b->p=p;
b->one=one;
b->begin=begin;
b->vector=one->vector+begin-one->begin;
b->size=end-begin;
b->lastsector=last;
#if TRACE_PARANOIA
fprintf(stderr, "- Verified [%ld-%ld] (0x%04X...0x%04X)%s\n",
begin, end,
b->vector[0]&0xFFFF, b->vector[b->size-1]&0xFFFF,
last ? " *" : "");
#endif
return(b);
}
void free_v_fragment(v_fragment_t *v)
{
free_elem(v->e,1);
}
c_block_t *
c_first(cdrom_paranoia_t *p)
{
if(p->cache->head)
return(p->cache->head->ptr);
return(NULL);
}
c_block_t *
c_last(cdrom_paranoia_t *p)
{
if(p->cache->tail)
return(p->cache->tail->ptr);
return(NULL);
}
c_block_t *
c_next(c_block_t *c)
{
if(c->e->next)
return(c->e->next->ptr);
return(NULL);
}
c_block_t *
c_prev(c_block_t *c)
{
if(c->e->prev)
return(c->e->prev->ptr);
return(NULL);
}
v_fragment_t *
v_first(cdrom_paranoia_t *p)
{
if(p->fragments->head){
return(p->fragments->head->ptr);
}
return(NULL);
}
v_fragment_t *
v_last(cdrom_paranoia_t *p)
{
if(p->fragments->tail)
return(p->fragments->tail->ptr);
return(NULL);
}
v_fragment_t *
v_next(v_fragment_t *v)
{
if(v->e->next)
return(v->e->next->ptr);
return(NULL);
}
v_fragment_t *
v_prev(v_fragment_t *v)
{
if(v->e->prev)
return(v->e->prev->ptr);
return(NULL);
}
void
recover_cache(cdrom_paranoia_t *p)
{
linked_list_t *l=p->cache;
/* Are we at/over our allowed cache size? */
while(l->active>p->cache_limit)
/* cull from the tail of the list */
free_c_block(c_last(p));
}
int16_t *
v_buffer(v_fragment_t *v)
{
if(!v->one)return(NULL);
if(!cv(v->one))return(NULL);
return(v->vector);
}
/* alloc a c_block not on a cache list */
c_block_t *
c_alloc(int16_t *vector, long begin, long size)
{
c_block_t *c=calloc(1,sizeof(c_block_t));
c->vector=vector;
c->begin=begin;
c->size=size;
return(c);
}
void c_set(c_block_t *v,long begin){
v->begin=begin;
}
/* pos here is vector position from zero */
void
c_insert(c_block_t *v,long pos,int16_t *b,long size)
{
int vs=cs(v);
if(pos<0 || pos>vs)return;
if(v->vector) {
v->vector = realloc(v->vector,sizeof(int16_t)*(size+vs));
} else {
v->vector = calloc(1, sizeof(int16_t)*size);
}
if(pos<vs)memmove(v->vector+pos+size,v->vector+pos,
(vs-pos)*sizeof(int16_t));
memcpy(v->vector+pos,b,size*sizeof(int16_t));
v->size+=size;
}
void
c_remove(c_block_t *v, long cutpos, long cutsize)
{
int vs=cs(v);
if(cutpos<0 || cutpos>vs)return;
if(cutpos+cutsize>vs)cutsize=vs-cutpos;
if(cutsize<0)cutsize=vs-cutpos;
if(cutsize<1)return;
memmove(v->vector+cutpos,v->vector+cutpos+cutsize,
(vs-cutpos-cutsize)*sizeof(int16_t));
v->size-=cutsize;
}
void
c_overwrite(c_block_t *v,long pos,int16_t *b,long size)
{
int vs=cs(v);
if(pos<0)return;
if(pos+size>vs)size=vs-pos;
memcpy(v->vector+pos,b,size*sizeof(int16_t));
}
void
c_append(c_block_t *v, int16_t *vector, long size)
{
int vs=cs(v);
/* update the vector */
if(v->vector)
v->vector=realloc(v->vector,sizeof(int16_t)*(size+vs));
else {
v->vector=calloc(1, sizeof(int16_t)*size);
}
memcpy(v->vector+vs,vector,sizeof(int16_t)*size);
v->size+=size;
}
void
c_removef(c_block_t *v, long cut)
{
c_remove(v,0,cut);
v->begin+=cut;
}
/**** Initialization *************************************************/
/*! Get the beginning and ending sector bounds given cursor position.
There are a couple of subtle differences between this and the
cdda_firsttrack_sector and cdda_lasttrack_sector. If the cursor is
an a sector later than cdda_firsttrack_sector, that sectur will be
used. As for the difference between cdda_lasttrack_sector, if the CD
is mixed and there is a data track after the cursor but before the
last audio track, the end of the audio sector before that is used.
*/
void
i_paranoia_firstlast(cdrom_paranoia_t *p)
{
track_t i, j;
cdrom_drive_t *d=p->d;
const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
const track_t i_last_track = cdio_get_last_track_num(d->p_cdio);
p->current_lastsector = p->current_firstsector = -1;
i = cdda_sector_gettrack(d, p->cursor);
if ( CDIO_INVALID_TRACK != i ) {
if ( 0 == i ) i++;
j = i;
/* In the below loops, We assume the cursor already is on an audio
sector. Not sure if this is correct if p->cursor is in the pregap
before the first track.
*/
for ( ; i < i_last_track; i++)
if( !cdda_track_audiop(d,i) ) {
p->current_lastsector=cdda_track_lastsector(d,i-1);
break;
}
i = j;
for ( ; i >= i_first_track; i-- )
if( !cdda_track_audiop(d,i) ) {
p->current_firstsector = cdda_track_firstsector(d,i+1);
break;
}
}
if (p->current_lastsector == -1)
p->current_lastsector = cdda_disc_lastsector(d);
if(p->current_firstsector == -1)
p->current_firstsector = cdda_disc_firstsector(d);
}
cdrom_paranoia_t *
paranoia_init(cdrom_drive_t *d)
{
cdrom_paranoia_t *p=calloc(1,sizeof(cdrom_paranoia_t));
p->cache=new_list((void *)&i_cblock_constructor,
(void *)&i_cblock_destructor);
p->fragments=new_list((void *)&i_vfragment_constructor,
(void *)&i_v_fragment_destructor);
p->readahead=150;
p->sortcache=sort_alloc(p->readahead*CD_FRAMEWORDS);
p->d=d;
p->dynoverlap=MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
p->cache_limit=JIGGLE_MODULO;
p->enable=PARANOIA_MODE_FULL;
p->cursor=cdda_disc_firstsector(d);
p->lastread=LONG_MAX;
/* One last one... in case data and audio tracks are mixed... */
i_paranoia_firstlast(p);
return(p);
}
void paranoia_set_range(cdrom_paranoia_t *p, long start, long end)
{
p->cursor = start;
p->current_firstsector = start;
p->current_lastsector = end;
}

View File

@@ -1,213 +0,0 @@
/*
$Id: p_block.h,v 1.6 2008/04/17 17:39:48 karl Exp $
Copyright (C) 2004, 2005, 2008 Rocky Bernstein <rocky@gnu.org>
Copyright (C) by Monty (xiphmont@mit.edu)
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _P_BLOCK_H_
#define _P_BLOCK_H_
#include <cdio/paranoia.h>
#include <cdio/cdda.h>
#define MIN_WORDS_OVERLAP 64 /* 16 bit words */
#define MIN_WORDS_SEARCH 64 /* 16 bit words */
#define MIN_WORDS_RIFT 16 /* 16 bit words */
#define MAX_SECTOR_OVERLAP 32 /* sectors */
#define MIN_SECTOR_EPSILON 128 /* words */
#define MIN_SECTOR_BACKUP 16 /* sectors */
#define JIGGLE_MODULO 15 /* sectors */
#define MIN_SILENCE_BOUNDARY 1024 /* 16 bit words */
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)<(y)?(y):(x))
#include "isort.h"
typedef struct {
/* linked list */
struct linked_element *head;
struct linked_element *tail;
void *(*new_poly)();
void (*free_poly)(void *poly);
long current;
long active;
} linked_list_t;
typedef struct linked_element{
void *ptr;
struct linked_element *prev;
struct linked_element *next;
linked_list_t *list;
int stamp;
} linked_element;
extern linked_list_t *new_list(void *(*new_fn)(void),void (*free)(void *));
extern linked_element *new_elem(linked_list_t *list);
extern linked_element *add_elem(linked_list_t *list,void *elem);
extern void free_list(linked_list_t *list,int free_ptr); /* unlink or free */
extern void free_elem(linked_element *e,int free_ptr); /* unlink or free */
extern void *get_elem(linked_element *e);
/* This is a shallow copy; it doesn't copy contained structures */
extern linked_list_t *copy_list(linked_list_t *p_list);
typedef struct c_block {
/* The buffer */
int16_t *vector;
long begin;
long size;
/* auxiliary support structures */
unsigned char *flags; /* 1 known boundaries in read data
2 known blanked data
4 matched sample
8 reserved
16 reserved
32 reserved
64 reserved
128 reserved
*/
/* end of session cases */
long lastsector;
cdrom_paranoia_t *p;
struct linked_element *e;
} c_block_t;
extern void free_c_block(c_block_t *c);
extern void i_cblock_destructor(c_block_t *c);
extern c_block_t *new_c_block(cdrom_paranoia_t *p);
typedef struct v_fragment_s {
c_block_t *one;
long begin;
long size;
int16_t *vector;
/* end of session cases */
long lastsector;
/* linked list */
cdrom_paranoia_t *p;
struct linked_element *e;
} v_fragment_t;
extern void free_v_fragment(v_fragment_t *c);
extern v_fragment_t *new_v_fragment(cdrom_paranoia_t *p, c_block_t *one,
long int begin, long int end,
int lastsector);
extern int16_t *v_buffer(v_fragment_t *v);
extern c_block_t *c_first(cdrom_paranoia_t *p);
extern c_block_t *c_last(cdrom_paranoia_t *p);
extern c_block_t *c_next(c_block_t *c);
extern c_block_t *c_prev(c_block_t *c);
extern v_fragment_t *v_first(cdrom_paranoia_t *p);
extern v_fragment_t *v_last(cdrom_paranoia_t *p);
extern v_fragment_t *v_next(v_fragment_t *v);
extern v_fragment_t *v_prev(v_fragment_t *v);
typedef struct root_block{
long returnedlimit;
long lastsector;
cdrom_paranoia_t *p;
c_block_t *vector; /* doesn't use any sorting */
int silenceflag;
long silencebegin;
} root_block;
typedef struct offsets{
long offpoints;
long newpoints;
long offaccum;
long offdiff;
long offmin;
long offmax;
} offsets;
struct cdrom_paranoia_s {
cdrom_drive_t *d;
root_block root; /* verified/reconstructed cached data */
linked_list_t *cache; /* our data as read from the cdrom */
long int cache_limit;
linked_list_t *fragments; /* fragments of blocks that have been 'verified' */
sort_info_t *sortcache;
int readahead; /* sectors of readahead in each readop */
int jitter;
long lastread;
paranoia_cb_mode_t enable;
long int cursor;
long int current_lastsector;
long int current_firstsector;
/* statistics for drift/overlap */
struct offsets stage1;
struct offsets stage2;
long dynoverlap;
long dyndrift;
/* statistics for verification */
};
extern c_block_t *c_alloc(int16_t *vector,long begin,long size);
extern void c_set(c_block_t *v,long begin);
extern void c_insert(c_block_t *v,long pos,int16_t *b,long size);
extern void c_remove(c_block_t *v,long cutpos,long cutsize);
extern void c_overwrite(c_block_t *v,long pos,int16_t *b,long size);
extern void c_append(c_block_t *v, int16_t *vector, long size);
extern void c_removef(c_block_t *v, long cut);
#define ce(v) (v->begin+v->size)
#define cb(v) (v->begin)
#define cs(v) (v->size)
/* pos here is vector position from zero */
extern void recover_cache(cdrom_paranoia_t *p);
extern void i_paranoia_firstlast(cdrom_paranoia_t *p);
#define cv(c) (c->vector)
#define fe(f) (f->begin+f->size)
#define fb(f) (f->begin)
#define fs(f) (f->size)
#define fv(f) (v_buffer(f))
#ifndef DO_NOT_WANT_PARANOIA_COMPATIBILITY
/** For compatibility with good ol' paranoia */
#define linked_list linked_list_t
#endif /*DO_NOT_WANT_PARANOIA_COMPATIBILITY*/
#define CDP_COMPILE
#endif /*_P_BLOCK_H_*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,4 @@
# $Id: Makefile.am,v 1.48 2008/08/31 13:38:22 flameeyes Exp $
#
# Copyright (C) 2003, 2004, 2006, 2008 Rocky Bernstein <rocky@gnu.org>
# Copyright (C) 2003, 2004, 2006, 2008, 2012 Rocky Bernstein <rocky@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
@@ -23,10 +21,6 @@ noinst_HEADERS = cddb.h getopt.h util.h
# Things to make the utility/diagnostic programs
####################################################
if BUILD_CD_PARANOIA
SUBDIRS = cd-paranoia
endif
CDDB_LIBS=@CDDB_LIBS@
CDDA_PLAYER_LIBS=@CDDA_PLAYER_LIBS@

View File

@@ -23,11 +23,6 @@
SUBDIRS = data driver
if BUILD_CD_PARANOIA
testparanoia=testparanoia
testparanoia_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) $(LIBCDIO_LIBS) $(LTLIBICONV)
endif
hack = check_sizeof testassert testgetdevices testischar \
testisocd testisocd2 testiso9660 test_lib_driver_util \
$(testparanoia) testpregap testunconfig

View File

@@ -65,7 +65,7 @@ get_temporary_name(const char *dirname, const char *errmsg)
{
char *new_filename = tempnam(NULL, "syml");
if (NULL == new_filename) {
printf("Could not generate %s name\n", errmsg);
printf("Could not generate %s name\n", errmsg);
}
return new_filename;
}
@@ -74,11 +74,11 @@ static int check_rc(int rc, const char *psz_operation,
const char *psz_filename)
{
if (-1 == rc) {
printf("%s %s failed with error: %s\n",
psz_operation, psz_filename, strerror(errno));
printf("%s %s failed with error: %s\n",
psz_operation, psz_filename, strerror(errno));
} else if (0 != rc) {
printf("%s %s gives weird return %d\n",
psz_operation, psz_filename, rc);
printf("%s %s gives weird return %d\n",
psz_operation, psz_filename, rc);
}
return rc;
}
@@ -99,18 +99,18 @@ main(int argc, const char *argv[])
psz_tmp_subdir = get_temporary_name(NULL, "temporary directory");
if (NULL == psz_tmp_subdir) {
exit(77);
exit(77);
}
if (-1 == check_rc(mkdir(psz_tmp_subdir, 0700),
"mkdir", psz_tmp_subdir))
exit(77);
"mkdir", psz_tmp_subdir))
exit(77);
cdio_realpath(psz_tmp_subdir, tmp_subdir);
if (0 == strlen(tmp_subdir)) {
fprintf(stderr, "cdio_realpath on temp directory %s failed\n",
psz_tmp_subdir);
psz_tmp_subdir);
exit(1);
}
@@ -122,48 +122,48 @@ main(int argc, const char *argv[])
psz_orig_file = get_temporary_name(NULL, "file");
if (NULL != psz_orig_file) {
FILE *fp = fopen(psz_orig_file, "w");
char orig_file[PATH_MAX+1] = {0};
int rc;
char symlink_file[PATH_MAX+1] = {0};
FILE *fp = fopen(psz_orig_file, "w");
char orig_file[PATH_MAX+1] = {0};
int rc;
char symlink_file[PATH_MAX+1] = {0};
fprintf(fp, "testing\n");
fclose(fp);
cdio_realpath(psz_orig_file, orig_file);
if (0 == strlen(orig_file)) {
fprintf(stderr, "cdio_realpath on temp file %s failed\n",
psz_orig_file);
exit(2);
}
fprintf(fp, "testing\n");
fclose(fp);
cdio_realpath(psz_orig_file, orig_file);
if (0 == strlen(orig_file)) {
fprintf(stderr, "cdio_realpath on temp file %s failed\n",
psz_orig_file);
exit(2);
}
psz_symlink_file = get_temporary_name(NULL, "symlink file");
rc = check_rc(symlink(psz_orig_file, psz_symlink_file),
"symlink", psz_symlink_file);
if (0 == rc) {
/* Just when you thought we'd forgotten, here is our first
test! */
cdio_realpath(psz_symlink_file, psz_file_check);
if (0 != strncmp(psz_file_check, orig_file, PATH_MAX)) {
fprintf(stderr, "simple cdio_realpath failed: %s vs %s\n",
psz_file_check, orig_file);
exit(3);
}
check_rc(unlink(psz_symlink_file), "unlink", psz_symlink_file);
}
psz_symlink_file = get_temporary_name(NULL, "symlink file");
rc = check_rc(symlink(psz_orig_file, psz_symlink_file),
"symlink", psz_symlink_file);
if (0 == rc) {
/* Just when you thought we'd forgotten, here is our first
test! */
cdio_realpath(psz_symlink_file, psz_file_check);
if (0 != strncmp(psz_file_check, orig_file, PATH_MAX)) {
fprintf(stderr, "simple cdio_realpath failed: %s vs %s\n",
psz_file_check, orig_file);
exit(3);
}
check_rc(unlink(psz_symlink_file), "unlink", psz_symlink_file);
}
/* Make sure we handle a cyclic symbolic name, e.g. xx -> xx */
cdio_realpath(psz_symlink_file, symlink_file);
rc = check_rc(symlink(psz_symlink_file, psz_symlink_file),
"symlink", psz_symlink_file);
if (0 == rc) {
cdio_realpath(psz_symlink_file, psz_file_check);
if (0 != strncmp(psz_file_check, symlink_file, PATH_MAX)) {
fprintf(stderr, "direct cdio_realpath cycle test failed. %s vs %s\n",
psz_file_check, symlink_file);
exit(4);
}
check_rc(unlink(psz_symlink_file), "unlink", psz_symlink_file);
}
/* Make sure we handle a cyclic symbolic name, e.g. xx -> xx */
cdio_realpath(psz_symlink_file, symlink_file);
rc = check_rc(symlink(psz_symlink_file, psz_symlink_file),
"symlink", psz_symlink_file);
if (0 == rc) {
cdio_realpath(psz_symlink_file, psz_file_check);
if (0 != strncmp(psz_file_check, symlink_file, PATH_MAX)) {
fprintf(stderr, "direct cdio_realpath cycle test failed. %s vs %s\n",
psz_file_check, symlink_file);
exit(4);
}
check_rc(unlink(psz_symlink_file), "unlink", psz_symlink_file);
}
}