From a8937ea36effa0ba5193f846b37719baf67ac994 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 29 Dec 2005 12:22:24 +0000 Subject: [PATCH] New cdparanoiasrc element based on cddabasesrc; enable cdparanoia plugin again (there are still fixes required to pla... Original commit message from CVS: * configure.ac: * ext/cdparanoia/Makefile.am: * ext/cdparanoia/gstcdparanoia.c: * ext/cdparanoia/gstcdparanoia.h: * ext/cdparanoia/gstcdparanoiasrc.c: (gst_cd_paranoia_mode_get_type), (gst_cd_paranoia_src_base_init), (gst_cd_paranoia_src_init), (gst_cd_paranoia_src_class_init), (gst_cd_paranoia_src_open), (gst_cd_paranoia_src_close), (gst_cd_paranoia_paranoia_callback), (gst_cd_paranoia_src_read_sector), (gst_cd_paranoia_src_finalize), (gst_cd_paranoia_src_set_property), (gst_cd_paranoia_src_get_property), (plugin_init): * ext/cdparanoia/gstcdparanoiasrc.h: New cdparanoiasrc element based on cddabasesrc; enable cdparanoia plugin again (there are still fixes required to playbin to make cdda:// uris work there). --- ChangeLog | 19 + configure.ac | 5 - ext/cdparanoia/Makefile.am | 12 +- ext/cdparanoia/gstcdparanoia.c | 1114 ------------------------------------- ext/cdparanoia/gstcdparanoia.h | 122 ---- ext/cdparanoia/gstcdparanoiasrc.c | 398 +++++++++++++ ext/cdparanoia/gstcdparanoiasrc.h | 74 +++ 7 files changed, 500 insertions(+), 1244 deletions(-) delete mode 100644 ext/cdparanoia/gstcdparanoia.c delete mode 100644 ext/cdparanoia/gstcdparanoia.h create mode 100644 ext/cdparanoia/gstcdparanoiasrc.c create mode 100644 ext/cdparanoia/gstcdparanoiasrc.h diff --git a/ChangeLog b/ChangeLog index 7d91498..ed30254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2005-12-29 Tim-Philipp Müller + * configure.ac: + * ext/cdparanoia/Makefile.am: + * ext/cdparanoia/gstcdparanoia.c: + * ext/cdparanoia/gstcdparanoia.h: + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_mode_get_type), (gst_cd_paranoia_src_base_init), + (gst_cd_paranoia_src_init), (gst_cd_paranoia_src_class_init), + (gst_cd_paranoia_src_open), (gst_cd_paranoia_src_close), + (gst_cd_paranoia_paranoia_callback), + (gst_cd_paranoia_src_read_sector), (gst_cd_paranoia_src_finalize), + (gst_cd_paranoia_src_set_property), + (gst_cd_paranoia_src_get_property), (plugin_init): + * ext/cdparanoia/gstcdparanoiasrc.h: + New cdparanoiasrc element based on cddabasesrc; enable cdparanoia + plugin again (there are still fixes required to playbin to make + cdda:// uris work there). + +2005-12-29 Tim-Philipp Müller + * tests/check/Makefile.am: Fix test case compilation. diff --git a/configure.ac b/configure.ac index e1f83da..95a921c 100644 --- a/configure.ac +++ b/configure.ac @@ -430,11 +430,6 @@ GST_CHECK_FEATURE(CDPARANOIA, [CDParanoia], cdparanoia, [ defined if cdda headers are in a cdda/ directory) fi AC_SUBST(CDPARANOIA_LIBS) - - dnl FIXME: temporarily disable for release - HAVE_CDPARANOIA=no -], disabled, , [ - AC_MSG_NOTICE(cdparanoiasrc not stable yet, not building) ]) dnl FIXME : add second check somehow if that is necessary dnl AC_CHECK_LIB(cdda_paranoia, paranoia_init, : , HAVE_CDPARANOIA=no, -lcdda_interface ) diff --git a/ext/cdparanoia/Makefile.am b/ext/cdparanoia/Makefile.am index e14b110..0a74a7a 100644 --- a/ext/cdparanoia/Makefile.am +++ b/ext/cdparanoia/Makefile.am @@ -1,8 +1,14 @@ plugin_LTLIBRARIES = libgstcdparanoia.la -libgstcdparanoia_la_SOURCES = gstcdparanoia.c +libgstcdparanoia_la_SOURCES = gstcdparanoiasrc.c libgstcdparanoia_la_CFLAGS = $(GST_CFLAGS) libgstcdparanoia_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstcdparanoia_la_LIBADD = $(CDPARANOIA_LIBS) $(GST_LIBS) $(GST_BASE_LIBS) +libgstcdparanoia_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/cdda/libgstcdda-@GST_MAJORMINOR@.la \ + $(CDPARANOIA_LIBS) \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) + +noinst_HEADERS = gstcdparanoiasrc.h + -noinst_HEADERS = gstcdparanoia.h diff --git a/ext/cdparanoia/gstcdparanoia.c b/ext/cdparanoia/gstcdparanoia.c deleted file mode 100644 index c59a91f..0000000 --- a/ext/cdparanoia/gstcdparanoia.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * <2005> Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gst/gst-i18n-plugin.h" -#include - -/* taken from linux/cdrom.h */ -#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ - -#include "gstcdparanoia.h" - -GST_DEBUG_CATEGORY_STATIC (cdparanoia_debug); -#define GST_CAT_DEFAULT cdparanoia_debug - -static GstElementDetails cdparanoia_details = { - "CD Audio (cdda) Source, Paranoia IV", - "Source/File", - "Read audio from CD in paranoid mode", - "Erik Walthinsen , " "Wim Taymans ", -}; - -/* we only have one possible caps */ -static GstStaticPadTemplate cdparanoia_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) true, " - "width = (int) 16, " - "depth = (int) 16, " "rate = (int) 44100, " "channels = (int) 2") - ); - - -/* Define useful types for non-programmatic interfaces **********/ -#define GST_TYPE_PARANOIA_MODE (gst_paranoia_mode_get_type()) -static GType -gst_paranoia_mode_get_type (void) -{ - /* FIXME, these are flags and a few of them are missing. */ - static GType paranoia_mode_type = 0; - static GEnumValue paranoia_modes[] = { - {PARANOIA_MODE_DISABLE, "Disable paranoid checking", "disable"}, - {PARANOIA_MODE_OVERLAP, "cdda2wav-style overlap checking", "overlap"}, - {PARANOIA_MODE_FULL, "Full paranoia", "full"}, - {0, NULL, NULL}, - }; - - if (!paranoia_mode_type) { - paranoia_mode_type = - g_enum_register_static ("GstParanoiaMode", paranoia_modes); - } - return paranoia_mode_type; -} - -typedef enum -{ - GST_PARANOIA_LE = 0, - GST_PARANOIA_BE = 1, -} GstParanoiaEndian; - -#define GST_TYPE_PARANOIA_ENDIAN (gst_paranoia_endian_get_type()) -static GType -gst_paranoia_endian_get_type (void) -{ - static GType paranoia_endian_type = 0; - static GEnumValue paranoia_endians[] = { - {GST_PARANOIA_LE, "treat drive as little endian", "little-endian"}, - {GST_PARANOIA_BE, "treat drive as big endian", "big-endian"}, - {0, NULL, NULL}, - }; - - if (!paranoia_endian_type) { - paranoia_endian_type = - g_enum_register_static ("GstParanoiaEndian", paranoia_endians); - } - return paranoia_endian_type; -} - -/* Standard stuff for signals and arguments **********/ -/* CDParanoia signals and args */ -enum -{ - SMILIE_CHANGE, - TRANSPORT_ERROR, - UNCORRECTED_ERROR, - LAST_SIGNAL -}; - -#define DEFAULT_DEVICE "/dev/cdrom" -#define DEFAULT_GENERIC_DEVICE NULL -#define DEFAULT_DEFAULT_SECTORS -1 -#define DEFAULT_SEARCH_OVERLAP -1 -#define DEFAULT_ENDIAN GST_PARANOIA_LE -#define DEFAULT_READ_SPEED -1 -#define DEFAULT_TOC_OFFSET 0 -#define DEFAULT_TOC_BIAS FALSE -#define DEFAULT_NEVER_SKIP FALSE -#define DEFAULT_ABORT_ON_SKIP FALSE -#define DEFAULT_PARANOIA_MODE 2 -#define DEFAULT_SMILIE -#define DEFAULT_DISCID NULL - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_GENERIC_DEVICE, - PROP_DEFAULT_SECTORS, - PROP_SEARCH_OVERLAP, - PROP_ENDIAN, - PROP_READ_SPEED, - PROP_TOC_OFFSET, - PROP_TOC_BIAS, - PROP_NEVER_SKIP, - PROP_ABORT_ON_SKIP, - PROP_PARANOIA_MODE, - PROP_SMILIE, - PROP_DISCID -}; - -static void cdparanoia_finalize (GObject * obj); - -static void cdparanoia_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void cdparanoia_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean cdparanoia_start (GstBaseSrc * bsrc); -static gboolean cdparanoia_stop (GstBaseSrc * bsrc); - -static GstFlowReturn cdparanoia_create (GstPushSrc * src, GstBuffer ** buffer); -static gboolean cdparanoia_convert (CDParanoia * src, - GstFormat src_format, - gint64 src_value, GstFormat * dest_format, gint64 * dest_value); -static gboolean cdparanoia_query (GstBaseSrc * bsrc, GstQuery * query); -static const GstQueryType *cdparanoia_get_query_types (GstPad * pad); -static gboolean cdparanoia_is_seekable (GstBaseSrc * bsrc); -static gboolean cdparanoia_do_seek (GstBaseSrc * bsrc, GstSegment * segment); - -static void cdparanoia_set_index (GstElement * element, GstIndex * index); -static GstIndex *cdparanoia_get_index (GstElement * element); - -static void cdparanoia_uri_handler_init (gpointer g_iface, gpointer iface_data); - -static void -_do_init (GType cdparanoia_type) -{ - static const GInterfaceInfo urihandler_info = { - cdparanoia_uri_handler_init, - NULL, - NULL, - }; - - g_type_add_interface_static (cdparanoia_type, GST_TYPE_URI_HANDLER, - &urihandler_info); - - GST_DEBUG_CATEGORY_INIT (cdparanoia_debug, "cdparanoia", 0, - "cdparanoia element"); -} - -GST_BOILERPLATE_FULL (CDParanoia, cdparanoia, GstPushSrc, GST_TYPE_PUSH_SRC, - _do_init); - -static guint cdparanoia_signals[LAST_SIGNAL] = { 0 }; - -/* our two formats */ -static GstFormat track_format; -static GstFormat sector_format; - -static void -cdparanoia_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&cdparanoia_src_template)); - gst_element_class_set_details (element_class, &cdparanoia_details); - - /* Register the track and sector format */ - track_format = gst_format_register ("track", "CD track"); - sector_format = gst_format_register ("sector", "CD sector"); -} - -static void -cdparanoia_class_init (CDParanoiaClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSrcClass *gstbasesrc_class; - GstPushSrcClass *gstpushsrc_class; - char *success = strerror_tr[0]; - - success = NULL; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstpushsrc_class = (GstPushSrcClass *) klass; - - parent_class = g_type_class_ref (GST_TYPE_PUSH_SRC); - - gobject_class->set_property = cdparanoia_set_property; - gobject_class->get_property = cdparanoia_get_property; - gobject_class->finalize = cdparanoia_finalize; - - cdparanoia_signals[SMILIE_CHANGE] = - g_signal_new ("smilie-change", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CDParanoiaClass, smilie_change), NULL, - NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); - cdparanoia_signals[TRANSPORT_ERROR] = - g_signal_new ("transport-error", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CDParanoiaClass, transport_error), - NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - cdparanoia_signals[UNCORRECTED_ERROR] = - g_signal_new ("uncorrected-error", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CDParanoiaClass, uncorrected_error), - NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE, - g_param_spec_string ("device", "Device", - "CD device location", DEFAULT_DEVICE, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GENERIC_DEVICE, - g_param_spec_string ("generic_device", "Generic device", - "Use specified generic scsi device", DEFAULT_GENERIC_DEVICE, - G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEFAULT_SECTORS, - g_param_spec_int ("default_sectors", "Default sectors", - "Force default number of sectors in read to n sectors", -1, 100, - DEFAULT_DEFAULT_SECTORS, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH_OVERLAP, - g_param_spec_int ("search_overlap", "Search overlap", - "Force minimum overlap search during verification to n sectors", -1, - 75, DEFAULT_SEARCH_OVERLAP, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ENDIAN, - g_param_spec_enum ("endian", "Endian", "Force endian on drive", - GST_TYPE_PARANOIA_ENDIAN, DEFAULT_ENDIAN, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED, - g_param_spec_int ("read_speed", "Read speed", - "Read from device at specified speed", G_MININT, G_MAXINT, - DEFAULT_READ_SPEED, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TOC_OFFSET, - g_param_spec_int ("toc_offset", "TOC offset", - "Add sectors to the values reported", G_MININT, G_MAXINT, - DEFAULT_TOC_OFFSET, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TOC_BIAS, - g_param_spec_boolean ("toc_bias", "TOC bias", - "Assume that the beginning offset of track 1 as reported in the TOC " - "will be addressed as LBA 0. Necessary for some Toshiba drives to " - "get track boundaries", DEFAULT_TOC_BIAS, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NEVER_SKIP, - g_param_spec_int ("never_skip", "Never skip", - "never accept any less than perfect data reconstruction (don't allow " - "'V's) but if [n] is given, skip after [n] retries without progress.", - 0, G_MAXINT, DEFAULT_NEVER_SKIP, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ABORT_ON_SKIP, - g_param_spec_boolean ("abort_on_skip", "Abort on skip", - "Abort on imperfect reads/skips", DEFAULT_ABORT_ON_SKIP, - G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARANOIA_MODE, - g_param_spec_enum ("paranoia_mode", "Paranoia mode", - "Type of checking to perform", GST_TYPE_PARANOIA_MODE, 0, - G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DISCID, - g_param_spec_string ("discid", "discid", "The dics id", DEFAULT_DISCID, - G_PARAM_READABLE)); - - /* tags */ - gst_tag_register ("discid", GST_TAG_FLAG_META, G_TYPE_STRING, - _("discid"), _("CDDA discid for metadata retrieval"), - gst_tag_merge_use_first); - - gstelement_class->set_index = GST_DEBUG_FUNCPTR (cdparanoia_set_index); - gstelement_class->get_index = GST_DEBUG_FUNCPTR (cdparanoia_get_index); - - gstbasesrc_class->start = GST_DEBUG_FUNCPTR (cdparanoia_start); - gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (cdparanoia_stop); - gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (cdparanoia_is_seekable); - gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (cdparanoia_do_seek); - gstbasesrc_class->query = GST_DEBUG_FUNCPTR (cdparanoia_query); - - gstpushsrc_class->create = GST_DEBUG_FUNCPTR (cdparanoia_create); -} - -static void -cdparanoia_init (CDParanoia * cdparanoia, CDParanoiaClass * klass) -{ - gst_pad_set_query_type_function (GST_BASE_SRC_PAD (cdparanoia), - GST_DEBUG_FUNCPTR (cdparanoia_get_query_types)); - - /* we're not live and we operate in time */ - gst_base_src_set_format (GST_BASE_SRC (cdparanoia), GST_FORMAT_TIME); - gst_base_src_set_live (GST_BASE_SRC (cdparanoia), FALSE); - - cdparanoia->device = g_strdup (DEFAULT_DEVICE); - cdparanoia->generic_device = g_strdup (DEFAULT_GENERIC_DEVICE); - cdparanoia->default_sectors = DEFAULT_DEFAULT_SECTORS; - cdparanoia->search_overlap = DEFAULT_SEARCH_OVERLAP; - cdparanoia->endian = DEFAULT_ENDIAN; - cdparanoia->read_speed = DEFAULT_READ_SPEED; - cdparanoia->toc_offset = DEFAULT_TOC_OFFSET; - cdparanoia->toc_bias = DEFAULT_TOC_BIAS; - cdparanoia->never_skip = DEFAULT_NEVER_SKIP; - cdparanoia->paranoia_mode = 2; - cdparanoia->abort_on_skip = DEFAULT_ABORT_ON_SKIP; - - cdparanoia->total_seconds = 0; - cdparanoia->uri = NULL; - cdparanoia->uri_track = -1; - cdparanoia->seek_request = -1; -} - -static void -cdparanoia_finalize (GObject * obj) -{ - CDParanoia *cdparanoia = CDPARANOIA (obj); - - g_free (cdparanoia->uri); - cdparanoia->uri = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -cdparanoia_set_property (GObject * object, guint prop_id, const GValue * value, - GParamSpec * pspec) -{ - CDParanoia *src; - - g_return_if_fail (GST_IS_CDPARANOIA (object)); - - src = CDPARANOIA (object); - - switch (prop_id) { - case PROP_DEVICE: - g_free (src->device); - /* clear the filename if we get a NULL (is that possible?) */ - if (!g_ascii_strcasecmp (g_value_get_string (value), "")) - src->device = NULL; - /* otherwise set the new filename */ - else - src->device = g_strdup (g_value_get_string (value)); - break; - case PROP_GENERIC_DEVICE: - - if (src->generic_device) - g_free (src->generic_device); - /* reset the device if we get a NULL (is that possible?) */ - if (!g_ascii_strcasecmp (g_value_get_string (value), "")) - src->generic_device = NULL; - /* otherwise set the new filename */ - else - src->generic_device = g_strdup (g_value_get_string (value)); - break; - case PROP_DEFAULT_SECTORS: - src->default_sectors = g_value_get_int (value); - break; - case PROP_SEARCH_OVERLAP: - src->search_overlap = g_value_get_int (value); - break; - case PROP_ENDIAN: - src->endian = g_value_get_enum (value); - break; - case PROP_READ_SPEED: - src->read_speed = g_value_get_int (value); - break; - case PROP_TOC_OFFSET: - src->toc_offset = g_value_get_int (value); - break; - case PROP_TOC_BIAS: - src->toc_bias = g_value_get_boolean (value); - break; - case PROP_NEVER_SKIP: - src->never_skip = g_value_get_int (value); - break; - case PROP_ABORT_ON_SKIP: - src->abort_on_skip = g_value_get_boolean (value); - break; - case PROP_PARANOIA_MODE: - src->paranoia_mode = g_value_get_enum (value); - break; - default: - break; - } - -} - -static void -cdparanoia_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - CDParanoia *src; - - g_return_if_fail (GST_IS_CDPARANOIA (object)); - - src = CDPARANOIA (object); - - switch (prop_id) { - case PROP_DEVICE: - g_value_set_string (value, src->device); - break; - case PROP_GENERIC_DEVICE: - g_value_set_string (value, src->generic_device); - break; - case PROP_DEFAULT_SECTORS: - g_value_set_int (value, src->default_sectors); - break; - case PROP_SEARCH_OVERLAP: - g_value_set_int (value, src->search_overlap); - break; - case PROP_ENDIAN: - g_value_set_enum (value, src->endian); - break; - case PROP_READ_SPEED: - g_value_set_int (value, src->read_speed); - break; - case PROP_TOC_OFFSET: - g_value_set_int (value, src->toc_offset); - break; - case PROP_TOC_BIAS: - g_value_set_boolean (value, src->toc_bias); - break; - case PROP_NEVER_SKIP: - g_value_set_int (value, src->never_skip); - break; - case PROP_ABORT_ON_SKIP: - g_value_set_boolean (value, src->abort_on_skip); - break; - case PROP_PARANOIA_MODE: - g_value_set_enum (value, src->paranoia_mode); - break; - case PROP_DISCID: - /* - * Due to possible autocorrections of start sectors of audio tracks on - * multisession cds, we can maybe not compute the correct discid. - * So issue a warning. - * See cdparanoia/interface/common-interface.c:FixupTOC - */ - if (src->d && src->d->cd_extra) - g_warning - ("DiscID on multisession discs might be broken. Use at own risk."); - g_value_set_string (value, src->discid); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -cdparanoia_do_seek (GstBaseSrc * bsrc, GstSegment * segment) -{ - CDParanoia *src; - gboolean res; - GstClockTime time; - gint64 start_sec, end_sec; - - src = CDPARANOIA (bsrc); - - time = segment->time = segment->start; - res = cdparanoia_convert (src, GST_FORMAT_TIME, time, §or_format, - &start_sec); - src->segment_start_sector = start_sec; - - if (segment->stop != -1) { - res &= cdparanoia_convert (src, GST_FORMAT_TIME, segment->stop, - §or_format, &end_sec); - src->segment_end_sector = end_sec; - } else { - src->segment_end_sector = src->last_sector; - } - - src->cur_sector = src->segment_start_sector; - paranoia_seek (src->p, src->cur_sector, SEEK_SET); - GST_DEBUG_OBJECT (src, "successfully seek'd to sector %d", src->cur_sector); - - return res; -} - -static gboolean -cdparanoia_is_seekable (GstBaseSrc * bsrc) -{ - /* we're seekable */ - return TRUE; -} - -static void -cdparanoia_callback (long inpos, int function) -{ -} - -static GstFlowReturn -cdparanoia_create (GstPushSrc * pushsrc, GstBuffer ** buffer) -{ - CDParanoia *src; - GstBuffer *buf; - gint16 *cdda_buf; - gint64 timestamp; - GstFormat format; - - src = CDPARANOIA (pushsrc); - - /* stop things apropriatly */ - if (src->cur_sector > src->segment_end_sector) - goto eos; - - /* convert the sequence sector number to a timestamp */ - format = GST_FORMAT_TIME; - timestamp = 0LL; - cdparanoia_convert (src, sector_format, src->cur_sector, &format, ×tamp); - - /* read a sector */ - cdda_buf = paranoia_read (src->p, cdparanoia_callback); - - /* have to copy the buffer for now since we don't own it... */ - /* FIXME must ask monty about allowing ownership transfer */ - buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW); - memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW); - GST_BUFFER_TIMESTAMP (buf) = timestamp; - cdparanoia_convert (src, GST_FORMAT_BYTES, - CD_FRAMESIZE_RAW, &format, ×tamp); - GST_BUFFER_DURATION (buf) = timestamp; - gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); - - GST_DEBUG_OBJECT (src, "pushing sector %d with timestamp %" GST_TIME_FORMAT, - src->cur_sector, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); - - /* update current sector */ - src->cur_sector++; - - *buffer = buf; - - /* we're done, push the buffer off now */ - return GST_FLOW_OK; - -eos: - { - GST_DEBUG_OBJECT (src, "reached EOS"); - return GST_FLOW_UNEXPECTED; - } -} - -/* need some stuff to get a discid (cdparanoia doesn't do cddb but lets - * not stop other ppl doing it ;-) */ -typedef int byte; - -typedef struct -{ - byte m; - byte s; - byte f; -} -toc_msf; - -/* cdparanoia provides the toc in lba format dang we need it in msf so - * we have to convert it */ -static inline void -lba_to_msf (const gint lba, byte * m, byte * s, byte * f) -{ - gint lba2 = lba; - - lba2 += CD_MSF_OFFSET; - lba2 &= 0xffffff; - *m = lba2 / (CD_SECS * CD_FRAMES); - lba2 %= (CD_SECS * CD_FRAMES); - *s = lba2 / CD_FRAMES; - *f = lba2 % CD_FRAMES; - *f += (*m) * 60 * 75; - *f += (*s) * 75; -} - -static void -lba_toc_to_msf_toc (TOC * lba_toc, toc_msf * msf_toc, gint tracks) -{ - gint i; - - for (i = 0; i <= tracks; i++) - lba_to_msf (lba_toc[i].dwStartSector, &msf_toc[i].m, &msf_toc[i].s, - &msf_toc[i].f); -} - -/* the cddb hash function */ -static guint -cddb_sum (gint n) -{ - guint ret; - - ret = 0; - while (n > 0) { - ret += (n % 10); - n /= 10; - } - return ret; -} - -static void -cddb_discid (gchar * discid, toc_msf * toc, gint tracks) -{ - guint i = 0, t = 0, n = 0; - - while (i < tracks) { - n = n + cddb_sum ((toc[i].m * 60) + toc[i].s); - i++; - } - t = ((toc[tracks].m * 60) + toc[tracks].s) - ((toc[0].m * 60) - + toc[0].s); - sprintf (discid, "%08x", ((n % 0xff) << 24 | t << 8 | tracks)); -} - -/* get all the cddb info at once */ -static void -get_cddb_info (TOC * toc, gint tracks, gchar * discid, gint64 * offsets, - gint64 * total_seconds) -{ - toc_msf msf_toc[MAXTRK]; - gint i; - gint64 *p = offsets; - - lba_toc_to_msf_toc (toc, &msf_toc[0], tracks); - cddb_discid (discid, &msf_toc[0], tracks); - - for (i = 0; i < tracks; i++) { - *p++ = msf_toc[i].f; - } - - *total_seconds = msf_toc[tracks].f / 75; - -} - -static void -add_index_associations (CDParanoia * src) -{ - int i; - - for (i = 0; i < src->d->tracks; i++) { - gint64 sector; - - sector = cdda_track_firstsector (src->d, i + 1); - gst_index_add_association (src->index, src->index_id, - GST_ASSOCIATION_FLAG_KEY_UNIT, - track_format, i, - sector_format, sector, - GST_FORMAT_TIME, - (gint64) (((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100), - GST_FORMAT_BYTES, (gint64) (sector << 2), GST_FORMAT_DEFAULT, - (gint64) ((CD_FRAMESIZE_RAW >> 2) * sector), NULL); -#if 0 - g_print ("Added association for track %d\n", i + 1); - g_print ("Sector: %lld\n", sector); - g_print ("Time: %lld\n", - (gint64) (((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100)); - g_print ("Bytes: %lld\n", (gint64) (sector << 2)); - g_print ("Units: %lld\n", (gint64) ((CD_FRAMESIZE_RAW >> 2) * sector)); - g_print ("-----------\n"); -#endif - } -} - -/* open the file, necessary to go to RUNNING state */ -static gboolean -cdparanoia_start (GstBaseSrc * bsrc) -{ - GstTagList *taglist; - gint i; - gint paranoia_mode; - CDParanoia *src; - - src = CDPARANOIA (bsrc); - - GST_DEBUG_OBJECT (src, "trying to open device..."); - - /* find the device */ - if (src->generic_device != NULL) { - src->d = cdda_identify_scsi (src->generic_device, src->device, FALSE, NULL); - } else { - if (src->device != NULL) { - src->d = cdda_identify (src->device, FALSE, NULL); - } else { - src->d = cdda_identify ("/dev/cdrom", FALSE, NULL); - } - } - - /* fail if the device couldn't be found */ - if (src->d == NULL) - goto no_device; - - /* set verbosity mode */ - cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); - - /* set various other parameters */ - if (src->default_sectors != -1) { - src->d->nsectors = src->default_sectors; - src->d->bigbuff = src->default_sectors * CD_FRAMESIZE_RAW; - } - - /* open the disc */ - if (cdda_open (src->d)) - goto open_failed; - - /* I don't like this here i would prefer it under get_cddb_info but for somereason - * when leaving the function it clobbers the allocated mem and all is lost bugger - */ - get_cddb_info (&src->d->disc_toc[0], src->d->tracks, src->discid, - src->offsets, &src->total_seconds); - - g_object_freeze_notify (G_OBJECT (src)); - g_object_notify (G_OBJECT (src), "discid"); - g_object_thaw_notify (G_OBJECT (src)); - - taglist = gst_tag_list_new (); - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, "discid", src->discid, NULL); - gst_element_found_tags (GST_ELEMENT (src), taglist); - /* no need to forward, because discid is useless to other elements */ - - if (src->toc_bias) { - src->toc_offset -= cdda_track_firstsector (src->d, 1); - } - for (i = 0; i < src->d->tracks + 1; i++) { - src->d->disc_toc[i].dwStartSector += src->toc_offset; - } - - if (src->read_speed != -1) { - cdda_speed_set (src->d, src->read_speed); - } - - /* save these ones - skip lead-in */ - src->first_sector = cdda_track_firstsector (src->d, 1); - src->last_sector = cdda_disc_lastsector (src->d); - - /* this is the default segment we will play */ - src->segment_start_sector = src->first_sector; - src->segment_end_sector = src->last_sector; - - /* create the paranoia struct and set it up */ - src->p = paranoia_init (src->d); - if (src->p == NULL) - goto init_failed; - - paranoia_mode = src->paranoia_mode; - if (src->never_skip) - paranoia_mode |= PARANOIA_MODE_NEVERSKIP; - - paranoia_modeset (src->p, paranoia_mode); - - if (src->search_overlap != -1) - paranoia_overlapset (src->p, src->search_overlap); - - if (src->index && GST_INDEX_IS_WRITABLE (src->index)) - add_index_associations (src); - - { - GstFormat format; - gint64 duration; - - format = GST_FORMAT_TIME; - - if (!cdparanoia_convert (src, - sector_format, src->last_sector + 1 - src->first_sector, - &format, &duration)) - duration = -1; - - gst_segment_set_duration (&bsrc->segment, format, duration); - } - - GST_DEBUG_OBJECT (src, "device successfully openend"); - - return TRUE; - - /* ERRORS */ -no_device: - { - GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, - (_("Could not open CD device for reading.")), ("cdda_identify failed")); - return FALSE; - } -open_failed: - { - GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, - (_("Could not open CD device for reading.")), ("cdda_open failed")); - cdda_close (src->d); - src->d = NULL; - return FALSE; - } -init_failed: - { - GST_ELEMENT_ERROR (src, LIBRARY, INIT, - ("failed to initialize paranoia"), ("failed to initialize paranoia")); - return FALSE; - } -} - -/* close the file */ -static gboolean -cdparanoia_stop (GstBaseSrc * bsrc) -{ - CDParanoia *src; - - src = CDPARANOIA (bsrc); - - /* kill the paranoia state */ - paranoia_free (src->p); - src->p = NULL; - - src->total_seconds = 0LL; - /* close the disc */ - cdda_close (src->d); - src->d = NULL; - - return TRUE; -} - -#if 0 -static const GstFormat * -cdparanoia_get_formats (GstPad * pad) -{ - static GstFormat formats[] = { - GST_FORMAT_TIME, - GST_FORMAT_BYTES, - GST_FORMAT_DEFAULT, - 0, /* filled later */ - 0, /* filled later */ - 0 - }; - - formats[3] = track_format; - formats[4] = sector_format; - - return formats; -} -#endif - -static gboolean -cdparanoia_convert (CDParanoia * src, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - - switch (src_format) { - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_BYTES: - src_value <<= 2; /* 4 bytes per sample */ - case GST_FORMAT_DEFAULT: - *dest_value = - gst_util_uint64_scale_int (src_value, 44100, GST_SECOND); - break; - default: - if (*dest_format == track_format || *dest_format == sector_format) { - gint sector = gst_util_uint64_scale (src_value, 44100, - (CD_FRAMESIZE_RAW >> 2) * GST_SECOND); - - if (*dest_format == sector_format) { - *dest_value = sector; - } else { - *dest_value = cdda_sector_gettrack (src->d, sector) - 1; - } - } else - goto error; - break; - } - break; - case GST_FORMAT_BYTES: - src_value >>= 2; - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_BYTES: - *dest_value = src_value * 4; - break; - case GST_FORMAT_TIME: - *dest_value = - gst_util_uint64_scale_int (src_value, GST_SECOND, 44100); - break; - default: - if (*dest_format == track_format || *dest_format == sector_format) { - gint sector = src_value / (CD_FRAMESIZE_RAW >> 2); - - if (*dest_format == track_format) { - *dest_value = cdda_sector_gettrack (src->d, sector) - 1; - } else { - *dest_value = sector; - } - } else - goto error; - break; - } - break; - default: - { - gint64 sector; - - if (src_format == track_format) { - /* some sanity checks */ - if (src_value < 0 || src_value > src->d->tracks) - goto error; - - sector = cdda_track_firstsector (src->d, src_value + 1); - } else if (src_format == sector_format) { - sector = src_value; - } else - goto error; - - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = ((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100; - break; - case GST_FORMAT_BYTES: - sector <<= 2; - case GST_FORMAT_DEFAULT: - *dest_value = (CD_FRAMESIZE_RAW >> 2) * sector; - break; - default: - if (*dest_format == sector_format) { - *dest_value = sector; - } else if (*dest_format == track_format) { - /* if we go past the last sector, make sure to report the last track */ - if (sector > src->last_sector - src->first_sector) - *dest_value = cdda_sector_gettrack (src->d, src->last_sector); - else - *dest_value = cdda_sector_gettrack (src->d, - sector + src->first_sector) - 1; - } else - goto error; - break; - } - break; - } - } -done: - return res; - -error: - { - GST_DEBUG_OBJECT (src, "convert failed"); - res = FALSE; - goto done; - } -} - -static const GstQueryType * -cdparanoia_get_query_types (GstPad * pad) -{ - static const GstQueryType src_query_types[] = { - GST_QUERY_DURATION, - GST_QUERY_POSITION, - GST_QUERY_SEGMENT, - 0 - }; - - return src_query_types; -} - -static gboolean -cdparanoia_query (GstBaseSrc * bsrc, GstQuery * query) -{ - gboolean res = TRUE; - CDParanoia *src; - - src = CDPARANOIA (bsrc); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL); - res = cdparanoia_convert (src, src_fmt, src_val, &dest_fmt, &dest_val); - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - } - default: - res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); - break; - } - return res; -} - -static void -cdparanoia_set_index (GstElement * element, GstIndex * index) -{ - CDParanoia *cdparanoia; - - cdparanoia = CDPARANOIA (element); - - cdparanoia->index = index; - - gst_index_get_writer_id (index, GST_OBJECT (cdparanoia), - &cdparanoia->index_id); - gst_index_add_format (index, cdparanoia->index_id, track_format); - gst_index_add_format (index, cdparanoia->index_id, sector_format); -} - -static GstIndex * -cdparanoia_get_index (GstElement * element) -{ - CDParanoia *cdparanoia; - - cdparanoia = CDPARANOIA (element); - - return cdparanoia->index; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "cdparanoia", GST_RANK_NONE, - GST_TYPE_CDPARANOIA)) - return FALSE; - - return TRUE; -} - -/* GSTURIHANDLER INTERFACE *************************************************/ - -static guint -cdparanoia_uri_get_type (void) -{ - return GST_URI_SRC; -} -static gchar ** -cdparanoia_uri_get_protocols (void) -{ - static gchar *protocols[] = { "cdda", NULL }; - - return protocols; -} -static const gchar * -cdparanoia_uri_get_uri (GstURIHandler * handler) -{ - CDParanoia *cdparanoia = CDPARANOIA (handler); - - return cdparanoia->uri; -} - -static gboolean -cdparanoia_uri_set_uri (GstURIHandler * handler, const gchar * uri) -{ - gchar *protocol, *location; - - CDParanoia *cdparanoia = CDPARANOIA (handler); - - protocol = gst_uri_get_protocol (uri); - if (strcmp (protocol, "cdda") != 0) - goto invalid_proto; - g_free (protocol); - - location = gst_uri_get_location (uri); - cdparanoia->uri_track = strtol (location, NULL, 10); - if (cdparanoia->uri_track > 0) { - cdparanoia->seek_request = cdparanoia->uri_track; - } - g_free (location); - - return TRUE; - - /* ERRORS */ -invalid_proto: - { - g_free (protocol); - return FALSE; - } -} - -static void -cdparanoia_uri_handler_init (gpointer g_iface, gpointer iface_data) -{ - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; - - iface->get_type = cdparanoia_uri_get_type; - iface->get_protocols = cdparanoia_uri_get_protocols; - iface->get_uri = cdparanoia_uri_get_uri; - iface->set_uri = cdparanoia_uri_set_uri; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "cdparanoia", - "Read audio from CD in paranoid mode", - plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/cdparanoia/gstcdparanoia.h b/ext/cdparanoia/gstcdparanoia.h deleted file mode 100644 index 4b664a8..0000000 --- a/ext/cdparanoia/gstcdparanoia.h +++ /dev/null @@ -1,122 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __CDPARANOIA_H__ -#define __CDPARANOIA_H__ - - -#include -#include -#include - -G_BEGIN_DECLS - -#define size16 gint16 -#define size32 gint32 - -#ifdef CDPARANOIA_HEADERS_IN_DIR - #include - #include -#else - #include - #include -#endif - -/*#define CDPARANOIA_BASEOFFSET 0xf1d2 */ -#define CDPARANOIA_BASEOFFSET 0x0 - -#define GST_TYPE_CDPARANOIA \ - (cdparanoia_get_type()) -#define CDPARANOIA(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CDPARANOIA,CDParanoia)) -#define CDPARANOIA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CDPARANOIA,CDParanoiaClass)) -#define GST_IS_CDPARANOIA(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CDPARANOIA)) -#define GST_IS_CDPARANOIA_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDPARANOIA)) - -typedef struct _CDParanoia CDParanoia; -typedef struct _CDParanoiaClass CDParanoiaClass; - -/** - * CDParanoia: - * - * Opaque #CDParanoia structure - */ -struct _CDParanoia { - GstPushSrc pushsrc; - - /*< private >*/ - - /* Index */ - GstIndex *index; - int index_id; - - gchar *device; - gchar *generic_device; - gint default_sectors; - gint search_overlap; - gint endian; - gint read_speed; - gint toc_offset; - gboolean toc_bias; - gint never_skip; - gboolean abort_on_skip; - gint paranoia_mode; - gchar *uri; /* URI caching */ - gint uri_track; - gint seek_request; - - cdrom_drive *d; - cdrom_paranoia *p; - - gint cur_sector; - gint segment_start_sector; - gint segment_end_sector; - - gint first_sector; - gint last_sector; - - gchar discid[20]; - gint64 offsets[MAXTRK]; - gint64 total_seconds; - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -struct _CDParanoiaClass { - GstPushSrcClass parent_class; - - /* signal callbacks */ - void (*smilie_change) (CDParanoia *cdparanoia, gchar *smilie); - void (*transport_error) (CDParanoia *cdparanoia, gint offset); - void (*uncorrected_error) (CDParanoia *cdparanoia, gint offset); - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -GType cdparanoia_get_type(void); - -G_END_DECLS - -#endif /* __CDPARANOIA_H__ */ diff --git a/ext/cdparanoia/gstcdparanoiasrc.c b/ext/cdparanoia/gstcdparanoiasrc.c new file mode 100644 index 0000000..dfc7589 --- /dev/null +++ b/ext/cdparanoia/gstcdparanoiasrc.c @@ -0,0 +1,398 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * <2005> Wim Taymans + * <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstcdparanoiasrc.h" +#include "gst/gst-i18n-plugin.h" + +enum +{ + PROP_0, + PROP_READ_SPEED, + PROP_PARANOIA_MODE, + PROP_SEARCH_OVERLAP, + PROP_GENERIC_DEVICE +}; + +#define DEFAULT_READ_SPEED -1 +#define DEFAULT_SEARCH_OVERLAP -1 +#define DEFAULT_PARANOIA_MODE PARANOIA_MODE_FRAGMENT +#define DEFAULT_GENERIC_DEVICE NULL + +GST_DEBUG_CATEGORY_STATIC (gst_cd_paranoia_src_debug); +#define GST_CAT_DEFAULT gst_cd_paranoia_src_debug + +GST_BOILERPLATE (GstCdParanoiaSrc, gst_cd_paranoia_src, GstCddaBaseSrc, + GST_TYPE_CDDA_BASE_SRC); + +static void gst_cd_paranoia_src_finalize (GObject * obj); +static void gst_cd_paranoia_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_cd_paranoia_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static GstBuffer *gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * src, + gint sector); +static gboolean gst_cd_paranoia_src_open (GstCddaBaseSrc * src, + const gchar * device); +static void gst_cd_paranoia_src_close (GstCddaBaseSrc * src); + +static GstElementDetails cdparanoia_details = { + "CD Audio (cdda) Source, Paranoia IV", + "Source/File", + "Read audio from CD in paranoid mode", + "Erik Walthinsen , " "Wim Taymans " +}; + +#define GST_TYPE_CD_PARANOIA_MODE (gst_cd_paranoia_mode_get_type()) +static GType +gst_cd_paranoia_mode_get_type (void) +{ + static const GFlagsValue paranoia_modes[] = { + {PARANOIA_MODE_DISABLE, "PARANOIA_MODE_DISABLE", "disable"}, + {PARANOIA_MODE_FRAGMENT, "PARANOIA_MODE_FRAGMENT", "fragment"}, + {PARANOIA_MODE_OVERLAP, "PARANOIA_MODE_OVERLAP", "overlap"}, + {PARANOIA_MODE_SCRATCH, "PARANOIA_MODE_SCRATCH", "scratch"}, + {PARANOIA_MODE_REPAIR, "PARANOIA_MODE_REPAIR", "repair"}, + {PARANOIA_MODE_FULL, "PARANOIA_MODE_FULL", "full"}, + {0, NULL, NULL}, + }; + + static GType type; /* 0 */ + + if (!type) { + type = g_flags_register_static ("GstCdParanoiaMode", paranoia_modes); + } + + return type; +} + +static void +gst_cd_paranoia_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &cdparanoia_details); + + GST_DEBUG_CATEGORY_INIT (gst_cd_paranoia_src_debug, "cdparanoiasrc", 0, + "CD Paranoia Source"); +} + +static void +gst_cd_paranoia_src_init (GstCdParanoiaSrc * src, GstCdParanoiaSrcClass * klass) +{ + src->d = NULL; + src->p = NULL; + src->next_sector = -1; + + src->search_overlap = DEFAULT_SEARCH_OVERLAP; + src->paranoia_mode = DEFAULT_PARANOIA_MODE; + src->read_speed = DEFAULT_READ_SPEED; + src->generic_device = g_strdup (DEFAULT_GENERIC_DEVICE); +} + +static void +gst_cd_paranoia_src_class_init (GstCdParanoiaSrcClass * klass) +{ + GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_cd_paranoia_src_set_property; + gobject_class->get_property = gst_cd_paranoia_src_get_property; + gobject_class->finalize = gst_cd_paranoia_src_finalize; + + cddabasesrc_class->open = gst_cd_paranoia_src_open; + cddabasesrc_class->close = gst_cd_paranoia_src_close; + cddabasesrc_class->read_sector = gst_cd_paranoia_src_read_sector; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GENERIC_DEVICE, + g_param_spec_string ("generic-device", "Generic device", + "Use specified generic scsi device", DEFAULT_GENERIC_DEVICE, + G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED, + g_param_spec_int ("read-speed", "Read speed", + "Read from device at specified speed", -1, G_MAXINT, + DEFAULT_READ_SPEED, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARANOIA_MODE, + g_param_spec_flags ("paranoia-mode", "Paranoia mode", + "Type of checking to perform", GST_TYPE_CD_PARANOIA_MODE, + DEFAULT_PARANOIA_MODE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH_OVERLAP, + g_param_spec_int ("search-overlap", "Search overlap", + "Force minimum overlap search during verification to n sectors", -1, + 75, DEFAULT_SEARCH_OVERLAP, G_PARAM_READWRITE)); +} + +static gboolean +gst_cd_paranoia_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + gint i; + + GST_DEBUG_OBJECT (src, "trying to open device %s (generic-device=%s) ...", + device, GST_STR_NULL (src->generic_device)); + + /* find the device */ + if (src->generic_device != NULL) { + src->d = cdda_identify_scsi (src->generic_device, device, FALSE, NULL); + } else { + if (device != NULL) { + src->d = cdda_identify (device, FALSE, NULL); + } else { + src->d = cdda_identify ("/dev/cdrom", FALSE, NULL); + } + } + + /* fail if the device couldn't be found */ + if (src->d == NULL) + goto no_device; + + /* set verbosity mode */ + cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); + + /* open the disc */ + if (cdda_open (src->d)) + goto open_failed; + + if (src->read_speed != -1) { + cdda_speed_set (src->d, src->read_speed); + } + + for (i = 1; i < src->d->tracks + 1; i++) { + GstCddaBaseSrcTrack track = { 0, }; + + track.num = i; + track.is_audio = IS_AUDIO (src->d, i - 1); + track.start = cdda_track_firstsector (src->d, i); + track.end = cdda_track_lastsector (src->d, i); + track.tags = NULL; + + gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track); + } + + /* create the paranoia struct and set it up */ + src->p = paranoia_init (src->d); + if (src->p == NULL) + goto init_failed; + + paranoia_modeset (src->p, src->paranoia_mode); + + if (src->search_overlap != -1) + paranoia_overlapset (src->p, src->search_overlap); + + src->next_sector = -1; + + return TRUE; + + /* ERRORS */ +no_device: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not open CD device for reading.")), ("cdda_identify failed")); + return FALSE; + } +open_failed: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not open CD device for reading.")), ("cdda_open failed")); + cdda_close (src->d); + src->d = NULL; + return FALSE; + } +init_failed: + { + GST_ELEMENT_ERROR (src, LIBRARY, INIT, + ("failed to initialize paranoia"), ("failed to initialize paranoia")); + return FALSE; + } +} + +static void +gst_cd_paranoia_src_close (GstCddaBaseSrc * cddabasesrc) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + + paranoia_free (src->p); + src->p = NULL; + + cdda_close (src->d); + src->d = NULL; + + src->next_sector = -1; +} + +static void +gst_cd_paranoia_paranoia_callback (long inpos, int function) +{ + /* do nothing for now, maybe emit signals later */ +} + +static GstBuffer * +gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + GstBuffer *buf; + gint16 *cdda_buf; + +#if 0 + /* Do we really need to output this? (tpm) */ + /* Due to possible autocorrections of start sectors of audio tracks on + * multisession cds, we can maybe not compute the correct discid. + * So issue a warning. + * See cdparanoia/interface/common-interface.c:FixupTOC */ + if (src->d && src->d->cd_extra) { + g_message + ("DiscID on multisession discs might be broken. Use at own risk."); + } +#endif + + if (src->next_sector == -1 || src->next_sector != sector) { + if (paranoia_seek (src->p, sector, SEEK_SET) == -1) { + GST_WARNING_OBJECT (src, "seek to sector %d failed!", sector); + GST_ELEMENT_ERROR (src, RESOURCE, SEEK, + (_("Could not seek CD.")), + ("paranoia_seek to %d failed: %s", sector, g_strerror (errno))); + return NULL; + } + GST_DEBUG_OBJECT (src, "successfully seeked to sector %d", sector); + src->next_sector = sector; + } + + cdda_buf = paranoia_read (src->p, gst_cd_paranoia_paranoia_callback); + + if (cdda_buf == NULL) { + GST_WARNING_OBJECT (src, "read at sector %d failed!", sector); + GST_ELEMENT_ERROR (src, RESOURCE, READ, + (_("Could not read CD.")), + ("paranoia_read at %d failed: %s", sector, g_strerror (errno))); + return NULL; + } + + buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW); + memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW); + + /* cdda base class will take care of timestamping etc. */ + ++src->next_sector; + + return buf; +} + +static void +gst_cd_paranoia_src_finalize (GObject * obj) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (obj); + + g_free (src->generic_device); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_cd_paranoia_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case PROP_GENERIC_DEVICE:{ + g_free (src->generic_device); + src->generic_device = g_value_dup_string (value); + if (src->generic_device && src->generic_device[0] == '\0') { + g_free (src->generic_device); + src->generic_device = NULL; + } + break; + } + case PROP_READ_SPEED:{ + src->read_speed = g_value_get_int (value); + if (src->read_speed == 0) + src->read_speed = -1; + break; + } + case PROP_PARANOIA_MODE:{ + src->paranoia_mode = g_value_get_flags (value) & PARANOIA_MODE_FULL; + break; + } + case PROP_SEARCH_OVERLAP:{ + src->search_overlap = g_value_get_int (value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (src); +} + +static void +gst_cd_paranoia_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case PROP_READ_SPEED: + g_value_set_int (value, src->read_speed); + break; + case PROP_PARANOIA_MODE: + g_value_set_flags (value, src->paranoia_mode); + break; + case PROP_GENERIC_DEVICE: + g_value_set_string (value, src->generic_device); + break; + case PROP_SEARCH_OVERLAP: + g_value_set_int (value, src->search_overlap); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (src); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "cdparanoiasrc", GST_RANK_SECONDARY, + GST_TYPE_CD_PARANOIA_SRC)) + return FALSE; + + return TRUE; +} + + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "cdparanoia", + "Read audio from CD in paranoid mode", + plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/cdparanoia/gstcdparanoiasrc.h b/ext/cdparanoia/gstcdparanoiasrc.h new file mode 100644 index 0000000..a622588 --- /dev/null +++ b/ext/cdparanoia/gstcdparanoiasrc.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_CD_PARANOIA_SRC_H__ +#define __GST_CD_PARANOIA_SRC_H__ + +#include "gst/cdda/gstcddabasesrc.h" + +G_BEGIN_DECLS + +#define size16 gint16 +#define size32 gint32 + +#ifdef CDPARANOIA_HEADERS_IN_DIR + #include + #include +#else + #include + #include +#endif + +#define GST_TYPE_CD_PARANOIA_SRC (gst_cd_paranoia_src_get_type()) +#define GST_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrc)) +#define GST_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrcClass)) +#define GST_IS_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_PARANOIA_SRC)) +#define GST_IS_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_PARANOIA_SRC)) +#define GST_CD_PARANOIA_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdParanoiaSrcClass)) + +typedef struct _GstCdParanoiaSrc GstCdParanoiaSrc; +typedef struct _GstCdParanoiaSrcClass GstCdParanoiaSrcClass; + +struct _GstCdParanoiaSrc { + GstCddaBaseSrc cddabasesrc; + + /*< private >*/ + cdrom_drive *d; + cdrom_paranoia *p; + + gint next_sector; /* -1 or next sector we expect to + * read, so we know when to do a seek */ + + gint paranoia_mode; + gint read_speed; + gint search_overlap; + + gchar *generic_device; +}; + +struct _GstCdParanoiaSrcClass { + GstCddaBaseSrcClass parent_class; +}; + +GType gst_cd_paranoia_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_CD_PARANOIA_SRC_H__ */ + -- 2.7.4