]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/cdio/gstcdiocddasrc.c
gst_element_class_set_details => gst_element_class_set_details_simple
[glsdk/gst-plugins-ugly0-10.git] / ext / cdio / gstcdiocddasrc.c
1 /* GStreamer
2  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
20 /**
21  * SECTION:element-cdiocddasrc
22  * @short_description: Reads raw audio from an Audio CD
23  * @see_also: GstCdParanoiaSrc, GstCddaBaseSrc
24  *
25  * <refsect2>
26  * <para>
27  * cdiocddasrc reads and extracts raw audio from Audio CDs. It can operate
28  * in one of two modes:
29  * <itemizedlist>
30  *  <listitem><para>
31  *    treat each track as a separate stream, counting time from the start
32  *    of the track to the end of the track and posting EOS at the end of
33  *    a track, or
34  *  </para></listitem>
35  *  <listitem><para>
36  *    treat the entire disc as one stream, counting time from the start of
37  *    the first track to the end of the last track, posting EOS only at
38  *    the end of the last track.
39  *  </para></listitem>
40  * </itemizedlist>
41  * </para>
42  * <para>
43  * With a recent-enough version of libcdio, the element will extract
44  * CD-TEXT if this is supported by the CD-drive and CD-TEXT information
45  * is available on the CD. The information will be posted on the bus in
46  * form of a tag message.
47  * </para>
48  * <para>
49  * When opened, the element will also calculate a CDDB disc ID and a
50  * MusicBrainz disc ID, which applications can use to query online
51  * databases for artist/title information. These disc IDs will also be
52  * posted on the bus as part of the tag messages.
53  * </para>
54  * <para>
55  * cdiocddasrc supports the GstUriHandler interface, so applications can use
56  * playbin with cdda://&lt;track-number&gt; URIs for playback (they will have
57  * to connect to playbin's notify::source signal and set the device on the
58  * cd source in the notify callback if they want to set the device property).
59  * Applications should use seeks in "track" format to switch between different
60  * tracks of the same CD (passing a new cdda:// URI to playbin involves opening
61  * and closing the CD device, which is much slower).
62  * </para>
63  * <title>Example launch line</title>
64  * <para>
65  * <programlisting>
66  * gst-launch cdiocddasrc track=5 device=/dev/cdrom ! audioconvert ! vorbisenc ! oggmux ! filesink location=track5.ogg
67  * </programlisting>
68  * This pipeline extracts track 5 of the audio CD and encodes it into an
69  * Ogg/Vorbis file.
70  * </para>
71  * </refsect2>
72  */
74 #ifdef HAVE_CONFIG_H
75 #include "config.h"
76 #endif
78 #include "gstcdio.h"
79 #include "gstcdiocddasrc.h"
81 #include <gst/gst.h>
82 #include "gst/gst-i18n-plugin.h"
84 #include <sys/types.h>
85 #include <stdlib.h>
86 #include <string.h>
87 #include <errno.h>
89 #define DEFAULT_READ_SPEED   -1
91 enum
92 {
93   PROP_0 = 0,
94   PROP_READ_SPEED
95 };
97 GST_BOILERPLATE (GstCdioCddaSrc, gst_cdio_cdda_src, GstCddaBaseSrc,
98     GST_TYPE_CDDA_BASE_SRC);
100 static void gst_cdio_cdda_src_finalize (GObject * obj);
101 static void gst_cdio_cdda_src_set_property (GObject * object, guint prop_id,
102     const GValue * value, GParamSpec * pspec);
103 static void gst_cdio_cdda_src_get_property (GObject * object, guint prop_id,
104     GValue * value, GParamSpec * pspec);
106 static gchar *gst_cdio_cdda_src_get_default_device (GstCddaBaseSrc * src);
107 static GstBuffer *gst_cdio_cdda_src_read_sector (GstCddaBaseSrc * src,
108     gint sector);
109 static gboolean gst_cdio_cdda_src_open (GstCddaBaseSrc * src,
110     const gchar * device);
111 static void gst_cdio_cdda_src_close (GstCddaBaseSrc * src);
113 static void
114 gst_cdio_cdda_src_base_init (gpointer g_class)
116   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
118   gst_element_class_set_details_simple (element_class, "CD audio source (CDDA)",
119       "Source/File",
120       "Read audio from CD using libcdio",
121       "Tim-Philipp Müller <tim centricular net>");
124 static gchar *
125 gst_cdio_cdda_src_get_default_device (GstCddaBaseSrc * cddabasesrc)
127   GstCdioCddaSrc *src;
128   gchar *default_device, *ret;
130   src = GST_CDIO_CDDA_SRC (cddabasesrc);
132   /* src->cdio may be NULL here */
133   default_device = cdio_get_default_device (src->cdio);
135   ret = g_strdup (default_device);
136   free (default_device);
138   GST_LOG_OBJECT (src, "returning default device: %s", GST_STR_NULL (ret));
140   return ret;
143 static gchar **
144 gst_cdio_cdda_src_probe_devices (GstCddaBaseSrc * cddabasesrc)
146   char **devices, **ret, **d;
148   /* FIXME: might return the same hardware device twice, e.g.
149    * as /dev/cdrom and /dev/dvd - gotta do something more sophisticated */
150   devices = cdio_get_devices (DRIVER_DEVICE);
152   if (devices == NULL)
153     goto no_devices;
155   if (*devices == NULL)
156     goto empty_devices;
158   ret = g_strdupv (devices);
159   for (d = devices; *d != NULL; ++d) {
160     GST_DEBUG_OBJECT (cddabasesrc, "device: %s", GST_STR_NULL (*d));
161     free (*d);
162   }
163   free (devices);
165   return ret;
167   /* ERRORS */
168 no_devices:
169   {
170     GST_DEBUG_OBJECT (cddabasesrc, "no devices found");
171     return NULL;
172   }
173 empty_devices:
174   {
175     GST_DEBUG_OBJECT (cddabasesrc, "empty device list found");
176     free (devices);
177     return NULL;
178   }
181 static GstBuffer *
182 gst_cdio_cdda_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
184   GstCdioCddaSrc *src;
185   GstBuffer *buf;
187   src = GST_CDIO_CDDA_SRC (cddabasesrc);
189   /* can't use pad_alloc because we can't return the GstFlowReturn */
190   buf = gst_buffer_new_and_alloc (CDIO_CD_FRAMESIZE_RAW);
192   if (cdio_read_audio_sector (src->cdio, GST_BUFFER_DATA (buf), sector) != 0)
193     goto read_failed;
195   return buf;
197   /* ERRORS */
198 read_failed:
199   {
200     GST_WARNING_OBJECT (src, "read at sector %d failed!", sector);
201     GST_ELEMENT_ERROR (src, RESOURCE, READ,
202         (_("Could not read from CD.")),
203         ("cdio_read_audio_sector at %d failed: %s", sector,
204             g_strerror (errno)));
205     gst_buffer_unref (buf);
206     return NULL;
207   }
210 static gboolean
211 notcdio_track_is_audio_track (const CdIo * p_cdio, track_t i_track)
213   return (cdio_get_track_format (p_cdio, i_track) == TRACK_FORMAT_AUDIO);
216 static gboolean
217 gst_cdio_cdda_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
219   GstCdioCddaSrc *src;
220   discmode_t discmode;
221   gint first_track, num_tracks, i;
223   src = GST_CDIO_CDDA_SRC (cddabasesrc);
225   g_assert (device != NULL);
226   g_assert (src->cdio == NULL);
228   GST_LOG_OBJECT (src, "trying to open device %s", device);
230   if (!(src->cdio = cdio_open (device, DRIVER_UNKNOWN)))
231     goto open_failed;
233   discmode = cdio_get_discmode (src->cdio);
234   GST_LOG_OBJECT (src, "discmode: %d", (gint) discmode);
236   if (discmode != CDIO_DISC_MODE_CD_DA && discmode != CDIO_DISC_MODE_CD_MIXED)
237     goto not_audio;
239   first_track = cdio_get_first_track_num (src->cdio);
240   num_tracks = cdio_get_num_tracks (src->cdio);
242   if (num_tracks <= 0 || first_track < 0)
243     return TRUE;                /* base class will generate 'has no tracks' error */
245   if (src->read_speed != -1)
246     cdio_set_speed (src->cdio, src->read_speed);
248   gst_cdio_add_cdtext_album_tags (GST_OBJECT_CAST (src), src->cdio,
249       cddabasesrc->tags);
251   GST_LOG_OBJECT (src, "%u tracks, first track: %d", num_tracks, first_track);
253   for (i = 0; i < num_tracks; ++i) {
254     GstCddaBaseSrcTrack track = { 0, };
255     gint len_sectors;
257     len_sectors = cdio_get_track_sec_count (src->cdio, i + first_track);
259     track.num = i + first_track;
260     track.is_audio = notcdio_track_is_audio_track (src->cdio, i + first_track);
262     /* Note: LSN/LBA confusion all around us; in any case, this does
263      * the right thing here (for cddb id calculations etc. as well) */
264     track.start = cdio_get_track_lsn (src->cdio, i + first_track);
265     track.end = track.start + len_sectors - 1;  /* -1? */
266     track.tags = gst_cdio_get_cdtext (GST_OBJECT (src), src->cdio,
267         i + first_track);
269     gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
270   }
271   return TRUE;
273   /* ERRORS */
274 open_failed:
275   {
276     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
277         (_("Could not open CD device for reading.")),
278         ("cdio_open() failed: %s", g_strerror (errno)));
279     return FALSE;
280   }
281 not_audio:
282   {
283     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
284         (_("Disc is not an Audio CD.")), ("discmode: %d", (gint) discmode));
286     cdio_destroy (src->cdio);
287     src->cdio = NULL;
288     return FALSE;
289   }
292 static void
293 gst_cdio_cdda_src_close (GstCddaBaseSrc * cddabasesrc)
295   GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (cddabasesrc);
297   if (src->cdio) {
298     cdio_destroy (src->cdio);
299     src->cdio = NULL;
300   }
303 static void
304 gst_cdio_cdda_src_init (GstCdioCddaSrc * src, GstCdioCddaSrcClass * klass)
306   src->read_speed = DEFAULT_READ_SPEED; /* don't need atomic access here */
307   src->cdio = NULL;
310 static void
311 gst_cdio_cdda_src_finalize (GObject * obj)
313   GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (obj);
315   if (src->cdio) {
316     cdio_destroy (src->cdio);
317     src->cdio = NULL;
318   }
320   G_OBJECT_CLASS (parent_class)->finalize (obj);
323 static void
324 gst_cdio_cdda_src_class_init (GstCdioCddaSrcClass * klass)
326   GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
327   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
329   gobject_class->set_property = gst_cdio_cdda_src_set_property;
330   gobject_class->get_property = gst_cdio_cdda_src_get_property;
331   gobject_class->finalize = gst_cdio_cdda_src_finalize;
333   cddabasesrc_class->open = gst_cdio_cdda_src_open;
334   cddabasesrc_class->close = gst_cdio_cdda_src_close;
335   cddabasesrc_class->read_sector = gst_cdio_cdda_src_read_sector;
336   cddabasesrc_class->probe_devices = gst_cdio_cdda_src_probe_devices;
337   cddabasesrc_class->get_default_device = gst_cdio_cdda_src_get_default_device;
339   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED,
340       g_param_spec_int ("read-speed", "Read speed",
341           "Read from device at the specified speed (-1 = default)", -1, 100,
342           DEFAULT_READ_SPEED, G_PARAM_READWRITE));
345 static void
346 gst_cdio_cdda_src_set_property (GObject * object, guint prop_id,
347     const GValue * value, GParamSpec * pspec)
349   GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (object);
351   switch (prop_id) {
352     case PROP_READ_SPEED:{
353       gint speed;
355       speed = g_value_get_int (value);
356       g_atomic_int_set (&src->read_speed, speed);
357       break;
358     }
359     default:
360       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
361       break;
362   }
365 static void
366 gst_cdio_cdda_src_get_property (GObject * object, guint prop_id,
367     GValue * value, GParamSpec * pspec)
369   GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (object);
371   switch (prop_id) {
372     case PROP_READ_SPEED:{
373       gint speed;
375       speed = g_atomic_int_get (&src->read_speed);
376       g_value_set_int (value, speed);
377       break;
378     }
379     default:
380       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
381       break;
382   }