15722N/A--- gst-plugins-good-0.10.13/configure.ac-orig 2009-01-23 10:02:53.003952000 -0600
15722N/A+++ gst-plugins-good-0.10.13/configure.ac 2009-01-23 10:03:03.048601000 -0600
20841N/A@@ -740,6 +740,24 @@ AG_GST_CHECK_FEATURE(CAIRO_GOBJECT,
20841N/A AG_GST_PKG_CHECK_MODULES(CAIRO_GOBJECT, cairo-gobject >= 1.10.0)
10819N/A ])
10819N/A
15635N/A+dnl *** cdda2wav ***
15635N/A+translit(dnm, m, l) AM_CONDITIONAL(USE_CDDA2WAV, true)
15635N/A+AG_GST_CHECK_FEATURE(CDDA2WAV, [HAL libraries], cdda2wav, [
15635N/A+ AG_GST_PKG_CHECK_MODULES(CDDA2WAV, [hal >= 0.5.8, hal-storage >= 0.5.8, dbus-1 >= 0.32])
15722N/A+ AC_PATH_PROG(CDDA2WAVBIN, cdda2wav, no)
15722N/A+ if test x$CDDA2WAVBIN = xno; then
15722N/A+ HAVE_CDDA2WAV="no"
15722N/A+ else
15722N/A+ CDDA_VERSION=`$CDDA2WAVBIN --version | grep Schilling`
15722N/A+ if test -z "$CDDA_VERSION"; then
15722N/A+ HAVE_CDDA2WAV="no"
15722N/A+ else
15722N/A+ HAVE_CDDA2WAV="yes"
15722N/A+ fi
15722N/A+ fi
15722N/A+ AC_SUBST(HAVE_CDDA2WAV)
10819N/A+])
10819N/A+
10819N/A dnl **** ESound ****
10819N/A translit(dnm, m, l) AM_CONDITIONAL(USE_ESD, true)
10819N/A AG_GST_CHECK_FEATURE(ESD, [ESounD sound daemon], esdsink, [
20841N/A@@ -1058,6 +1076,7 @@ AM_CONDITIONAL(USE_CAIRO_GOBJECT, false)
15256N/A AM_CONDITIONAL(USE_DIRECTSOUND, false)
15256N/A AM_CONDITIONAL(USE_DV1394, false)
14045N/A AM_CONDITIONAL(USE_ESD, false)
15635N/A+AM_CONDITIONAL(USE_CDDA2WAV, false)
10828N/A AM_CONDITIONAL(USE_FLAC, false)
10828N/A AM_CONDITIONAL(USE_GCONF, false)
15256N/A AM_CONDITIONAL(USE_GCONFTOOL, false)
20841N/A@@ -1194,6 +1213,7 @@ ext/Makefile
10819N/A ext/aalib/Makefile
10819N/A ext/annodex/Makefile
10819N/A ext/cairo/Makefile
15635N/A+ext/cdda2wav/Makefile
10819N/A ext/dv/Makefile
10819N/A ext/esd/Makefile
14045N/A ext/flac/Makefile
14045N/A--- gst-plugins-good-0.10.10/ext/Makefile.am-orig 2008-08-27 23:56:51.987944000 -0500
14045N/A+++ gst-plugins-good-0.10.10/ext/Makefile.am 2008-08-27 23:57:20.124741000 -0500
14045N/A@@ -16,6 +16,12 @@ else
14045N/A CAIRO_DIR =
10819N/A endif
10819N/A
15635N/A+if USE_CDDA2WAV
15635N/A+CDDA2WAV_DIR = cdda2wav
10819N/A+else
15635N/A+CDDA2WAV_DIR =
10819N/A+endif
10819N/A+
10819N/A if USE_ESD
10819N/A ESD_DIR = esd
10819N/A else
14045N/A@@ -131,6 +137,7 @@ SUBDIRS = \
10819N/A $(CAIRO_DIR) \
10819N/A $(DV1394_DIR) \
10819N/A $(ESD_DIR) \
15635N/A+ $(CDDA2WAV_DIR) \
10819N/A $(FLAC_DIR) \
14045N/A $(GCONF_DIR) \
14045N/A $(GDK_PIXBUF_DIR) \
12239N/A--- /dev/null 2007-03-19 01:47:57.000000000 +0800
15635N/A+++ gst-plugins-good-0.10.6/ext/cdda2wav/Makefile.am 2007-03-19 01:46:41.639278000 +0800
12239N/A@@ -0,0 +1,20 @@
15635N/A+plugin_LTLIBRARIES = libgstcdda2wav.la
12239N/A+
15635N/A+libgstcdda2wav_la_SOURCES = \
15635N/A+ gstcdda2wav.c
12239N/A+
15635N/A+libgstcdda2wav_la_CFLAGS = \
12239N/A+ $(GST_PLUGINS_BASE_CFLAGS) \
12239N/A+ $(GST_BASE_CFLAGS) \
12239N/A+ $(GST_CFLAGS) \
15635N/A+ $(CDDA2WAV_CFLAGS)
12239N/A+
15635N/A+libgstcdda2wav_la_LIBADD = \
12239N/A+ $(GST_PLUGINS_BASE_LIBS) -lgstcdda-$(GST_MAJORMINOR) \
12239N/A+ $(GST_BASE_LIBS) \
15635N/A+ $(CDDA2WAV_LIBS)
12239N/A+
15635N/A+libgstcdda2wav_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
12239N/A+
12239N/A+noinst_HEADERS = \
15635N/A+ gstcdda2wav.h
15635N/A--- /dev/null 2008-12-19 17:50:06.000000000 -0600
15635N/A+++ gst-plugins-good-0.10.6/ext/cdda2wav/gstcdda2wav.h 2008-07-17 07:48:57.000000000 -0500
15635N/A@@ -0,0 +1,72 @@
10819N/A+/* GStreamer
15635N/A+ * Copyright (C) 2007 Brian Cameron <Brian.Cameron@sun.com> and
10819N/A+ * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
16148N/A+ * Copyright (C) 2008 J�rg Schilling <Joerg.Schilling@fokus.fraunhofer.de>
10819N/A+ *
10819N/A+ * This library is free software; you can redistribute it and/or
10819N/A+ * modify it under the terms of the GNU Library General Public
10819N/A+ * License as published by the Free Software Foundation; either
10819N/A+ * version 2 of the License, or (at your option) any later version.
10819N/A+ *
10819N/A+ * This library is distributed in the hope that it will be useful,
10819N/A+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10819N/A+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10819N/A+ * Library General Public License for more details.
10819N/A+ *
10819N/A+ * You should have received a copy of the GNU Library General Public
10819N/A+ * License along with this library; if not, write to the
10819N/A+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10819N/A+ * Boston, MA 02111-1307, USA.
10819N/A+ */
10819N/A+
15635N/A+#ifndef __GST_CDDA2WAV_H__
15635N/A+#define __GST_CDDA2WAV_H__
10819N/A+
10819N/A+#include <sys/types.h>
10819N/A+#include "gst/cdda/gstcddabasesrc.h"
10819N/A+
15635N/A+#define CDDA2WAV_BSIZE 2352
15635N/A+
10819N/A+G_BEGIN_DECLS
10819N/A+
15635N/A+#define GST_TYPE_CDDA2WAV (gst_cdda2wav_get_type())
15635N/A+#define GST_CDDA2WAV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CDDA2WAV,GstCdda2Wav))
15635N/A+#define GST_CDDA2WAV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CDDA2WAV,GstCdda2WavClass))
15635N/A+#define GST_IS_CDDA2WAV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CDDA2WAV))
15635N/A+#define GST_IS_CDDA2WAV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDDA2WAV))
15635N/A+#define GST_CDDA2WAV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA2WAV, GstCdda2WavClass))
10819N/A+
15635N/A+typedef struct _GstCdda2Wav GstCdda2Wav;
15635N/A+typedef struct _GstCdda2WavClass GstCdda2WavClass;
10819N/A+
15635N/A+#define CDDA2WAV_BSIZE 2352
10819N/A+
10819N/A+/**
15635N/A+ * GstCdda2Wav::
10819N/A+ *
15635N/A+ * The cdda2wav object structure.
10819N/A+ */
15635N/A+struct _GstCdda2Wav {
10819N/A+ GstCddaBaseSrc cddabasesrc;
10819N/A+
10819N/A+ /*< private >*/
15635N/A+ FILE *cdda2wav_in;
15635N/A+ FILE *cdda2wav_out;
15635N/A+ FILE *cdda2wav_err;
15635N/A+ pid_t cdda2wav_pid;
10819N/A+ uint_t track_count;
10819N/A+ char **devices;
15635N/A+ char *current_device;
10819N/A+ boolean_t *has_audio;
10819N/A+};
10819N/A+
15635N/A+struct _GstCdda2WavClass {
10819N/A+ GstCddaBaseSrcClass parent_class;
10819N/A+};
10819N/A+
15635N/A+GType gst_cdda2wav_get_type (void);
10819N/A+
10819N/A+G_END_DECLS
10819N/A+
15635N/A+#endif /* __GST_CDDA2WAV_H__ */
10819N/A+
15635N/A--- /dev/null 2009-01-08 02:18:21.000000000 -0600
15635N/A+++ gst-plugins-good-0.10.11/ext/cdda2wav/gstcdda2wav.c 2009-01-08 02:17:15.164536000 -0600
16148N/A@@ -0,0 +1,795 @@
10819N/A+/* GStreamer
15635N/A+ * Copyright (C) <2007> Brian Cameron <Brian.Cameron@sun.com> and
15635N/A+ * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
16148N/A+ * Copyright (C) 2008 J�rg Schilling <Joerg.Schilling@fokus.fraunhofer.de>
10819N/A+ *
10819N/A+ * This library is free software; you can redistribute it and/or
10819N/A+ * modify it under the terms of the GNU Library General Public
10819N/A+ * License as published by the Free Software Foundation; either
10819N/A+ * version 2 of the License, or (at your option) any later version.
10819N/A+ *
10819N/A+ * This library is distributed in the hope that it will be useful,
10819N/A+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10819N/A+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10819N/A+ * Library General Public License for more details.
10819N/A+ *
10819N/A+ * You should have received a copy of the GNU Library General Public
10819N/A+ * License along with this library; if not, write to the
10819N/A+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10819N/A+ * Boston, MA 02111-1307, USA.
10819N/A+ */
10819N/A+
10819N/A+/**
15635N/A+ * SECTION:element-cdda2wav
10819N/A+ * @short_description: Reads raw audio from an Audio CD
10819N/A+ * @see_also: GstCddaBaseSrc
10819N/A+ *
10819N/A+ * <refsect2>
10819N/A+ * <para>
15635N/A+ * cdda2wav reads and extracts raw audio from Audio CDs using cdda2wav.
10819N/A+ * </para>
10819N/A+ * <title>Example launch line</title>
10819N/A+ * <para>
10819N/A+ * <programlisting>
15635N/A+ * gst-launch cdda2wav track=5 ! audioconvert ! vorbisenc ! oggmux ! filesink location=track5.ogg
10819N/A+ * </programlisting>
10819N/A+ * This pipeline extracts track 5 of the audio CD and encodes it into an
10819N/A+ * Ogg/Vorbis file.
10819N/A+ * </para>
10819N/A+ * </refsect2>
10819N/A+ */
10819N/A+
10819N/A+#ifdef HAVE_CONFIG_H
10819N/A+#include "config.h"
10819N/A+#endif
10819N/A+
10819N/A+#include <stdio.h>
10819N/A+#include <stdlib.h>
10819N/A+#include <fcntl.h>
10819N/A+#include <string.h>
10819N/A+#include <libintl.h>
10819N/A+#include <errno.h>
10819N/A+#include <unistd.h>
15635N/A+#include <sys/filio.h>
15635N/A+#include <signal.h>
15635N/A+#define HAVE_POLL /* XXX Need autoconf test */
15635N/A+#ifdef HAVE_POLL
15635N/A+#include <poll.h>
15635N/A+#endif
10819N/A+#include <sys/byteorder.h>
10819N/A+#include <hal/libhal.h>
10819N/A+#include <hal/libhal-storage.h>
10819N/A+
15635N/A+#include "gstcdda2wav.h"
10819N/A+#include "gst/gst-i18n-plugin.h"
10819N/A+
10819N/A+enum
10819N/A+{
10819N/A+ PROP0 = 0,
10819N/A+};
10819N/A+
15635N/A+GST_DEBUG_CATEGORY_STATIC (gst_cdda2wav_debug);
15635N/A+#define GST_CAT_DEFAULT gst_cdda2wav_debug
10819N/A+
15635N/A+GST_BOILERPLATE (GstCdda2Wav, gst_cdda2wav, GstCddaBaseSrc,
10819N/A+ GST_TYPE_CDDA_BASE_SRC)
10819N/A+
15635N/A+static void gst_cdda2wav_finalize (GObject * obj);
15635N/A+static GstBuffer *gst_cdda2wav_read_sector (GstCddaBaseSrc * src,
10819N/A+ gint sector);
15635N/A+static gboolean gst_cdda2wav_open (GstCddaBaseSrc * src,
10819N/A+ const gchar * device);
15635N/A+static void gst_cdda2wav_close (GstCddaBaseSrc * src);
15635N/A+static gchar **gst_cdda2wav_probe_devices (GstCddaBaseSrc * cddabasesrc);
15635N/A+static gchar *gst_cdda2wav_get_default_device (GstCddaBaseSrc * cddabasesrc);
15635N/A+static void gst_cdda2wav_set_property (GObject * object, guint prop_id,
10819N/A+ const GValue * value, GParamSpec * pspec);
15635N/A+static void gst_cdda2wav_get_property (GObject * object, guint prop_id,
10819N/A+ GValue * value, GParamSpec * pspec);
10819N/A+
15635N/A+static void gst_cdda2wav_hal_find_cdroms (GstCdda2Wav *);
10819N/A+
15635N/A+static pid_t xpopen(FILE **pfpin, FILE **pfpout, FILE **pfperr, const char *cmd);
15635N/A+static int xpclose(FILE *fpin, FILE *fpout, FILE *fperr, pid_t child);
15635N/A+
15635N/A+
15635N/A+static const GstElementDetails cdda2wav_details =
10819N/A+GST_ELEMENT_DETAILS ("CD Audio (cdda) Source",
10819N/A+ "Source/File",
10819N/A+ "Read audio from CD",
15635N/A+ "Brian Cameron <Brian.Cameron@sun.com>, " "Artem Kachitchkine <Artem.Kachitchkine@sun.com>, "
15635N/A+ "Joerg Schilling <Joerg.Schilling@fokus.fraunhofer.de>");
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_base_init (gpointer g_class)
10819N/A+{
10819N/A+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
10819N/A+
15635N/A+ gst_element_class_set_details (element_class, &cdda2wav_details);
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_init (GstCdda2Wav * src, GstCdda2WavClass * klass)
10819N/A+{
15635N/A+ src->devices = NULL;
15635N/A+ src->current_device = NULL;
15635N/A+ src->cdda2wav_in = NULL;
15635N/A+ src->cdda2wav_out = NULL;
15635N/A+ src->cdda2wav_err = NULL;
15635N/A+ src->cdda2wav_pid = 0;
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_class_init (GstCdda2WavClass * klass)
10819N/A+{
10819N/A+ GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
10819N/A+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
10819N/A+
15635N/A+ gobject_class->set_property = gst_cdda2wav_set_property;
15635N/A+ gobject_class->get_property = gst_cdda2wav_get_property;
15635N/A+ gobject_class->finalize = gst_cdda2wav_finalize;
10819N/A+
15635N/A+ cddabasesrc_class->open = gst_cdda2wav_open;
15635N/A+ cddabasesrc_class->close = gst_cdda2wav_close;
15635N/A+ cddabasesrc_class->read_sector = gst_cdda2wav_read_sector;
15635N/A+ cddabasesrc_class->get_default_device = gst_cdda2wav_get_default_device;
15635N/A+ cddabasesrc_class->probe_devices = gst_cdda2wav_probe_devices;
10819N/A+}
10819N/A+
10819N/A+static gchar **
15635N/A+gst_cdda2wav_probe_devices (GstCddaBaseSrc * cddabasesrc)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
10819N/A+
10819N/A+ if (src->devices != NULL) {
10819N/A+ free (src->devices);
10819N/A+ free (src->has_audio);
10819N/A+
10819N/A+ src->devices = NULL;
10819N/A+ src->has_audio = NULL;
10819N/A+ }
15635N/A+ gst_cdda2wav_hal_find_cdroms (src);
10819N/A+
10819N/A+ return (src->devices);
10819N/A+}
10819N/A+
10819N/A+static gchar *
15635N/A+gst_cdda2wav_get_default_device (GstCddaBaseSrc * cddabasesrc)
10819N/A+{
15635N/A+ GstCdda2Wav *src;
10819N/A+ gchar *ret = NULL;
10819N/A+ int i;
10819N/A+
15635N/A+ src = GST_CDDA2WAV (cddabasesrc);
10819N/A+
10819N/A+ if (src->devices == NULL) {
15635N/A+ gst_cdda2wav_probe_devices (cddabasesrc);
10819N/A+ if (src->devices == NULL) {
10819N/A+ return (NULL);
10819N/A+ }
10819N/A+ }
10819N/A+
10819N/A+ /* prefer a drive with an audio disc, otherwise pick first */
10819N/A+ for (i = 0; src->devices[i] != NULL; i++) {
10819N/A+ if (src->has_audio[i]) {
10819N/A+ ret = src->devices[i];
10819N/A+ break;
10819N/A+ }
10819N/A+ }
10819N/A+
10819N/A+ if (ret == NULL)
10819N/A+ ret = src->devices[0];
10819N/A+
10819N/A+ GST_LOG_OBJECT (src, "returning default device: %s", GST_STR_NULL (ret));
10819N/A+
10819N/A+ return (ret);
10819N/A+}
10819N/A+
10819N/A+static boolean_t
15635N/A+cdda2wav_read_toc (GstCdda2Wav *src)
10819N/A+{
15635N/A+ gchar *command;
15635N/A+ char buf[BUFSIZ];
15635N/A+ guint leadout;
15635N/A+ int track_num;
15635N/A+ uint_t i;
15635N/A+ GstCddaBaseSrcTrack tracks[100];
15635N/A+ FILE *f;
15635N/A+
15635N/A+ /* Open the connection to cdda2wav */
15635N/A+ command = g_strdup_printf (
15635N/A+ "/usr/bin/cdda2wav -q dev=%s --info-only -vtoc --no-infofile --gui 2>&1",
15635N/A+ src->current_device);
15635N/A+ f = popen (command, "r");
15635N/A+ g_free (command);
15635N/A+ if (f == NULL)
15635N/A+ return (FALSE);
15635N/A+
15635N/A+ track_num = 0;
15635N/A+ leadout = 0;
15635N/A+
15635N/A+ i = 0;
15635N/A+ while (fgets (buf, BUFSIZ, f) != NULL) {
15635N/A+ char *endptr;
15635N/A+ g_strchomp (buf);
10819N/A+
15635N/A+ if ((strlen (buf) > 12) &&
15635N/A+ (buf[0] == 'T') &&
15635N/A+ (g_ascii_isdigit(buf[1])) &&
15635N/A+ (g_ascii_isdigit(buf[2])) &&
15635N/A+ (buf[3] == ':')) {
10819N/A+
15635N/A+ track_num = buf[2] - '0' + (buf[1] - '0') * 10;
15635N/A+ tracks[i].is_audio = strstr((buf + 4), "audio") != 0;
15635N/A+ tracks[i].num = buf[2] - '0' + (buf[1] - '0') * 10;
15635N/A+ tracks[i].tags = NULL;
15635N/A+ tracks[i].start = (guint) (g_ascii_strtod ((buf + 4), &endptr));
15635N/A+#ifdef DEBUG
15635N/A+ fprintf(stderr, "Track %2.2d %2.2d audio %d start %u\n",
15635N/A+ i, tracks[i].num, tracks[i].is_audio, tracks[i].start);
15635N/A+#endif
15635N/A+ i++;
15635N/A+ }
10819N/A+
15635N/A+ if (strncmp (buf, "Leadout:", 8) == 0) {
15635N/A+ leadout = (guint) (g_ascii_strtod ((buf + 8), &endptr));
15635N/A+ }
15635N/A+ }
15635N/A+ track_num = i;
15635N/A+
15635N/A+ for (i=0; i < track_num; i++) {
10819N/A+ GstCddaBaseSrcTrack track = { 0, };
10819N/A+
15635N/A+ track.is_audio = tracks[i].is_audio;
15635N/A+ track.num = tracks[i].num;
10819N/A+ track.tags = NULL;
15635N/A+ track.start = tracks[i].start;
10819N/A+
15635N/A+ if (i < (track_num - 1))
15635N/A+ track.end = tracks[i+1].start - 1;
15635N/A+ else
15635N/A+ track.end = leadout;
10819N/A+
10819N/A+ gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
10819N/A+ }
10819N/A+
15635N/A+ src->track_count = track_num + 1;
15635N/A+
15635N/A+ pclose (f);
15635N/A+
10819N/A+ return (TRUE);
10819N/A+}
10819N/A+
10819N/A+static gboolean
15635N/A+gst_cdda2wav_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
15635N/A+ gchar *command;
15635N/A+ gboolean ret;
10819N/A+
10819N/A+ g_assert (device != NULL);
10819N/A+
15635N/A+ GST_LOG_OBJECT (src, "Trying to open device %s", device);
15635N/A+ src->current_device = g_strdup (device);
15635N/A+
15635N/A+ ret = cdda2wav_read_toc (src);
15635N/A+
15635N/A+ return ret;
15635N/A+}
10819N/A+
15635N/A+static int
15635N/A+gst_cdda_close (GstCdda2Wav * src)
15635N/A+{
15635N/A+ int rc = 0;
10819N/A+
15635N/A+ if (src->cdda2wav_pid != 0) {
15635N/A+ rc = xpclose (src->cdda2wav_in, src->cdda2wav_out, src->cdda2wav_err,
15635N/A+ src->cdda2wav_pid);
15635N/A+ }
15635N/A+ src->cdda2wav_in = NULL;
15635N/A+ src->cdda2wav_out = NULL;
15635N/A+ src->cdda2wav_err = NULL;
15635N/A+ src->cdda2wav_pid = 0;
15635N/A+
15635N/A+ return rc;
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_close (GstCddaBaseSrc * cddabasesrc)
15635N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
15635N/A+
15635N/A+ gst_cdda_close (src);
15635N/A+}
15635N/A+
15635N/A+static gboolean
15635N/A+getans(GstCdda2Wav *src)
10819N/A+{
15635N/A+ char buf[1024];
15635N/A+ char *p;
15635N/A+ int ret;
15635N/A+#ifdef HAVE_POLL
15635N/A+ struct pollfd pfd[1];
15635N/A+#endif
15635N/A+
15635N/A+#ifdef DEBUG
15635N/A+ fprintf(stderr, "getans\n");
15635N/A+#endif
15635N/A+ if (src->cdda2wav_err == NULL)
15635N/A+ return (FALSE);
15635N/A+ do {
15635N/A+ buf[0] = '\0';
15635N/A+#ifdef HAVE_POLL
15635N/A+ pfd[0].fd = fileno(src->cdda2wav_err);
15635N/A+ pfd[0].events = POLLIN;
15635N/A+ pfd[0].revents = 0;
15635N/A+ if (poll(pfd, 1, 5000) < 1) /* Give up after 5s */
15635N/A+ break;
15635N/A+#else
15635N/A+ insert select code here
15635N/A+#endif
15635N/A+ p = fgets(buf, sizeof (buf), src->cdda2wav_err);
15635N/A+#ifdef DEBUG
15635N/A+ fprintf(stderr, "ERR: '%s'\n", buf);
15635N/A+#endif
15635N/A+ if (buf[0] >= '0' && buf[0] <= '9' &&
15635N/A+ buf[1] >= '0' && buf[1] <= '9' &&
15635N/A+ buf[2] >= '0' && buf[2] <= '9' &&
15635N/A+ buf[3] == ' ')
15635N/A+ break;
15635N/A+ } while (p);
15635N/A+ ret = atoi(buf);
15635N/A+ if (ret != 200) {
15635N/A+ fprintf(stderr, "ERR: %s\n", buf);
15635N/A+ gst_cdda_close (src);
15635N/A+ return (FALSE);
15635N/A+ }
15635N/A+ return (TRUE);
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+flushpipe(FILE *f)
10819N/A+{
15635N/A+ int nread;
15635N/A+ char fbuf[5120];
15635N/A+
15635N/A+ do {
15635N/A+ ioctl(fileno(f), FIONREAD, &nread);
15635N/A+ if (nread > 0) {
15635N/A+ int amt;
15635N/A+
15635N/A+ amt = nread;
15635N/A+ if (amt > sizeof (fbuf))
15635N/A+ amt = sizeof (fbuf);
15635N/A+ if (fread(fbuf, amt, 1, f) != 1)
15635N/A+ break;
15635N/A+ }
15635N/A+ } while (nread > 0);
15635N/A+}
10819N/A+
15635N/A+static gboolean
15635N/A+sendcmd(GstCdda2Wav *src, const char *fmt, uint_t addr)
15635N/A+{
15635N/A+ struct sigaction old;
15635N/A+ struct sigaction my;
15635N/A+
15635N/A+ sigemptyset(&my.sa_mask);
15635N/A+ my.sa_handler == SIG_IGN;
15635N/A+ my.sa_flags = 0;
15635N/A+ sigaction(SIGPIPE, &my, &old);
15635N/A+
15635N/A+ clearerr(src->cdda2wav_in);
15635N/A+ fprintf(src->cdda2wav_in, fmt, addr);
15635N/A+ fflush(src->cdda2wav_in);
15635N/A+
15635N/A+ sigaction(SIGPIPE, &old, NULL);
15635N/A+
15635N/A+ if (ferror(src->cdda2wav_in)) {
15635N/A+ gst_cdda_close(src);
15635N/A+ return (FALSE);
15635N/A+ }
15635N/A+ return (TRUE);
10819N/A+}
10819N/A+
16148N/A+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
16148N/A+#define CDDA2WAV_BYTE_ORDER "little"
16148N/A+#elif G_BYTE_ORDER == G_BIG_ENDIAN
16148N/A+#define CDDA2WAV_BYTE_ORDER "big"
16148N/A+#else
16148N/A+#error "G_BYTE_ORDER should be big or little endian."
16148N/A+#endif
16148N/A+
10819N/A+static gboolean
15635N/A+cdda2wav_read (GstCdda2Wav *src, void *buf, uint_t addr, uint_t len)
10819N/A+{
15635N/A+ static int last_addr = -1;
15635N/A+ char * command;
15635N/A+ int did_retry = -1;
15635N/A+ gboolean do_paranoia = FALSE; /* Need to be parameterized from elsewhere */
15635N/A+
15635N/A+retry:
15635N/A+ if (++did_retry > 1)
15635N/A+ return (FALSE);
10819N/A+
15635N/A+ if (src->cdda2wav_pid == 0) {
15635N/A+ command = g_strdup_printf (
16148N/A+ "/usr/bin/cdda2wav -q --output-endianess=%s dev=%s -Oraw %s -interactive -",
16148N/A+ CDDA2WAV_BYTE_ORDER, src->current_device,
16148N/A+ do_paranoia ? "-paranoia -paraopts=minoverlap=2":"");
15635N/A+ src->cdda2wav_pid = xpopen (&src->cdda2wav_in, &src->cdda2wav_out,
15635N/A+ &src->cdda2wav_err, command);
15635N/A+#ifdef DEBUG
15635N/A+ fprintf(stderr, "PID %d\n", src->cdda2wav_pid);
15635N/A+#endif
15635N/A+ g_free (command);
15635N/A+ if (!sendcmd(src, "read sectors %u\n", addr))
15635N/A+ goto retry;
15635N/A+ if (!getans(src))
15635N/A+ goto retry;
15635N/A+ last_addr = addr;
15635N/A+ } else if (addr != (last_addr + 1)) { /* Check whether we need to seek */
15635N/A+ int nread;
10819N/A+
15635N/A+ if (!sendcmd(src, "stop\n", 0))
15635N/A+ goto retry;
15635N/A+ flushpipe(src->cdda2wav_out);
15635N/A+ if (!getans(src))
15635N/A+ goto retry;
15635N/A+ do {
15635N/A+ if (!sendcmd(src, "stop\n", 0))
15635N/A+ goto retry;
15635N/A+ flushpipe(src->cdda2wav_out);
15635N/A+ if (!getans(src))
15635N/A+ goto retry;
15635N/A+ ioctl(fileno(src->cdda2wav_out), FIONREAD, &nread);
15635N/A+ } while (nread > 0);
15635N/A+ if (!sendcmd(src, "read sectors %u\n", addr))
15635N/A+ goto retry;
15635N/A+ if (!getans(src))
15635N/A+ goto retry;
10819N/A+ }
15635N/A+ last_addr = addr;
10819N/A+
15635N/A+ if (fread (buf, CDDA2WAV_BSIZE, len, src->cdda2wav_out) != len) {
15635N/A+ if (feof(src->cdda2wav_out)) {
15635N/A+ if (gst_cdda_close (src) == 0)
15635N/A+ return (TRUE);
15635N/A+ goto retry;
15635N/A+ }
15635N/A+ return (FALSE);
15635N/A+ }
10819N/A+
10819N/A+ return (TRUE);
10819N/A+}
10819N/A+
10819N/A+static GstBuffer *
15635N/A+gst_cdda2wav_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
15635N/A+ size_t len = CDDA2WAV_BSIZE;
15635N/A+ GstBuffer *buf;
10819N/A+
15635N/A+ buf = gst_buffer_new_and_alloc (CDDA2WAV_BSIZE);
12929N/A+
15635N/A+ if (!cdda2wav_read (src, GST_BUFFER_DATA (buf), sector, 1)) {
15635N/A+ free (buf);
12929N/A+ buf = NULL;
12929N/A+ return NULL;
10819N/A+ }
10819N/A+
12929N/A+ return (buf);
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_finalize (GObject * obj)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (obj);
10819N/A+
15635N/A+ gst_cdda_close (src);
15635N/A+
15635N/A+ g_free (src->devices);
15635N/A+ g_free (src->current_device);
10819N/A+
10819N/A+ G_OBJECT_CLASS (parent_class)->finalize (obj);
10819N/A+}
10819N/A+
10819N/A+static gboolean
10819N/A+plugin_init (GstPlugin * plugin)
10819N/A+{
15635N/A+ GST_DEBUG_CATEGORY_INIT (gst_cdda2wav_debug, "cdda2wav", 0,
10819N/A+ "CDDA Source");
10819N/A+
15635N/A+ if (!gst_element_register (plugin, "cdda2wav", GST_RANK_SECONDARY,
15635N/A+ GST_TYPE_CDDA2WAV))
10819N/A+ return FALSE;
10819N/A+
10819N/A+#ifdef ENABLE_NLS
10819N/A+ GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
10819N/A+ LOCALEDIR);
10819N/A+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
10819N/A+#endif
10819N/A+
10819N/A+ return TRUE;
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_set_property (GObject * object, guint prop_id,
10819N/A+ const GValue * value, GParamSpec * pspec)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (object);
10819N/A+
10819N/A+ switch (prop_id) {
10819N/A+ default:
10819N/A+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
10819N/A+ break;
10819N/A+ }
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_get_property (GObject * object, guint prop_id,
10819N/A+ GValue * value, GParamSpec * pspec)
10819N/A+{
15635N/A+ GstCdda2Wav *src = GST_CDDA2WAV (object);
10819N/A+
10819N/A+ switch (prop_id) {
10819N/A+ default:
10819N/A+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
10819N/A+ break;
10819N/A+ }
10819N/A+}
10819N/A+
10819N/A+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
10819N/A+ GST_VERSION_MINOR,
15635N/A+ "cdda2wav",
10819N/A+ "Read audio from CD",
10819N/A+ plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
10819N/A+
10819N/A+/* ===== HAL stuff ===== */
10819N/A+
10819N/A+static LibHalContext *
15635N/A+gst_cdda2wav_hal_init (GstCdda2Wav *src)
10819N/A+{
10819N/A+ DBusError error;
10819N/A+ LibHalContext *hal_ctx = NULL;
10819N/A+
10819N/A+ dbus_error_init (&error);
10819N/A+ if ((hal_ctx = libhal_ctx_new ()) == NULL) {
10819N/A+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
10819N/A+ ("failed to initialize HAL"), ("failed to initialize HAL"));
10819N/A+ goto out;
10819N/A+ }
10819N/A+ if (!libhal_ctx_set_dbus_connection(hal_ctx,
10819N/A+ dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
10819N/A+
10819N/A+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
10819N/A+ ("DBus connection failed"),
10819N/A+ ("libhal_ctx_set_dbus_connection: %s %s", error.name, error.message));
10819N/A+ libhal_ctx_free (hal_ctx);
10819N/A+ goto out;
10819N/A+ }
10819N/A+ if (!libhal_ctx_init(hal_ctx, &error)) {
10819N/A+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
10819N/A+ ("HAL context init failed"),
10819N/A+ ("libhal_ctx_init: %s: %s", error.name, error.message));
10819N/A+ libhal_ctx_free (hal_ctx);
10819N/A+ goto out;
10819N/A+ }
10819N/A+out:
10819N/A+ dbus_error_free (&error);
10819N/A+
10819N/A+ return (hal_ctx);
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_hal_fini (LibHalContext *hal_ctx)
10819N/A+{
10819N/A+ DBusError error;
10819N/A+
10819N/A+ dbus_error_init (&error);
10819N/A+ libhal_ctx_shutdown (hal_ctx, &error);
10819N/A+ libhal_ctx_free (hal_ctx);
10819N/A+ dbus_error_free (&error);
10819N/A+}
10819N/A+
10819N/A+static void
15635N/A+gst_cdda2wav_hal_find_cdroms (GstCdda2Wav *src)
10819N/A+{
10819N/A+ DBusError error;
10819N/A+ LibHalContext *hal_ctx;
10819N/A+ int i, j, k;
10819N/A+ char **drive_udis, **volume_udis;
10819N/A+ int num_drives, num_volumes;
10819N/A+ char *raw_device;
10819N/A+ LibHalDrive *drive;
10819N/A+ dbus_bool_t has_audio;
10819N/A+
15635N/A+ if ((hal_ctx = gst_cdda2wav_hal_init (src)) == NULL) {
10819N/A+ return;
10819N/A+ }
10819N/A+ dbus_error_init (&error);
10819N/A+
10819N/A+ drive_udis = libhal_find_device_by_capability (hal_ctx, "storage.cdrom",
10819N/A+ &num_drives, &error);
10819N/A+
10819N/A+ if (dbus_error_is_set (&error) || drive_udis == NULL) {
10819N/A+ goto out;
10819N/A+ }
10819N/A+
10819N/A+ src->devices = calloc (num_drives + 1, sizeof (char *));
10819N/A+ src->has_audio = calloc (num_drives + 1, sizeof (boolean_t));
10819N/A+
10819N/A+ for (i = j = 0; i < num_drives; i++) {
10819N/A+ raw_device = libhal_device_get_property_string (hal_ctx,
10819N/A+ drive_udis[i], "block.solaris.raw_device", &error);
10819N/A+ dbus_error_free (&error);
10819N/A+
10819N/A+ if ((raw_device == NULL) || (strlen (raw_device) == 0)) {
10819N/A+ libhal_free_string (raw_device);
10819N/A+ continue;
10819N/A+ }
10819N/A+
10819N/A+ src->devices[j] = strdup (raw_device);
10819N/A+ libhal_free_string (raw_device);
10819N/A+
10819N/A+ /* check for audio disc in this drive */
10819N/A+ if ((drive = libhal_drive_from_udi (hal_ctx, drive_udis[i])) != NULL) {
10819N/A+ if ((volume_udis = libhal_drive_find_all_volumes (hal_ctx,
10819N/A+ drive, &num_volumes)) != NULL) {
10819N/A+
10819N/A+ for (k = 0; k < num_volumes; k++) {
10819N/A+ src->has_audio[j] = (boolean_t)
10819N/A+ libhal_device_get_property_bool (hal_ctx,
10819N/A+ volume_udis[k], "volume.disc.has_audio", &error);
10819N/A+ dbus_error_free (&error);
10819N/A+ if (src->has_audio[j]) {
10819N/A+ break;
10819N/A+ }
10819N/A+ }
10819N/A+ libhal_free_string_array (volume_udis);
10819N/A+ }
10819N/A+ libhal_drive_free (drive);
10819N/A+ }
10819N/A+
10819N/A+ j++;
10819N/A+ }
10819N/A+
10819N/A+out:
10819N/A+ libhal_free_string_array (drive_udis);
10819N/A+ dbus_error_free (&error);
10819N/A+
15635N/A+ gst_cdda2wav_hal_fini (hal_ctx);
10819N/A+}
10819N/A+
15635N/A+#define HAVE_SYS_FORK_H /* XXX Need autoconf test */
15635N/A+#ifdef HAVE_SYS_FORK_H
15635N/A+#include <sys/fork.h>
15635N/A+#endif
15635N/A+#include <wait.h>
15635N/A+
15635N/A+static pid_t
15635N/A+xpopen(FILE **pfpin, FILE **pfpout, FILE **pfperr, const char *cmd)
15635N/A+{
15635N/A+ int in[2];
15635N/A+ int out[2];
15635N/A+ int err[2];
15635N/A+ pid_t pid;
15635N/A+
15635N/A+ in[0] = STDIN_FILENO;
15635N/A+ out[1] = STDOUT_FILENO;
15635N/A+ err[1] = STDERR_FILENO;
15635N/A+ if (pfpin) {
15635N/A+ if (pipe(in) < 0)
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ if (pfpout) {
15635N/A+ if (pipe(out) < 0) {
15635N/A+ close(in[0]);
15635N/A+ close(in[1]);
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ }
15635N/A+ if (pfperr) {
15635N/A+ if (pipe(err) < 0) {
15635N/A+ close(in[0]);
15635N/A+ close(in[1]);
15635N/A+ close(out[0]);
15635N/A+ close(out[1]);
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ }
15635N/A+
15635N/A+#ifdef FORK_NOSIGCHLD
15635N/A+ pid = vforkx(FORK_NOSIGCHLD|FORK_WAITPID);
15635N/A+#else
15635N/A+ pid = vfork(); /* Need to find a way to deal with SIGCHLD and wait */
15635N/A+#endif
15635N/A+ if (pid == (pid_t)-1) {
15635N/A+ return ((pid_t)-1);
15635N/A+ } else if (pid > 0) {
15635N/A+ if (pfpin) {
15635N/A+ close(in[0]);
15635N/A+ *pfpin = fdopen(in[1], "w");
15635N/A+ if (*pfpin == NULL) {
15635N/A+ close(in[1]);
15635N/A+ close(out[0]);
15635N/A+ close(out[1]);
15635N/A+ close(err[0]);
15635N/A+ close(err[1]);
15635N/A+ kill(pid, SIGKILL);
15722N/A+ xpclose(NULL, NULL, NULL, pid);
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ }
15635N/A+ if (pfpout) {
15635N/A+ close(out[1]);
15635N/A+ *pfpout = fdopen(out[0], "r");
15635N/A+ if (*pfpout == NULL) {
15635N/A+ close(out[0]);
15635N/A+ close(err[0]);
15635N/A+ close(err[1]);
15635N/A+ kill(pid, SIGKILL);
15722N/A+ xpclose(*pfpin, NULL, NULL, pid);
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ }
15635N/A+ if (pfperr) {
15635N/A+ close(err[1]);
15635N/A+ *pfperr = fdopen(err[0], "r");
15635N/A+ if (*pfperr == NULL) {
15635N/A+ close(err[0]);
15635N/A+ kill(pid, SIGKILL);
15722N/A+ xpclose(*pfpin, *pfpout, NULL, pid);
15635N/A+ return ((pid_t)-1);
15635N/A+ }
15635N/A+ }
15635N/A+ } else {
15635N/A+ if (pfpin)
15635N/A+ close(in[1]);
15635N/A+ if (pfpout)
15635N/A+ close(out[0]);
15635N/A+ if (pfperr)
15635N/A+ close(err[0]);
15635N/A+ if (in[0] != STDIN_FILENO) {
15635N/A+ dup2(in[0], STDIN_FILENO);
15635N/A+ close(in[0]);
15635N/A+ }
15635N/A+ if (out[1] != STDOUT_FILENO) {
15635N/A+ dup2(out[1], STDOUT_FILENO);
15635N/A+ close(out[1]);
15635N/A+ }
15635N/A+ if (err[1] != STDERR_FILENO) {
15635N/A+ dup2(err[1], STDERR_FILENO);
15635N/A+ close(err[1]);
15635N/A+ }
15635N/A+ execl("/bin/sh", "sh", "-c", cmd, (char *)0);
15635N/A+ _exit(1);
15635N/A+ }
15635N/A+ return (pid);
15635N/A+}
15635N/A+
15635N/A+static int
15635N/A+xpclose(FILE *fpin, FILE *fpout, FILE *fperr, pid_t child)
15635N/A+{
15635N/A+ int status = 0;
15635N/A+
15635N/A+ if (fpin)
15635N/A+ fclose(fpin);
15635N/A+ if (fpout)
15635N/A+ fclose(fpout);
15635N/A+ if (fperr)
15635N/A+ fclose(fperr);
15635N/A+
15635N/A+ if (child <= 0) {
15635N/A+ errno = ECHILD;
15635N/A+ return (-1);
15635N/A+ }
15635N/A+ if (waitpid(child, &status, WNOHANG) == child)
15635N/A+ return (status);
15635N/A+ while (waitpid(child, &status, 0) < 0) {
15635N/A+ if (errno != EINTR) {
15635N/A+ status = -1;
15635N/A+ break;
15635N/A+ }
15635N/A+ }
15635N/A+ return (status);
15635N/A+}