@@ -660,6 +660,12 @@ AG_GST_CHECK_FEATURE(CAIRO, [Cairo graph
AG_GST_PKG_CHECK_MODULES(CAIRO, cairo >= 1.0.0)
+translit(dnm, m, l) AM_CONDITIONAL(USE_CDDASRC, true)
+AG_GST_CHECK_FEATURE(CDDASRC, [HAL libraries], cddasrc, [
+ AG_GST_PKG_CHECK_MODULES(CDDASRC, [hal >= 0.5.8, hal-storage >= 0.5.8, dbus-1 >= 0.32])
translit(dnm, m, l) AM_CONDITIONAL(USE_ESD, true)
AG_GST_CHECK_FEATURE(ESD, [ESounD sound daemon], esdsink, [
@@ -928,6 +934,7 @@ AM_CONDITIONAL(USE_DIRECTDRAW, false)
AM_CONDITIONAL(USE_DIRECTSOUND, false)
AM_CONDITIONAL(USE_DV1394, false)
AM_CONDITIONAL(USE_ESD, false)
+AM_CONDITIONAL(USE_CDDASRC, false)
AM_CONDITIONAL(USE_FLAC, false)
AM_CONDITIONAL(USE_GCONF, false)
AM_CONDITIONAL(USE_GCONFTOOL, false)
@@ -131,6 +137,7 @@ SUBDIRS = \
---
/dev/null 2007-03-19 01:47:57.000000000 +0800
+libgstcddasrc_la_SOURCES = \
+libgstcddasrc_la_CFLAGS = \
+ $(GST_PLUGINS_BASE_CFLAGS) \
+libgstcddasrc_la_LIBADD = \
+ $(GST_PLUGINS_BASE_LIBS) -lgstcdda-$(GST_MAJORMINOR) \
+libgstcddasrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
---
/dev/null 2008-04-02 16:29:27.000000000 -0500
+ * Copyright (C) 2007 Sun Microsystems, Inc.,
+ * Brian Cameron <Brian.Cameron@sun.com>,
+ * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
+ * 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_CDDASRC_H__
+#define __GST_CDDASRC_H__
+#define GST_TYPE_CDDASRC (gst_cddasrc_get_type())
+#define GST_CDDASRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CDDASRC,GstCddaSrc))
+#define GST_CDDASRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CDDASRC,GstCddaSrcClass))
+#define GST_IS_CDDASRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CDDASRC))
+#define GST_IS_CDDASRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDDASRC))
+#define GST_CDDASRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDASRCSRC, GstCddaSrcClass))
+typedef struct _GstCddaSrc GstCddaSrc;
+typedef struct _GstCddaSrcClass GstCddaSrcClass;
+#define CDDASRC_BSIZE 2352
+ * The cddasrc object structure.
+ GstCddaBaseSrc cddabasesrc;
+struct _GstCddaSrcClass {
+ GstCddaBaseSrcClass parent_class;
+GType gst_cddasrc_get_type (void);
+#endif /* __GST_CDDASRC_H__ */
---
/dev/null 2008-04-02 16:29:27.000000000 -0500
+ * Copyright (C) 2007 Sun Microsystems, Inc.,
+ * Brian Cameron <Brian.Cameron@sun.com>,
+ * Artem Kachitchkine <Artem.Kachitchkine@sun.com>
+ * 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.
+ * SECTION:element-cddasrc
+ * @short_description: Reads raw audio from an Audio CD
+ * @see_also: GstCddaBaseSrc
+ * cddasrc reads and extracts raw audio from Audio CDs using kernel
+ * <title>Example launch line</title>
+ * gst-launch cddasrc track=5 ! audioconvert ! vorbisenc ! oggmux ! filesink location=
track5.ogg+ * This pipeline extracts track 5 of the audio CD and encodes it into an
+#define DEFAULT_READ_SPEED -1
+GST_DEBUG_CATEGORY_STATIC (gst_cddasrc_debug);
+#define GST_CAT_DEFAULT gst_cddasrc_debug
+GST_BOILERPLATE (GstCddaSrc, gst_cddasrc, GstCddaBaseSrc,
+ GST_TYPE_CDDA_BASE_SRC)
+static void gst_cddasrc_finalize (GObject * obj);
+static GstBuffer *gst_cddasrc_read_sector (GstCddaBaseSrc * src,
+static gboolean gst_cddasrc_open (GstCddaBaseSrc * src,
+static void gst_cddasrc_close (GstCddaBaseSrc * src);
+static gchar **gst_cddasrc_probe_devices (GstCddaBaseSrc * cddabasesrc);
+static gchar *gst_cddasrc_get_default_device (GstCddaBaseSrc * cddabasesrc);
+static void gst_cddasrc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_cddasrc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_cddasrc_hal_find_cdroms (GstCddaSrc *);
+static const GstElementDetails cddasrc_details =
+GST_ELEMENT_DETAILS ("CD Audio (cdda) Source",
+ "Brian Cameron <Brian.Cameron@sun.com>, " "Artem Kachitchkine <Artem.Kachitchkine@sun.com>");
+gst_cddasrc_base_init (gpointer g_class)
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ gst_element_class_set_details (element_class, &cddasrc_details);
+gst_cddasrc_init (GstCddaSrc * src, GstCddaSrcClass * klass)
+gst_cddasrc_class_init (GstCddaSrcClass * klass)
+ GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->set_property = gst_cddasrc_set_property;
+ gobject_class->get_property = gst_cddasrc_get_property;
+ gobject_class->finalize = gst_cddasrc_finalize;
+ cddabasesrc_class->open = gst_cddasrc_open;
+ cddabasesrc_class->close = gst_cddasrc_close;
+ cddabasesrc_class->read_sector = gst_cddasrc_read_sector;
+ cddabasesrc_class->get_default_device = gst_cddasrc_get_default_device;
+ cddabasesrc_class->probe_devices = gst_cddasrc_probe_devices;
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED,
+ g_param_spec_int ("read-speed", "Read speed",
+ "Read from device at the specified speed (-1 = default)", -1, 100,
+ DEFAULT_READ_SPEED, G_PARAM_READWRITE));
+gst_cddasrc_probe_devices (GstCddaBaseSrc * cddabasesrc)
+ GstCddaSrc *src = GST_CDDASRC (cddabasesrc);
+ if (src->devices != NULL) {
+ gst_cddasrc_hal_find_cdroms (src);
+gst_cddasrc_get_default_device (GstCddaBaseSrc * cddabasesrc)
+ src = GST_CDDASRC (cddabasesrc);
+ if (src->devices == NULL) {
+ gst_cddasrc_probe_devices (cddabasesrc);
+ if (src->devices == NULL) {
+ /* prefer a drive with an audio disc, otherwise pick first */
+ for (i = 0; src->devices[i] != NULL; i++) {
+ if (src->has_audio[i]) {
+ GST_LOG_OBJECT (src, "returning default device: %s", GST_STR_NULL (ret));
+cddasrc_init_device (GstCddaSrc *src)
+ /* spin up and set max speed */
+ if (ioctl (src->fd, CDROMSTART) < 0)
+cddasrc_read_toc (GstCddaSrc *src)
+ struct cdrom_tochdr toc_hdr;
+ struct cdrom_tocentry toc_entry;
+ /* determine track count */
+ if (ioctl (src->fd, CDROMREADTOCHDR, &toc_hdr) < 0) {
+ /* retrieve track entries */
+ for (i = 1; i <= src->track_count; i++) {
+ GstCddaBaseSrcTrack track = { 0, };
+ if (ioctl (src->fd, CDROMREADTOCENTRY, &toc_entry) == -1)
+ /* End of the track is the start of the next track */
+ if (i == src->track_count)
+ if (ioctl (src->fd, CDROMREADTOCENTRY, &toc_entry) == -1)
+ gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
+gst_cddasrc_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
+ GstCddaSrc *src = GST_CDDASRC (cddabasesrc);
+ GST_LOG_OBJECT (src, "Trying to open device %s", device);
+ g_assert (device != NULL);
+ if ((src->fd = open (device, O_RDONLY)) < 0) {
+ GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+ (_("Could not open CD device for reading.")),
+ ("open () of %s failed", device));
+ if (!cddasrc_init_device (src)) {
+ GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+ (_("Could not open CD device for reading.")),
+ ret = cddasrc_read_toc (src);
+gst_cddasrc_close (GstCddaBaseSrc * cddabasesrc)
+ GstCddaSrc *src = GST_CDDASRC (cddabasesrc);
+cddasrc_byte_swap (guint8 *buf, uint_t len)
+ for (i=0; i < len; i=i+2) {
+cddasrc_read (GstCddaSrc *src, guint8 *buf, uint_t addr, uint_t len)
+ struct cdrom_cdda cdda;
+ if (ioctl (src->fd, CDROMCDDA, &cdda) < 0) {
+ if (ioctl (src->fd, CDROMCDDA, &cdda) < 0) {
+ GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
+ (_("Failed reading CD.")),
+ cddasrc_byte_swap (buf, len * CDDASRC_BSIZE);
+gst_cddasrc_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
+ GstCddaSrc *src = GST_CDDASRC (cddabasesrc);
+ size_t len = CDDASRC_BSIZE;
+ buf = gst_buffer_new_and_alloc (CDDASRC_BSIZE);
+ if (!cddasrc_read (src, GST_BUFFER_DATA (buf), sector, 1)) {
+ gst_buffer_unref (buf);
+gst_cddasrc_finalize (GObject * obj)
+ GstCddaSrc *src = GST_CDDASRC (obj);
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+plugin_init (GstPlugin * plugin)
+ GST_DEBUG_CATEGORY_INIT (gst_cddasrc_debug, "cddasrc", 0,
+ if (!gst_element_register (plugin, "cddasrc", GST_RANK_SECONDARY,
+ GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+gst_cddasrc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+ GstCddaSrc *src = GST_CDDASRC (object);
+ read_speed = g_value_get_int (value);
+ * Solaris only supports certain speeds, so use the
+ * fastest available speed.
+ solaris_speed = CDROM_NORMAL_SPEED;
+ else if (read_speed >= 2 && read_speed < 4)
+ solaris_speed = CDROM_DOUBLE_SPEED;
+ else if (read_speed >= 4 && read_speed < 12)
+ solaris_speed = CDROM_QUAD_SPEED;
+ else if (read_speed == 12)
+ solaris_speed = CDROM_TWELVE_SPEED;
+ else if (read_speed >= 12)
+ solaris_speed = CDROM_MAXIMUM_SPEED;
+ * This ioctl will return -1 if the drive doesn't support
+ ioctl (src->fd, CDROMSDRVSPEED, solaris_speed);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+gst_cddasrc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+ GstCddaSrc *src = GST_CDDASRC (object);
+ * Solaris only supports certain speeds, so return
+ * supported values. Just say MAXIMUM is 100 since
+ * Solaris ioctls doesn't let you find out the actual
+ * drive speed, but we know it is max (100).
+ ret = ioctl (src->fd, CDROMGDRVSPEED, &solaris_speed);
+ read_speed = -1; /* drive does not support getting speed */
+ if (solaris_speed == CDROM_NORMAL_SPEED)
+ else if (solaris_speed == CDROM_DOUBLE_SPEED)
+ else if (solaris_speed == CDROM_QUAD_SPEED)
+ else if (solaris_speed == CDROM_TWELVE_SPEED)
+ else if (solaris_speed == CDROM_MAXIMUM_SPEED)
+ g_value_set_int (value, read_speed);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+/* ===== HAL stuff ===== */
+gst_cddasrc_hal_init (GstCddaSrc *src)
+ LibHalContext *hal_ctx = NULL;
+ dbus_error_init (&error);
+ if ((hal_ctx = libhal_ctx_new ()) == NULL) {
+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
+ ("failed to initialize HAL"), ("failed to initialize HAL"));
+ if (!libhal_ctx_set_dbus_connection(hal_ctx,
+ dbus_bus_get (DBUS_BUS_SYSTEM, &error))) {
+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
+ ("DBus connection failed"),
+ libhal_ctx_free (hal_ctx);
+ if (!libhal_ctx_init(hal_ctx, &error)) {
+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
+ ("HAL context init failed"),
+ libhal_ctx_free (hal_ctx);
+ dbus_error_free (&error);
+gst_cddasrc_hal_fini (LibHalContext *hal_ctx)
+ dbus_error_init (&error);
+ libhal_ctx_shutdown (hal_ctx, &error);
+ libhal_ctx_free (hal_ctx);
+ dbus_error_free (&error);
+gst_cddasrc_hal_find_cdroms (GstCddaSrc *src)
+ LibHalContext *hal_ctx;
+ char **drive_udis, **volume_udis;
+ int num_drives, num_volumes;
+ if ((hal_ctx = gst_cddasrc_hal_init (src)) == NULL) {
+ dbus_error_init (&error);
+ drive_udis = libhal_find_device_by_capability (hal_ctx, "
storage.cdrom",
+ if (dbus_error_is_set (&error) || drive_udis == NULL) {
+ src->devices = calloc (num_drives + 1, sizeof (char *));
+ src->has_audio = calloc (num_drives + 1, sizeof (boolean_t));
+ for (i = j = 0; i < num_drives; i++) {
+ raw_device = libhal_device_get_property_string (hal_ctx,
+ dbus_error_free (&error);
+ if ((raw_device == NULL) || (strlen (raw_device) == 0)) {
+ libhal_free_string (raw_device);
+ src->devices[j] = strdup (raw_device);
+ libhal_free_string (raw_device);
+ /* check for audio disc in this drive */
+ if ((drive = libhal_drive_from_udi (hal_ctx, drive_udis[i])) != NULL) {
+ if ((volume_udis = libhal_drive_find_all_volumes (hal_ctx,
+ drive, &num_volumes)) != NULL) {
+ for (k = 0; k < num_volumes; k++) {
+ src->has_audio[j] = (boolean_t)
+ libhal_device_get_property_bool (hal_ctx,
+ dbus_error_free (&error);
+ if (src->has_audio[j]) {
+ libhal_free_string_array (volume_udis);
+ libhal_drive_free (drive);
+ libhal_free_string_array (drive_udis);
+ dbus_error_free (&error);
+ gst_cddasrc_hal_fini (hal_ctx);