2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wim.taymans@chello.be>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
27 #include "gst/gst-i18n-plugin.h"
28 #include <sys/types.h>
30 #include <sys/ioctl.h>
32 #include <sys/soundcard.h>
37 #include <gst/propertyprobe/propertyprobe.h>
39 #include "gstosselement.h"
40 #include "gstossmixer.h"
50 /* elementfactory information */
51 static GstElementDetails gst_osselement_details =
52 GST_ELEMENT_DETAILS ("Audio Mixer (OSS)",
54 "OSS-based mixer element",
55 "Ronald Bultje <rbultje@ronald.bitfreak.net>");
57 static void gst_osselement_base_init (GstOssElementClass * klass);
58 static void gst_osselement_class_init (GstOssElementClass * klass);
60 static void gst_ossprobe_interface_init (GstPropertyProbeInterface * iface);
61 static void gst_osselement_init (GstOssElement * oss);
62 static void gst_osselement_dispose (GObject * object);
64 static void gst_osselement_set_property (GObject * object,
65 guint prop_id, const GValue * value, GParamSpec * pspec);
66 static void gst_osselement_get_property (GObject * object,
67 guint prop_id, GValue * value, GParamSpec * pspec);
68 static GstElementStateReturn gst_osselement_change_state (GstElement * element);
70 static GstElementClass *parent_class = NULL;
72 /*static guint gst_osssrc_signals[LAST_SIGNAL] = { 0 }; */
75 gst_osselement_get_type (void)
77 static GType osselement_type = 0;
79 if (!osselement_type) {
80 static const GTypeInfo osselement_info = {
81 sizeof (GstOssElementClass),
82 (GBaseInitFunc) gst_osselement_base_init,
84 (GClassInitFunc) gst_osselement_class_init,
87 sizeof (GstOssElement),
89 (GInstanceInitFunc) gst_osselement_init
91 static const GInterfaceInfo ossiface_info = {
92 (GInterfaceInitFunc) gst_oss_interface_init,
96 static const GInterfaceInfo ossmixer_info = {
97 (GInterfaceInitFunc) gst_ossmixer_interface_init,
101 static const GInterfaceInfo ossprobe_info = {
102 (GInterfaceInitFunc) gst_ossprobe_interface_init,
107 osselement_type = g_type_register_static (GST_TYPE_ELEMENT,
108 "GstOssElement", &osselement_info, 0);
109 g_type_add_interface_static (osselement_type,
110 GST_TYPE_IMPLEMENTS_INTERFACE, &ossiface_info);
111 g_type_add_interface_static (osselement_type,
112 GST_TYPE_MIXER, &ossmixer_info);
113 g_type_add_interface_static (osselement_type,
114 GST_TYPE_PROPERTY_PROBE, &ossprobe_info);
117 return osselement_type;
121 gst_osselement_base_init (GstOssElementClass * klass)
123 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
125 klass->device_combinations = NULL;
127 gst_element_class_set_details (element_class, &gst_osselement_details);
131 gst_osselement_class_init (GstOssElementClass * klass)
133 GObjectClass *gobject_class;
134 GstElementClass *gstelement_class;
136 gobject_class = (GObjectClass *) klass;
137 gstelement_class = (GstElementClass *) klass;
139 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
141 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE,
142 g_param_spec_string ("device", "Device", "OSS device (/dev/dspN usually)",
143 "default", G_PARAM_READWRITE));
144 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIXERDEV,
145 g_param_spec_string ("mixerdev", "Mixer device",
146 "OSS mixer device (/dev/mixerN usually)",
147 "default", G_PARAM_READWRITE));
148 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE_NAME,
149 g_param_spec_string ("device_name", "Device name", "Name of the device",
150 NULL, G_PARAM_READABLE));
152 gobject_class->set_property = gst_osselement_set_property;
153 gobject_class->get_property = gst_osselement_get_property;
154 gobject_class->dispose = gst_osselement_dispose;
156 gstelement_class->change_state = gst_osselement_change_state;
160 gst_ossprobe_get_properties (GstPropertyProbe * probe)
162 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
163 static GList *list = NULL;
166 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
172 /* OSS (without devfs) allows at max. 16 devices */
173 #define MAX_OSS_DEVICES 16
176 gst_osselement_probe (gchar * device_base,
177 gint device_num, gchar ** name, dev_t * devno)
179 gchar *device = NULL;
182 if ((name == NULL) || (devno == NULL)) {
189 if (device_num == -1)
190 device = g_strdup (device_base);
191 else if ((device_num >= -1) && (device_num <= MAX_OSS_DEVICES)) {
192 device = g_strdup_printf ("%s%d", device_base, device_num);
197 if (lstat (device, &s) || !S_ISCHR (s.st_mode))
209 device_combination_append (GList * device_combinations,
210 GstOssDeviceCombination * combi)
214 for (it = device_combinations; it != NULL; it = it->next) {
215 GstOssDeviceCombination *cur;
217 cur = (GstOssDeviceCombination *) it->data;
218 if (cur->dev == combi->dev) {
219 return device_combinations;
223 return g_list_append (device_combinations, combi);
227 gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
229 GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
230 static gboolean init = FALSE;
231 static GList *device_combinations;
233 gint openmode = O_RDONLY;
234 gboolean mixer = FALSE;
236 /* Ok, so how do we open the device? We assume that we have (max.) one
237 * pad, and if this is a sinkpad, we're osssink (w). else, we're osssrc
239 padtempllist = gst_element_class_get_pad_template_list (eklass);
240 if (padtempllist != NULL) {
241 GstPadTemplate *firstpadtempl = padtempllist->data;
243 if (GST_PAD_TEMPLATE_DIRECTION (firstpadtempl) == GST_PAD_SINK) {
249 if (!init && !check) {
252 gchar *dev_base[][2] = { {"/dev/mixer", "/dev/dsp"}
254 {"/dev/sound/mixer", "/dev/sound/dsp"}
261 while (device_combinations) {
262 GList *item = device_combinations;
263 GstOssDeviceCombination *combi = item->data;
265 device_combinations = g_list_remove (device_combinations, item);
268 g_free (combi->mixer);
272 /* probe for all /dev entries */
273 for (base = 0; dev_base[base][DSP] != NULL; base++) {
276 for (n = -1; n < MAX_OSS_DEVICES; n++) {
282 gst_osselement_probe (dev_base[base][DSP], n, &dsp, &dsp_dev);
286 gst_osselement_probe (dev_base[base][MIXER], n, &mixer, &mixer_dev);
287 /* does the device exist (can we open them)? */
289 /* we just check the dsp. we assume the mixer always works.
290 * we don't need a mixer anyway (says OSS)... If we are a
291 * mixer element, we use the mixer anyway. */
292 if ((fd = open (mixer ? mixer :
293 dsp, openmode | O_NONBLOCK)) > 0 || errno == EBUSY) {
294 GstOssDeviceCombination *combi;
300 combi = g_new0 (GstOssDeviceCombination, 1);
302 combi->mixer = mixer;
303 device_combinations = device_combination_append (device_combinations,
315 klass->device_combinations = device_combinations;
321 gst_osselement_class_list_devices (GstOssElementClass * klass)
324 GValue value = { 0 };
327 if (!klass->device_combinations)
330 array = g_value_array_new (g_list_length (klass->device_combinations));
331 item = klass->device_combinations;
332 g_value_init (&value, G_TYPE_STRING);
334 GstOssDeviceCombination *combi = item->data;
336 g_value_set_string (&value, combi->dsp);
337 g_value_array_append (array, &value);
341 g_value_unset (&value);
347 gst_ossprobe_probe_property (GstPropertyProbe * probe,
348 guint prop_id, const GParamSpec * pspec)
350 GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
354 gst_osselement_class_probe_devices (klass, FALSE);
357 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
363 gst_ossprobe_needs_probe (GstPropertyProbe * probe,
364 guint prop_id, const GParamSpec * pspec)
366 GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
367 gboolean ret = FALSE;
371 ret = !gst_osselement_class_probe_devices (klass, TRUE);
374 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
382 gst_ossprobe_get_values (GstPropertyProbe * probe,
383 guint prop_id, const GParamSpec * pspec)
385 GstOssElementClass *klass = GST_OSSELEMENT_GET_CLASS (probe);
386 GValueArray *array = NULL;
390 array = gst_osselement_class_list_devices (klass);
393 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
401 gst_ossprobe_interface_init (GstPropertyProbeInterface * iface)
403 iface->get_properties = gst_ossprobe_get_properties;
404 iface->probe_property = gst_ossprobe_probe_property;
405 iface->needs_probe = gst_ossprobe_needs_probe;
406 iface->get_values = gst_ossprobe_get_values;
410 gst_osselement_init (GstOssElement * oss)
412 oss->device = g_strdup ("/dev/dsp");
413 oss->mixer_dev = g_strdup ("/dev/mixer");
416 oss->tracklist = NULL;
417 oss->device_name = NULL;
419 gst_osselement_reset (oss);
423 gst_osselement_dispose (GObject * object)
425 GstOssElement *oss = (GstOssElement *) object;
427 g_free (oss->device);
428 g_free (oss->mixer_dev);
430 G_OBJECT_CLASS (parent_class)->dispose (object);
434 gst_osselement_reset (GstOssElement * oss)
437 oss->endianness = G_BYTE_ORDER;
446 /* AFMT_*_BE not available on all OSS includes (e.g. FBSD) */
447 #ifdef WORDS_BIGENDIAN
448 oss->format = AFMT_S16_BE;
450 oss->format = AFMT_S16_LE;
451 #endif /* WORDS_BIGENDIAN */
455 gst_ossformat_get (gint law, gint endianness, gboolean sign, gint width,
456 gint depth, gint * format, gint * bps)
466 if (endianness == G_LITTLE_ENDIAN) {
467 *format = AFMT_S16_LE;
468 GST_DEBUG ("16 bit signed LE, no law (%d)", *format);
469 } else if (endianness == G_BIG_ENDIAN) {
470 *format = AFMT_S16_BE;
471 GST_DEBUG ("16 bit signed BE, no law (%d)", *format);
474 if (endianness == G_LITTLE_ENDIAN) {
475 *format = AFMT_U16_LE;
476 GST_DEBUG ("16 bit unsigned LE, no law (%d)", *format);
477 } else if (endianness == G_BIG_ENDIAN) {
478 *format = AFMT_U16_BE;
479 GST_DEBUG ("16 bit unsigned BE, no law (%d)", *format);
483 } else if (width == 8) {
486 GST_DEBUG ("8 bit signed, no law (%d)", *format);
489 GST_DEBUG ("8 bit unsigned, no law (%d)", *format);
493 } else if (law == 1) {
494 *format = AFMT_MU_LAW;
495 GST_DEBUG ("mu law (%d)", *format);
496 } else if (law == 2) {
497 *format = AFMT_A_LAW;
498 GST_DEBUG ("a law (%d)", *format);
500 g_critical ("unknown law");
508 gst_osselement_parse_caps (GstOssElement * oss, const GstCaps * caps)
511 GstStructure *structure;
513 structure = gst_caps_get_structure (caps, 0);
515 gst_structure_get_int (structure, "width", &oss->width);
516 gst_structure_get_int (structure, "depth", &oss->depth);
518 if (oss->width != oss->depth)
521 gst_structure_get_int (structure, "law", &oss->law);
522 gst_structure_get_int (structure, "endianness", &oss->endianness);
523 gst_structure_get_boolean (structure, "signed", &oss->sign);
525 if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
526 oss->width, oss->depth, &format, &bps)) {
527 GST_DEBUG ("could not get format");
531 gst_structure_get_int (structure, "channels", &oss->channels);
532 gst_structure_get_int (structure, "rate", &oss->rate);
534 oss->bps = bps * oss->channels * oss->rate;
535 oss->format = format;
540 #define GET_FIXED_INT(caps, name, dest) \
542 if (gst_caps_has_fixed_property (caps, name)) \
543 gst_structure_get_int (structure, name, dest); \
545 #define GET_FIXED_BOOLEAN(caps, name, dest) \
547 if (gst_caps_has_fixed_property (caps, name)) \
548 gst_structure_get_boolean (structure, name, dest); \
552 gst_osselement_merge_fixed_caps (GstOssElement * oss, GstCaps * caps)
555 GstStructure *structure;
557 structure = gst_caps_get_structure (caps, 0);
559 /* peel off fixed stuff from the caps */
560 gst_structure_get_int (structure, "law", &oss->law);
561 gst_structure_get_int (structure, "endianness", &oss->endianness);
562 gst_structure_get_boolean (structure, "signed", &oss->sign);
563 gst_structure_get_int (structure, "width", &oss->width);
564 gst_structure_get_int (structure, "depth", &oss->depth);
566 if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
567 oss->width, oss->depth, &format, &bps)) {
571 gst_structure_get_int (structure, "rate", &oss->rate);
572 gst_structure_get_int (structure, "channels", &oss->channels);
574 oss->bps = bps * oss->channels * oss->rate;
575 oss->format = format;
581 gst_osselement_sync_parms (GstOssElement * oss)
583 audio_buf_info space;
586 gint target_channels;
588 gint fragscale, frag_ln;
593 if (oss->fragment >> 16)
594 frag = oss->fragment;
596 frag = 0x7FFF0000 | oss->fragment;
599 ("osselement: setting sound card to %dHz %d format %s (%08x fragment)",
600 oss->rate, oss->format, (oss->channels == 2) ? "stereo" : "mono", frag);
602 ioctl (oss->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
603 ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
605 target_format = oss->format;
606 target_channels = oss->channels;
607 target_rate = oss->rate;
609 ioctl (oss->fd, SNDCTL_DSP_SETFMT, &oss->format);
610 ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &oss->channels);
611 ioctl (oss->fd, SNDCTL_DSP_SPEED, &oss->rate);
613 ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size);
615 if (oss->mode == GST_OSSELEMENT_WRITE) {
616 ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space);
618 ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space);
621 /* calculate new fragment using a poor man's logarithm function */
624 while (fragscale < space.fragsize) {
628 oss->fragment = space.fragstotal << 16 | frag_ln;
630 GST_INFO ("osselement: set sound card to %dHz, %d format, %s "
631 "(%d bytes buffer, %08x fragment)",
632 oss->rate, oss->format,
633 (oss->channels == 2) ? "stereo" : "mono", space.bytes, oss->fragment);
635 oss->fragment_time = (GST_SECOND * oss->fragment_size) / oss->bps;
636 GST_INFO ("fragment time %u %" G_GUINT64_FORMAT "\n",
637 oss->bps, oss->fragment_time);
639 if (target_format != oss->format ||
640 target_channels != oss->channels || target_rate != oss->rate) {
641 if (target_channels != oss->channels)
643 ("couldn't set the right number of channels (wanted %d, got %d), enjoy the tone difference",
644 target_channels, oss->channels);
645 if (target_rate != oss->rate)
647 ("couldn't set the right sample rate (wanted %d, got %d), enjoy the speed difference",
648 target_rate, oss->rate);
649 if (target_format != oss->format)
650 g_warning ("couldn't set requested OSS format, enjoy the noise :)");
651 /* we could eventually return FALSE here, or just do some additional tests
652 * to see that the frequencies don't differ too much etc.. */
658 gst_osselement_open_audio (GstOssElement * oss)
661 GstOssOpenMode mode = GST_OSSELEMENT_READ;
662 const GList *padlist;
664 g_return_val_if_fail (oss->fd == -1, FALSE);
665 GST_INFO ("osselement: attempting to open sound device");
667 /* Ok, so how do we open the device? We assume that we have (max.) one
668 * pad, and if this is a sinkpad, we're osssink (w). else, we're osssrc (r) */
669 padlist = gst_element_get_pad_list (GST_ELEMENT (oss));
670 if (padlist != NULL) {
671 GstPad *firstpad = padlist->data;
673 if (GST_PAD_IS_SINK (firstpad)) {
674 mode = GST_OSSELEMENT_WRITE;
680 /* first try to open the sound card */
681 if (mode == GST_OSSELEMENT_WRITE) {
682 /* open non blocking first so that it returns immediatly with an error
683 * when we cannot get to the device */
684 oss->fd = open (oss->device, O_WRONLY | O_NONBLOCK);
689 /* re-open the sound device in blocking mode */
690 oss->fd = open (oss->device, O_WRONLY);
693 oss->fd = open (oss->device, O_RDONLY);
699 GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
700 (_("OSS device \"%s\" is already in use by another program."),
701 oss->device), (NULL));
705 if (mode == GST_OSSELEMENT_WRITE)
706 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
707 (_("Could not access device \"%s\", check its permissions."),
708 oss->device), GST_ERROR_SYSTEM);
710 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
711 (_("Could not access device \"%s\", check its permissions."),
712 oss->device), GST_ERROR_SYSTEM);
717 GST_ELEMENT_ERROR (oss, RESOURCE, NOT_FOUND,
718 (_("Device \"%s\" does not exist."), oss->device),
722 /* FIXME: strerror is not threadsafe */
723 if (mode == GST_OSSELEMENT_WRITE)
724 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
725 (_("Could not open device \"%s\" for writing."), oss->device),
728 GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_READ,
729 (_("Could not open device \"%s\" for reading."), oss->device),
738 /* we have it, set the default parameters and go have fun */
740 ioctl (oss->fd, SNDCTL_DSP_GETCAPS, &caps);
742 GST_INFO ("osselement: Capabilities %08x", caps);
744 if (caps & DSP_CAP_DUPLEX)
745 GST_INFO ("osselement: Full duplex");
746 if (caps & DSP_CAP_REALTIME)
747 GST_INFO ("osselement: Realtime");
748 if (caps & DSP_CAP_BATCH)
749 GST_INFO ("osselement: Batch");
750 if (caps & DSP_CAP_COPROC)
751 GST_INFO ("osselement: Has coprocessor");
752 if (caps & DSP_CAP_TRIGGER)
753 GST_INFO ("osselement: Trigger");
754 if (caps & DSP_CAP_MMAP)
755 GST_INFO ("osselement: Direct access");
758 if (caps & DSP_CAP_MULTI)
759 GST_INFO ("osselement: Multiple open");
760 #endif /* DSP_CAP_MULTI */
763 if (caps & DSP_CAP_BIND)
764 GST_INFO ("osselement: Channel binding");
765 #endif /* DSP_CAP_BIND */
767 ioctl (oss->fd, SNDCTL_DSP_GETFMTS, &caps);
769 GST_INFO ("osselement: Formats %08x", caps);
770 if (caps & AFMT_MU_LAW)
771 GST_INFO ("osselement: MU_LAW");
772 if (caps & AFMT_A_LAW)
773 GST_INFO ("osselement: A_LAW");
774 if (caps & AFMT_IMA_ADPCM)
775 GST_INFO ("osselement: IMA_ADPCM");
777 GST_INFO ("osselement: U8");
778 if (caps & AFMT_S16_LE)
779 GST_INFO ("osselement: S16_LE");
780 if (caps & AFMT_S16_BE)
781 GST_INFO ("osselement: S16_BE");
783 GST_INFO ("osselement: S8");
784 if (caps & AFMT_U16_LE)
785 GST_INFO ("osselement: U16_LE");
786 if (caps & AFMT_U16_BE)
787 GST_INFO ("osselement: U16_BE");
788 if (caps & AFMT_MPEG)
789 GST_INFO ("osselement: MPEG");
792 GST_INFO ("osselement: AC3");
795 GST_INFO ("osselement: opened audio (%s) with fd=%d", oss->device, oss->fd);
800 gst_ossmixer_build_list (oss);
806 gst_osselement_close_audio (GstOssElement * oss)
808 gst_ossmixer_free_list (oss);
818 gst_osselement_convert (GstOssElement * oss,
819 GstFormat src_format,
820 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
824 if (src_format == *dest_format) {
825 *dest_value = src_value;
829 if (oss->bps == 0 || oss->channels == 0 || oss->width == 0)
832 switch (src_format) {
833 case GST_FORMAT_BYTES:
834 switch (*dest_format) {
835 case GST_FORMAT_TIME:
836 *dest_value = src_value * GST_SECOND / oss->bps;
838 case GST_FORMAT_DEFAULT:
839 *dest_value = src_value / (oss->width * oss->channels / 8);
845 case GST_FORMAT_TIME:
846 switch (*dest_format) {
847 case GST_FORMAT_BYTES:
848 *dest_value = src_value * oss->bps / GST_SECOND;
850 case GST_FORMAT_DEFAULT:
851 *dest_value = src_value * oss->rate / GST_SECOND;
857 case GST_FORMAT_DEFAULT:
858 switch (*dest_format) {
859 case GST_FORMAT_TIME:
860 *dest_value = src_value * GST_SECOND / oss->rate;
862 case GST_FORMAT_BYTES:
863 *dest_value = src_value * oss->width * oss->channels / 8;
877 gst_osselement_set_property (GObject * object,
878 guint prop_id, const GValue * value, GParamSpec * pspec)
880 GstOssElement *oss = GST_OSSELEMENT (object);
884 /* disallow changing the device while it is opened
885 get_property("device") should return the right one */
886 if (gst_element_get_state (GST_ELEMENT (oss)) == GST_STATE_NULL) {
887 g_free (oss->device);
888 oss->device = g_strdup (g_value_get_string (value));
890 /* let's assume that if we have a device map for the mixer,
891 * we're allowed to do all that automagically here */
892 if (GST_OSSELEMENT_GET_CLASS (oss)->device_combinations != NULL) {
893 GList *list = GST_OSSELEMENT_GET_CLASS (oss)->device_combinations;
896 GstOssDeviceCombination *combi = list->data;
898 if (!strcmp (combi->dsp, oss->device)) {
899 g_free (oss->mixer_dev);
900 oss->mixer_dev = g_strdup (combi->mixer);
910 /* disallow changing the device while it is opened
911 get_property("mixerdev") should return the right one */
912 if (gst_element_get_state (GST_ELEMENT (oss)) == GST_STATE_NULL) {
913 g_free (oss->mixer_dev);
914 oss->mixer_dev = g_strdup (g_value_get_string (value));
923 gst_osselement_get_property (GObject * object,
924 guint prop_id, GValue * value, GParamSpec * pspec)
926 GstOssElement *oss = GST_OSSELEMENT (object);
930 g_value_set_string (value, oss->device);
933 g_value_set_string (value, oss->mixer_dev);
935 case ARG_DEVICE_NAME:
936 g_value_set_string (value, oss->device_name);
939 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
944 static GstElementStateReturn
945 gst_osselement_change_state (GstElement * element)
947 GstOssElement *oss = GST_OSSELEMENT (element);
949 switch (GST_STATE_TRANSITION (element)) {
950 case GST_STATE_NULL_TO_READY:
951 if (!gst_osselement_open_audio (oss)) {
952 return GST_STATE_FAILURE;
954 GST_INFO ("osselement: opened sound device");
956 case GST_STATE_READY_TO_NULL:
957 gst_osselement_close_audio (oss);
958 gst_osselement_reset (oss);
959 GST_INFO ("osselement: closed sound device");
965 if (GST_ELEMENT_CLASS (parent_class)->change_state)
966 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
968 return GST_STATE_SUCCESS;