1 --- gst-plugins-good-0.10.13/configure.ac-orig 2009-01-23 10:02:53.003952000 -0600
2 +++ gst-plugins-good-0.10.13/configure.ac 2009-01-23 10:03:03.048601000 -0600
3 @@ -660,6 +668,24 @@ AG_GST_CHECK_FEATURE(CAIRO_GOBJECT,
4 AG_GST_PKG_CHECK_MODULES(CAIRO_GOBJECT, cairo-gobject >= 1.10.0)
8 +translit(dnm, m, l) AM_CONDITIONAL(USE_CDDA2WAV, true)
9 +AG_GST_CHECK_FEATURE(CDDA2WAV, [HAL libraries], cdda2wav, [
10 + AG_GST_PKG_CHECK_MODULES(CDDA2WAV, [hal >= 0.5.8, hal-storage >= 0.5.8, dbus-1 >= 0.32])
11 + AC_PATH_PROG(CDDA2WAVBIN, cdda2wav, no)
12 + if test x$CDDA2WAVBIN = xno; then
15 + CDDA_VERSION=`$CDDA2WAVBIN --version | grep Schilling`
16 + if test -z "$CDDA_VERSION"; then
22 + AC_SUBST(HAVE_CDDA2WAV)
26 translit(dnm, m, l) AM_CONDITIONAL(USE_ESD, true)
27 AG_GST_CHECK_FEATURE(ESD, [ESounD sound daemon], esdsink, [
28 @@ -928,6 +954,7 @@ AM_CONDITIONAL(USE_DIRECTDRAW, false)
29 AM_CONDITIONAL(USE_DIRECTSOUND, false)
30 AM_CONDITIONAL(USE_DV1394, false)
31 AM_CONDITIONAL(USE_ESD, false)
32 +AM_CONDITIONAL(USE_CDDA2WAV, false)
33 AM_CONDITIONAL(USE_FLAC, false)
34 AM_CONDITIONAL(USE_GCONF, false)
35 AM_CONDITIONAL(USE_GCONFTOOL, false)
36 @@ -1055,6 +1083,7 @@ ext/Makefile
40 +ext/cdda2wav/Makefile
44 --- gst-plugins-good-0.10.10/ext/Makefile.am-orig 2008-08-27 23:56:51.987944000 -0500
45 +++ gst-plugins-good-0.10.10/ext/Makefile.am 2008-08-27 23:57:20.124741000 -0500
46 @@ -16,6 +16,12 @@ else
51 +CDDA2WAV_DIR = cdda2wav
59 @@ -131,6 +137,7 @@ SUBDIRS = \
67 --- /dev/null 2007-03-19 01:47:57.000000000 +0800
68 +++ gst-plugins-good-0.10.6/ext/cdda2wav/Makefile.am 2007-03-19 01:46:41.639278000 +0800
70 +plugin_LTLIBRARIES = libgstcdda2wav.la
72 +libgstcdda2wav_la_SOURCES = \
75 +libgstcdda2wav_la_CFLAGS = \
76 + $(GST_PLUGINS_BASE_CFLAGS) \
77 + $(GST_BASE_CFLAGS) \
81 +libgstcdda2wav_la_LIBADD = \
82 + $(GST_PLUGINS_BASE_LIBS) -lgstcdda-$(GST_MAJORMINOR) \
86 +libgstcdda2wav_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
90 --- /dev/null 2008-12-19 17:50:06.000000000 -0600
91 +++ gst-plugins-good-0.10.6/ext/cdda2wav/gstcdda2wav.h 2008-07-17 07:48:57.000000000 -0500
94 + * Copyright (C) 2007 Brian Cameron <Brian.Cameron@sun.com> and
95 + * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
96 + * Copyright (C) 2008 J÷rg Schilling <Joerg.Schilling@fokus.fraunhofer.de>
98 + * This library is free software; you can redistribute it and/or
99 + * modify it under the terms of the GNU Library General Public
100 + * License as published by the Free Software Foundation; either
101 + * version 2 of the License, or (at your option) any later version.
103 + * This library is distributed in the hope that it will be useful,
104 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
105 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
106 + * Library General Public License for more details.
108 + * You should have received a copy of the GNU Library General Public
109 + * License along with this library; if not, write to the
110 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
111 + * Boston, MA 02111-1307, USA.
114 +#ifndef __GST_CDDA2WAV_H__
115 +#define __GST_CDDA2WAV_H__
117 +#include <sys/types.h>
118 +#include "gst/cdda/gstcddabasesrc.h"
120 +#define CDDA2WAV_BSIZE 2352
124 +#define GST_TYPE_CDDA2WAV (gst_cdda2wav_get_type())
125 +#define GST_CDDA2WAV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CDDA2WAV,GstCdda2Wav))
126 +#define GST_CDDA2WAV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CDDA2WAV,GstCdda2WavClass))
127 +#define GST_IS_CDDA2WAV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CDDA2WAV))
128 +#define GST_IS_CDDA2WAV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDDA2WAV))
129 +#define GST_CDDA2WAV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA2WAV, GstCdda2WavClass))
131 +typedef struct _GstCdda2Wav GstCdda2Wav;
132 +typedef struct _GstCdda2WavClass GstCdda2WavClass;
134 +#define CDDA2WAV_BSIZE 2352
139 + * The cdda2wav object structure.
141 +struct _GstCdda2Wav {
142 + GstCddaBaseSrc cddabasesrc;
146 + FILE *cdda2wav_out;
147 + FILE *cdda2wav_err;
148 + pid_t cdda2wav_pid;
149 + uint_t track_count;
151 + char *current_device;
152 + boolean_t *has_audio;
155 +struct _GstCdda2WavClass {
156 + GstCddaBaseSrcClass parent_class;
159 +GType gst_cdda2wav_get_type (void);
163 +#endif /* __GST_CDDA2WAV_H__ */
165 --- /dev/null 2009-01-08 02:18:21.000000000 -0600
166 +++ gst-plugins-good-0.10.11/ext/cdda2wav/gstcdda2wav.c 2009-01-08 02:17:15.164536000 -0600
169 + * Copyright (C) <2007> Brian Cameron <Brian.Cameron@sun.com> and
170 + * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
171 + * Copyright (C) 2008 J÷rg Schilling <Joerg.Schilling@fokus.fraunhofer.de>
173 + * This library is free software; you can redistribute it and/or
174 + * modify it under the terms of the GNU Library General Public
175 + * License as published by the Free Software Foundation; either
176 + * version 2 of the License, or (at your option) any later version.
178 + * This library is distributed in the hope that it will be useful,
179 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
180 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
181 + * Library General Public License for more details.
183 + * You should have received a copy of the GNU Library General Public
184 + * License along with this library; if not, write to the
185 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
186 + * Boston, MA 02111-1307, USA.
190 + * SECTION:element-cdda2wav
191 + * @short_description: Reads raw audio from an Audio CD
192 + * @see_also: GstCddaBaseSrc
196 + * cdda2wav reads and extracts raw audio from Audio CDs using cdda2wav.
198 + * <title>Example launch line</title>
201 + * gst-launch cdda2wav track=5 ! audioconvert ! vorbisenc ! oggmux ! filesink location=track5.ogg
202 + * </programlisting>
203 + * This pipeline extracts track 5 of the audio CD and encodes it into an
209 +#ifdef HAVE_CONFIG_H
217 +#include <libintl.h>
220 +#include <sys/filio.h>
222 +#define HAVE_POLL /* XXX Need autoconf test */
226 +#include <sys/byteorder.h>
227 +#include <hal/libhal.h>
228 +#include <hal/libhal-storage.h>
230 +#include "gstcdda2wav.h"
231 +#include "gst/gst-i18n-plugin.h"
238 +GST_DEBUG_CATEGORY_STATIC (gst_cdda2wav_debug);
239 +#define GST_CAT_DEFAULT gst_cdda2wav_debug
241 +GST_BOILERPLATE (GstCdda2Wav, gst_cdda2wav, GstCddaBaseSrc,
242 + GST_TYPE_CDDA_BASE_SRC)
244 +static void gst_cdda2wav_finalize (GObject * obj);
245 +static GstBuffer *gst_cdda2wav_read_sector (GstCddaBaseSrc * src,
247 +static gboolean gst_cdda2wav_open (GstCddaBaseSrc * src,
248 + const gchar * device);
249 +static void gst_cdda2wav_close (GstCddaBaseSrc * src);
250 +static gchar **gst_cdda2wav_probe_devices (GstCddaBaseSrc * cddabasesrc);
251 +static gchar *gst_cdda2wav_get_default_device (GstCddaBaseSrc * cddabasesrc);
252 +static void gst_cdda2wav_set_property (GObject * object, guint prop_id,
253 + const GValue * value, GParamSpec * pspec);
254 +static void gst_cdda2wav_get_property (GObject * object, guint prop_id,
255 + GValue * value, GParamSpec * pspec);
257 +static void gst_cdda2wav_hal_find_cdroms (GstCdda2Wav *);
259 +static pid_t xpopen(FILE **pfpin, FILE **pfpout, FILE **pfperr, const char *cmd);
260 +static int xpclose(FILE *fpin, FILE *fpout, FILE *fperr, pid_t child);
263 +static const GstElementDetails cdda2wav_details =
264 +GST_ELEMENT_DETAILS ("CD Audio (cdda) Source",
266 + "Read audio from CD",
267 + "Brian Cameron <Brian.Cameron@sun.com>, " "Artem Kachitchkine <Artem.Kachitchkine@sun.com>, "
268 + "Joerg Schilling <Joerg.Schilling@fokus.fraunhofer.de>");
271 +gst_cdda2wav_base_init (gpointer g_class)
273 + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
275 + gst_element_class_set_details (element_class, &cdda2wav_details);
279 +gst_cdda2wav_init (GstCdda2Wav * src, GstCdda2WavClass * klass)
281 + src->devices = NULL;
282 + src->current_device = NULL;
283 + src->cdda2wav_in = NULL;
284 + src->cdda2wav_out = NULL;
285 + src->cdda2wav_err = NULL;
286 + src->cdda2wav_pid = 0;
290 +gst_cdda2wav_class_init (GstCdda2WavClass * klass)
292 + GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
293 + GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
295 + gobject_class->set_property = gst_cdda2wav_set_property;
296 + gobject_class->get_property = gst_cdda2wav_get_property;
297 + gobject_class->finalize = gst_cdda2wav_finalize;
299 + cddabasesrc_class->open = gst_cdda2wav_open;
300 + cddabasesrc_class->close = gst_cdda2wav_close;
301 + cddabasesrc_class->read_sector = gst_cdda2wav_read_sector;
302 + cddabasesrc_class->get_default_device = gst_cdda2wav_get_default_device;
303 + cddabasesrc_class->probe_devices = gst_cdda2wav_probe_devices;
307 +gst_cdda2wav_probe_devices (GstCddaBaseSrc * cddabasesrc)
309 + GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
311 + if (src->devices != NULL) {
312 + free (src->devices);
313 + free (src->has_audio);
315 + src->devices = NULL;
316 + src->has_audio = NULL;
318 + gst_cdda2wav_hal_find_cdroms (src);
320 + return (src->devices);
324 +gst_cdda2wav_get_default_device (GstCddaBaseSrc * cddabasesrc)
330 + src = GST_CDDA2WAV (cddabasesrc);
332 + if (src->devices == NULL) {
333 + gst_cdda2wav_probe_devices (cddabasesrc);
334 + if (src->devices == NULL) {
339 + /* prefer a drive with an audio disc, otherwise pick first */
340 + for (i = 0; src->devices[i] != NULL; i++) {
341 + if (src->has_audio[i]) {
342 + ret = src->devices[i];
348 + ret = src->devices[0];
350 + GST_LOG_OBJECT (src, "returning default device: %s", GST_STR_NULL (ret));
356 +cdda2wav_read_toc (GstCdda2Wav *src)
363 + GstCddaBaseSrcTrack tracks[100];
366 + /* Open the connection to cdda2wav */
367 + command = g_strdup_printf (
368 + "/usr/bin/cdda2wav -q dev=%s --info-only -vtoc --no-infofile --gui 2>&1",
369 + src->current_device);
370 + f = popen (command, "r");
379 + while (fgets (buf, BUFSIZ, f) != NULL) {
383 + if ((strlen (buf) > 12) &&
385 + (g_ascii_isdigit(buf[1])) &&
386 + (g_ascii_isdigit(buf[2])) &&
389 + track_num = buf[2] - '0' + (buf[1] - '0') * 10;
390 + tracks[i].is_audio = strstr((buf + 4), "audio") != 0;
391 + tracks[i].num = buf[2] - '0' + (buf[1] - '0') * 10;
392 + tracks[i].tags = NULL;
393 + tracks[i].start = (guint) (g_ascii_strtod ((buf + 4), &endptr));
395 + fprintf(stderr, "Track %2.2d %2.2d audio %d start %u\n",
396 + i, tracks[i].num, tracks[i].is_audio, tracks[i].start);
401 + if (strncmp (buf, "Leadout:", 8) == 0) {
402 + leadout = (guint) (g_ascii_strtod ((buf + 8), &endptr));
407 + for (i=0; i < track_num; i++) {
408 + GstCddaBaseSrcTrack track = { 0, };
410 + track.is_audio = tracks[i].is_audio;
411 + track.num = tracks[i].num;
413 + track.start = tracks[i].start;
415 + if (i < (track_num - 1))
416 + track.end = tracks[i+1].start - 1;
418 + track.end = leadout;
420 + gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
423 + src->track_count = track_num + 1;
431 +gst_cdda2wav_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
433 + GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
437 + g_assert (device != NULL);
439 + GST_LOG_OBJECT (src, "Trying to open device %s", device);
440 + src->current_device = g_strdup (device);
442 + ret = cdda2wav_read_toc (src);
448 +gst_cdda_close (GstCdda2Wav * src)
452 + if (src->cdda2wav_pid != 0) {
453 + rc = xpclose (src->cdda2wav_in, src->cdda2wav_out, src->cdda2wav_err,
454 + src->cdda2wav_pid);
456 + src->cdda2wav_in = NULL;
457 + src->cdda2wav_out = NULL;
458 + src->cdda2wav_err = NULL;
459 + src->cdda2wav_pid = 0;
465 +gst_cdda2wav_close (GstCddaBaseSrc * cddabasesrc)
467 + GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
469 + gst_cdda_close (src);
473 +getans(GstCdda2Wav *src)
479 + struct pollfd pfd[1];
483 + fprintf(stderr, "getans\n");
485 + if (src->cdda2wav_err == NULL)
490 + pfd[0].fd = fileno(src->cdda2wav_err);
491 + pfd[0].events = POLLIN;
492 + pfd[0].revents = 0;
493 + if (poll(pfd, 1, 5000) < 1) /* Give up after 5s */
496 + insert select code here
498 + p = fgets(buf, sizeof (buf), src->cdda2wav_err);
500 + fprintf(stderr, "ERR: '%s'\n", buf);
502 + if (buf[0] >= '0' && buf[0] <= '9' &&
503 + buf[1] >= '0' && buf[1] <= '9' &&
504 + buf[2] >= '0' && buf[2] <= '9' &&
510 + fprintf(stderr, "ERR: %s\n", buf);
511 + gst_cdda_close (src);
524 + ioctl(fileno(f), FIONREAD, &nread);
529 + if (amt > sizeof (fbuf))
530 + amt = sizeof (fbuf);
531 + if (fread(fbuf, amt, 1, f) != 1)
534 + } while (nread > 0);
538 +sendcmd(GstCdda2Wav *src, const char *fmt, uint_t addr)
540 + struct sigaction old;
541 + struct sigaction my;
543 + sigemptyset(&my.sa_mask);
544 + my.sa_handler == SIG_IGN;
546 + sigaction(SIGPIPE, &my, &old);
548 + clearerr(src->cdda2wav_in);
549 + fprintf(src->cdda2wav_in, fmt, addr);
550 + fflush(src->cdda2wav_in);
552 + sigaction(SIGPIPE, &old, NULL);
554 + if (ferror(src->cdda2wav_in)) {
555 + gst_cdda_close(src);
561 +#if G_BYTE_ORDER == G_LITTLE_ENDIAN
562 +#define CDDA2WAV_BYTE_ORDER "little"
563 +#elif G_BYTE_ORDER == G_BIG_ENDIAN
564 +#define CDDA2WAV_BYTE_ORDER "big"
566 +#error "G_BYTE_ORDER should be big or little endian."
570 +cdda2wav_read (GstCdda2Wav *src, void *buf, uint_t addr, uint_t len)
572 + static int last_addr = -1;
574 + int did_retry = -1;
575 + gboolean do_paranoia = FALSE; /* Need to be parameterized from elsewhere */
578 + if (++did_retry > 1)
581 + if (src->cdda2wav_pid == 0) {
582 + command = g_strdup_printf (
583 + "/usr/bin/cdda2wav -q --output-endianess=%s dev=%s -Oraw %s -interactive -",
584 + CDDA2WAV_BYTE_ORDER, src->current_device,
585 + do_paranoia ? "-paranoia -paraopts=minoverlap=2":"");
586 + src->cdda2wav_pid = xpopen (&src->cdda2wav_in, &src->cdda2wav_out,
587 + &src->cdda2wav_err, command);
589 + fprintf(stderr, "PID %d\n", src->cdda2wav_pid);
592 + if (!sendcmd(src, "read sectors %u\n", addr))
597 + } else if (addr != (last_addr + 1)) { /* Check whether we need to seek */
600 + if (!sendcmd(src, "stop\n", 0))
602 + flushpipe(src->cdda2wav_out);
606 + if (!sendcmd(src, "stop\n", 0))
608 + flushpipe(src->cdda2wav_out);
611 + ioctl(fileno(src->cdda2wav_out), FIONREAD, &nread);
612 + } while (nread > 0);
613 + if (!sendcmd(src, "read sectors %u\n", addr))
620 + if (fread (buf, CDDA2WAV_BSIZE, len, src->cdda2wav_out) != len) {
621 + if (feof(src->cdda2wav_out)) {
622 + if (gst_cdda_close (src) == 0)
633 +gst_cdda2wav_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
635 + GstCdda2Wav *src = GST_CDDA2WAV (cddabasesrc);
636 + size_t len = CDDA2WAV_BSIZE;
639 + buf = gst_buffer_new_and_alloc (CDDA2WAV_BSIZE);
641 + if (!cdda2wav_read (src, GST_BUFFER_DATA (buf), sector, 1)) {
651 +gst_cdda2wav_finalize (GObject * obj)
653 + GstCdda2Wav *src = GST_CDDA2WAV (obj);
655 + gst_cdda_close (src);
657 + g_free (src->devices);
658 + g_free (src->current_device);
660 + G_OBJECT_CLASS (parent_class)->finalize (obj);
664 +plugin_init (GstPlugin * plugin)
666 + GST_DEBUG_CATEGORY_INIT (gst_cdda2wav_debug, "cdda2wav", 0,
669 + if (!gst_element_register (plugin, "cdda2wav", GST_RANK_SECONDARY,
670 + GST_TYPE_CDDA2WAV))
674 + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
676 + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
683 +gst_cdda2wav_set_property (GObject * object, guint prop_id,
684 + const GValue * value, GParamSpec * pspec)
686 + GstCdda2Wav *src = GST_CDDA2WAV (object);
690 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
696 +gst_cdda2wav_get_property (GObject * object, guint prop_id,
697 + GValue * value, GParamSpec * pspec)
699 + GstCdda2Wav *src = GST_CDDA2WAV (object);
703 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
708 +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
711 + "Read audio from CD",
712 + plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
714 +/* ===== HAL stuff ===== */
716 +static LibHalContext *
717 +gst_cdda2wav_hal_init (GstCdda2Wav *src)
720 + LibHalContext *hal_ctx = NULL;
722 + dbus_error_init (&error);
723 + if ((hal_ctx = libhal_ctx_new ()) == NULL) {
724 + GST_ELEMENT_ERROR (src, LIBRARY, INIT,
725 + ("failed to initialize HAL"), ("failed to initialize HAL"));
728 + if (!libhal_ctx_set_dbus_connection(hal_ctx,
729 + dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
731 + GST_ELEMENT_ERROR (src, LIBRARY, INIT,
732 + ("DBus connection failed"),
733 + ("libhal_ctx_set_dbus_connection: %s %s", error.name, error.message));
734 + libhal_ctx_free (hal_ctx);
737 + if (!libhal_ctx_init(hal_ctx, &error)) {
738 + GST_ELEMENT_ERROR (src, LIBRARY, INIT,
739 + ("HAL context init failed"),
740 + ("libhal_ctx_init: %s: %s", error.name, error.message));
741 + libhal_ctx_free (hal_ctx);
745 + dbus_error_free (&error);
751 +gst_cdda2wav_hal_fini (LibHalContext *hal_ctx)
755 + dbus_error_init (&error);
756 + libhal_ctx_shutdown (hal_ctx, &error);
757 + libhal_ctx_free (hal_ctx);
758 + dbus_error_free (&error);
762 +gst_cdda2wav_hal_find_cdroms (GstCdda2Wav *src)
765 + LibHalContext *hal_ctx;
767 + char **drive_udis, **volume_udis;
768 + int num_drives, num_volumes;
770 + LibHalDrive *drive;
771 + dbus_bool_t has_audio;
773 + if ((hal_ctx = gst_cdda2wav_hal_init (src)) == NULL) {
776 + dbus_error_init (&error);
778 + drive_udis = libhal_find_device_by_capability (hal_ctx, "storage.cdrom",
779 + &num_drives, &error);
781 + if (dbus_error_is_set (&error) || drive_udis == NULL) {
785 + src->devices = calloc (num_drives + 1, sizeof (char *));
786 + src->has_audio = calloc (num_drives + 1, sizeof (boolean_t));
788 + for (i = j = 0; i < num_drives; i++) {
789 + raw_device = libhal_device_get_property_string (hal_ctx,
790 + drive_udis[i], "block.solaris.raw_device", &error);
791 + dbus_error_free (&error);
793 + if ((raw_device == NULL) || (strlen (raw_device) == 0)) {
794 + libhal_free_string (raw_device);
798 + src->devices[j] = strdup (raw_device);
799 + libhal_free_string (raw_device);
801 + /* check for audio disc in this drive */
802 + if ((drive = libhal_drive_from_udi (hal_ctx, drive_udis[i])) != NULL) {
803 + if ((volume_udis = libhal_drive_find_all_volumes (hal_ctx,
804 + drive, &num_volumes)) != NULL) {
806 + for (k = 0; k < num_volumes; k++) {
807 + src->has_audio[j] = (boolean_t)
808 + libhal_device_get_property_bool (hal_ctx,
809 + volume_udis[k], "volume.disc.has_audio", &error);
810 + dbus_error_free (&error);
811 + if (src->has_audio[j]) {
815 + libhal_free_string_array (volume_udis);
817 + libhal_drive_free (drive);
824 + libhal_free_string_array (drive_udis);
825 + dbus_error_free (&error);
827 + gst_cdda2wav_hal_fini (hal_ctx);
830 +#define HAVE_SYS_FORK_H /* XXX Need autoconf test */
831 +#ifdef HAVE_SYS_FORK_H
832 +#include <sys/fork.h>
837 +xpopen(FILE **pfpin, FILE **pfpout, FILE **pfperr, const char *cmd)
844 + in[0] = STDIN_FILENO;
845 + out[1] = STDOUT_FILENO;
846 + err[1] = STDERR_FILENO;
849 + return ((pid_t)-1);
852 + if (pipe(out) < 0) {
855 + return ((pid_t)-1);
859 + if (pipe(err) < 0) {
864 + return ((pid_t)-1);
868 +#ifdef FORK_NOSIGCHLD
869 + pid = vforkx(FORK_NOSIGCHLD|FORK_WAITPID);
871 + pid = vfork(); /* Need to find a way to deal with SIGCHLD and wait */
873 + if (pid == (pid_t)-1) {
874 + return ((pid_t)-1);
875 + } else if (pid > 0) {
878 + *pfpin = fdopen(in[1], "w");
879 + if (*pfpin == NULL) {
885 + kill(pid, SIGKILL);
886 + xpclose(NULL, NULL, NULL, pid);
887 + return ((pid_t)-1);
892 + *pfpout = fdopen(out[0], "r");
893 + if (*pfpout == NULL) {
897 + kill(pid, SIGKILL);
898 + xpclose(*pfpin, NULL, NULL, pid);
899 + return ((pid_t)-1);
904 + *pfperr = fdopen(err[0], "r");
905 + if (*pfperr == NULL) {
907 + kill(pid, SIGKILL);
908 + xpclose(*pfpin, *pfpout, NULL, pid);
909 + return ((pid_t)-1);
919 + if (in[0] != STDIN_FILENO) {
920 + dup2(in[0], STDIN_FILENO);
923 + if (out[1] != STDOUT_FILENO) {
924 + dup2(out[1], STDOUT_FILENO);
927 + if (err[1] != STDERR_FILENO) {
928 + dup2(err[1], STDERR_FILENO);
931 + execl("/bin/sh", "sh", "-c", cmd, (char *)0);
938 +xpclose(FILE *fpin, FILE *fpout, FILE *fperr, pid_t child)
953 + if (waitpid(child, &status, WNOHANG) == child)
955 + while (waitpid(child, &status, 0) < 0) {
956 + if (errno != EINTR) {