2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * <2006> Wim Taymans <wim@fluendo.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
29 GST_DEBUG_CATEGORY_STATIC (gst_cdaudio_debug);
30 #define GST_CAT_DEFAULT gst_cdaudio_debug
32 #define GST_TYPE_CDAUDIO (gst_cdaudio_get_type())
33 #define GST_CDAUDIO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CDAUDIO,GstCDAudio))
34 #define GST_CDAUDIO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CDAUDIO,GstCDAudioClass))
35 #define GST_IS_CDAUDIO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CDAUDIO))
36 #define GST_IS_CDAUDIO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDAUDIO))
38 typedef struct _GstCDAudio GstCDAudio;
39 typedef struct _GstCDAudioClass GstCDAudioClass;
54 struct disc_info info;
55 struct disc_volume volume;
60 struct _GstCDAudioClass
62 GstElementClass parent_class;
64 void (*close_tray) (GstElement * element);
65 /* signal callbacks */
66 void (*track_change) (GstElement * element, guint track);
69 #define DEFAULT_DEVICE "/dev/cdrom"
70 #define DEFAULT_VOLUME_FR 255
71 #define DEFAULT_VOLUME_FL 255
72 #define DEFAULT_VOLUME_BR 255
73 #define DEFAULT_VOLUME_BL 255
94 static void gst_cdaudio_finalize (GObject * object);
96 static void gst_cdaudio_set_property (GObject * object, guint prop_id,
97 const GValue * value, GParamSpec * spec);
98 static void gst_cdaudio_get_property (GObject * object, guint prop_id,
99 GValue * value, GParamSpec * spec);
100 static GstStateChangeReturn gst_cdaudio_change_state (GstElement * element,
101 GstStateChange transition);
103 static const GstQueryType *gst_cdaudio_get_query_types (GstElement * element);
104 static gboolean gst_cdaudio_query (GstElement * element, GstQuery * query);
106 static gboolean gst_cdaudio_send_event (GstElement * element, GstEvent * event);
108 static void cdaudio_uri_handler_init (gpointer g_iface, gpointer iface_data);
110 static GstFormat track_format;
111 static GstFormat sector_format;
113 static GstElementClass *parent_class;
114 static guint gst_cdaudio_signals[LAST_SIGNAL] = { 0 };
117 _do_init (GType cdaudio_type)
119 static const GInterfaceInfo urihandler_info = {
120 cdaudio_uri_handler_init,
125 g_type_add_interface_static (cdaudio_type, GST_TYPE_URI_HANDLER,
129 GType gst_cdaudio_get_type (void);
130 GST_BOILERPLATE_FULL (GstCDAudio, gst_cdaudio, GstElement, GST_TYPE_ELEMENT,
134 gst_cdaudio_base_init (gpointer g_class)
136 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
138 gst_element_class_set_details_simple (element_class, "CD player",
140 "Play CD audio through the CD Drive", "Wim Taymans <wim@fluendo.com>");
142 /* Register the track and sector format */
143 track_format = gst_format_register ("track", "CD track");
144 sector_format = gst_format_register ("sector", "CD sector");
148 gst_cdaudio_class_init (GstCDAudioClass * klass)
150 GObjectClass *gobject_klass;
151 GstElementClass *gstelement_klass;
153 gobject_klass = (GObjectClass *) klass;
154 gstelement_klass = (GstElementClass *) klass;
156 parent_class = g_type_class_peek_parent (klass);
158 gobject_klass->set_property = gst_cdaudio_set_property;
159 gobject_klass->get_property = gst_cdaudio_get_property;
161 g_object_class_install_property (gobject_klass, PROP_DEVICE,
162 g_param_spec_string ("device", "Device", "CDROM device",
163 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164 g_object_class_install_property (gobject_klass, PROP_VOLUME_FL,
165 g_param_spec_int ("volume-fl", "Volume fl", "Front left volume",
166 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
167 g_object_class_install_property (gobject_klass, PROP_VOLUME_FR,
168 g_param_spec_int ("volume-fr", "Volume fr", "Front right volume",
169 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
170 g_object_class_install_property (gobject_klass, PROP_VOLUME_BL,
171 g_param_spec_int ("volume-bl", "Volume bl", "Back left volume",
172 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
173 g_object_class_install_property (gobject_klass, PROP_VOLUME_BR,
174 g_param_spec_int ("volume-br", "Volume br", "Back right volume",
175 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
177 gst_cdaudio_signals[TRACK_CHANGE] =
178 g_signal_new ("track-change", G_TYPE_FROM_CLASS (klass),
179 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstCDAudioClass, track_change), NULL,
180 NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
182 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_cdaudio_finalize);
184 gstelement_klass->change_state = GST_DEBUG_FUNCPTR (gst_cdaudio_change_state);
185 gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_cdaudio_send_event);
186 gstelement_klass->get_query_types =
187 GST_DEBUG_FUNCPTR (gst_cdaudio_get_query_types);
188 gstelement_klass->query = GST_DEBUG_FUNCPTR (gst_cdaudio_query);
190 GST_DEBUG_CATEGORY_INIT (gst_cdaudio_debug, "cdaudio", 0, "CDAudio Element");
194 gst_cdaudio_init (GstCDAudio * cdaudio, GstCDAudioClass * g_class)
196 cdaudio->device = g_strdup (DEFAULT_DEVICE);
197 cdaudio->volume.vol_front.right = DEFAULT_VOLUME_FR;
198 cdaudio->volume.vol_front.left = DEFAULT_VOLUME_FL;
199 cdaudio->volume.vol_back.right = DEFAULT_VOLUME_BR;
200 cdaudio->volume.vol_back.left = DEFAULT_VOLUME_BL;
202 cdaudio->was_playing = FALSE;
203 cdaudio->timer = g_timer_new ();
205 GST_OBJECT_FLAG_SET (cdaudio, GST_ELEMENT_IS_SINK);
209 gst_cdaudio_finalize (GObject * object)
211 GstCDAudio *cdaudio = GST_CDAUDIO (object);
213 g_timer_destroy (cdaudio->timer);
214 g_free (cdaudio->device);
216 G_OBJECT_CLASS (parent_class)->finalize (object);
220 gst_cdaudio_set_property (GObject * object, guint prop_id, const GValue * value,
225 cdaudio = GST_CDAUDIO (object);
229 g_free (cdaudio->device);
230 cdaudio->device = g_value_dup_string (value);
233 cdaudio->volume.vol_front.right = g_value_get_int (value);
236 cdaudio->volume.vol_front.left = g_value_get_int (value);
239 cdaudio->volume.vol_back.right = g_value_get_int (value);
242 cdaudio->volume.vol_back.left = g_value_get_int (value);
250 gst_cdaudio_get_property (GObject * object, guint prop_id, GValue * value,
255 cdaudio = GST_CDAUDIO (object);
259 g_value_set_string (value, cdaudio->device);
262 g_value_set_int (value, cdaudio->volume.vol_front.right);
265 g_value_set_int (value, cdaudio->volume.vol_front.left);
268 g_value_set_int (value, cdaudio->volume.vol_back.right);
271 g_value_set_int (value, cdaudio->volume.vol_back.left);
279 debug_track_info (GstCDAudio * cdaudio)
283 for (i = 0; i < cdaudio->info.disc_total_tracks; i++) {
284 GST_DEBUG_OBJECT (cdaudio, "%d %d %d %d:%02d", i,
285 cdaudio->info.disc_track[i].track_length.frames,
286 cdaudio->info.disc_track[i].track_pos.frames,
287 cdaudio->info.disc_track[i].track_length.minutes,
288 cdaudio->info.disc_track[i].track_length.seconds);
292 static GstStateChangeReturn
293 gst_cdaudio_change_state (GstElement * element, GstStateChange transition)
296 GstStateChangeReturn ret;
299 cdaudio = GST_CDAUDIO (element);
301 switch (transition) {
302 case GST_STATE_CHANGE_NULL_TO_READY:
304 case GST_STATE_CHANGE_READY_TO_PAUSED:
305 if ((res = cd_init_device (cdaudio->device)) < 0)
308 cdaudio->cd_desc = res;
311 if ((res = cd_close (cdaudio->cd_desc)) < 0)
314 if ((res = cd_stat (cdaudio->cd_desc, &cdaudio->info)) < 0) {
315 /* we just give a warning here */
316 GST_ELEMENT_WARNING (cdaudio, LIBRARY, INIT,
317 ("Could not retrieve CD track info."), (NULL));
319 debug_track_info (cdaudio);
320 cdaudio->discid = cddb_discid (cdaudio->cd_desc);
321 /* FIXME, post message with discid */
323 cdaudio->was_playing = FALSE;
325 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
327 if (cdaudio->was_playing)
328 res = cd_resume (cdaudio->cd_desc);
330 res = cd_play (cdaudio->cd_desc, 1);
335 cdaudio->was_playing = TRUE;
336 g_timer_start (cdaudio->timer);
343 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
345 switch (transition) {
346 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
347 if ((res = cd_pause (cdaudio->cd_desc)) < 0)
349 g_timer_stop (cdaudio->timer);
351 case GST_STATE_CHANGE_PAUSED_TO_READY:
352 if ((res = cd_stop (cdaudio->cd_desc)) < 0)
354 if ((res = cd_finish (cdaudio->cd_desc)) < 0)
356 cdaudio->cd_desc = -1;
358 case GST_STATE_CHANGE_READY_TO_NULL:
368 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
369 ("Could not init CD device %s. (%d)", cdaudio->device, res), (NULL));
370 cdaudio->cd_desc = -1;
371 return GST_STATE_CHANGE_FAILURE;
375 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
376 ("Could not close CD tray for device %s. (%d)", cdaudio->device, res),
378 return GST_STATE_CHANGE_FAILURE;
382 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
383 ("Could not play CD device %s. (%d)", cdaudio->device, res), (NULL));
384 return GST_STATE_CHANGE_FAILURE;
388 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
389 ("Could not pause CD device %s. (%d)", cdaudio->device, res), (NULL));
390 return GST_STATE_CHANGE_FAILURE;
394 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
395 ("Could not stop CD device %s. (%d)", cdaudio->device, res), (NULL));
396 return GST_STATE_CHANGE_FAILURE;
400 GST_ELEMENT_ERROR (cdaudio, LIBRARY, INIT,
401 ("Could not finish CD device %s. (%d)", cdaudio->device, res), (NULL));
402 return GST_STATE_CHANGE_FAILURE;
407 gst_cdaudio_send_event (GstElement * element, GstEvent * event)
412 cdaudio = GST_CDAUDIO (element);
414 switch (GST_EVENT_TYPE (event)) {
420 GstSeekType start_type, stop_type;
424 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
427 /* FIXME, implement more formats */
428 if (format != GST_FORMAT_TIME)
434 if (start_type != GST_SEEK_TYPE_SET)
437 ret = cd_play_pos (cdaudio->cd_desc, 1, start / GST_SECOND);
447 gst_event_unref (event);
454 GST_DEBUG_OBJECT (cdaudio, "only seek in TIME is supported");
460 GST_DEBUG_OBJECT (cdaudio, "only seek with 1.0 rate is supported");
466 GST_DEBUG_OBJECT (cdaudio, "only seek SET is supported");
472 GST_DEBUG_OBJECT (cdaudio, "seek failed");
478 static const GstQueryType *
479 gst_cdaudio_get_query_types (GstElement * element)
481 static const GstQueryType query_types[] = {
491 gst_cdaudio_query (GstElement * element, GstQuery * query)
498 cdaudio = GST_CDAUDIO (element);
500 GST_LOG_OBJECT (element, "handling %s query",
501 gst_query_type_get_name (GST_QUERY_TYPE (query)));
503 /* take new snapshot every 1000 miliseconds */
504 seconds = g_timer_elapsed (cdaudio->timer, µs);
505 if (micros > 1000 || seconds > 1) {
506 cd_stat (cdaudio->cd_desc, &cdaudio->info);
507 g_timer_start (cdaudio->timer);
510 switch (GST_QUERY_TYPE (query)) {
511 case GST_QUERY_DURATION:
513 GstFormat dest_format;
516 gst_query_parse_duration (query, &dest_format, NULL);
518 switch (dest_format) {
519 case GST_FORMAT_TIME:
520 dest_val = (cdaudio->info.disc_length.minutes * 60 +
521 cdaudio->info.disc_length.seconds) * GST_SECOND;
525 if (dest_format == track_format) {
526 dest_val = cdaudio->info.disc_total_tracks;
534 gst_query_set_duration (query, dest_format, dest_val);
537 case GST_QUERY_POSITION:
539 GstFormat dest_format;
542 gst_query_parse_position (query, &dest_format, NULL);
544 switch (dest_format) {
545 case GST_FORMAT_TIME:
546 dest_val = (cdaudio->info.disc_time.minutes * 60 +
547 cdaudio->info.disc_time.seconds) * GST_SECOND;
551 if (dest_format == track_format) {
552 dest_val = cdaudio->info.disc_current_track;
560 gst_query_set_position (query, dest_format, dest_val);
572 plugin_init (GstPlugin * plugin)
574 if (!gst_element_register (plugin, "cdaudio", GST_RANK_NONE,
581 /*** GSTURIHANDLER INTERFACE *************************************************/
584 cdaudio_uri_get_type (void)
590 cdaudio_uri_get_protocols (void)
592 static gchar *protocols[] = { (char *) "cd", NULL };
598 cdaudio_uri_get_uri (GstURIHandler * handler)
600 GstCDAudio *cdaudio = GST_CDAUDIO (handler);
606 cdaudio_uri_set_uri (GstURIHandler * handler, const gchar * uri)
608 gchar *protocol, *location;
613 //GstCDAudio *cdaudio = GST_CDAUDIO(handler);
615 protocol = gst_uri_get_protocol (uri);
616 if (strcmp (protocol, "cd") != 0)
621 location = gst_uri_get_location (uri);
623 cdaudio->uri_track = strtol(location,NULL,10);
624 if (cdaudio->uri_track > 0) {
625 cdaudio->seek_request = cdaudio->uri_track;
641 cdaudio_uri_handler_init (gpointer g_iface, gpointer iface_data)
643 GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
645 iface->get_type = cdaudio_uri_get_type;
646 iface->get_protocols = cdaudio_uri_get_protocols;
647 iface->get_uri = cdaudio_uri_get_uri;
648 iface->set_uri = cdaudio_uri_set_uri;
651 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
654 "Play CD audio through the CD Drive",
655 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)