mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
gst-libs/gst/audio/gstaudiosrc.*: Implement open_device and close_device in the ring buffer, like gstaudiosink.
Original commit message from CVS: 2005-08-22 Andy Wingo <wingo@pobox.com> * gst-libs/gst/audio/gstaudiosrc.h: * gst-libs/gst/audio/gstaudiosrc.c: Implement open_device and close_device in the ring buffer, like gstaudiosink. * ext/alsa/gstalsamixer.h: * ext/alsa/gstalsamixer.c: Not a GObject any more. Include a nifty macro to implement the interface without much code. Cleanups. * ext/alsa/gstalsasrc.h: * ext/alsa/gstalsasrc.c: Be a mixer. Open device and mixer in READY. * ext/alsa/Makefile.am: Add new files. * ext/alsa/gstalsamixerelement.c: * ext/alsa/gstalsamixerelement.c: Split element code out from mixer code so that alsasrc can be a mixer too.
This commit is contained in:
parent
6d828d3b93
commit
13b122a106
11 changed files with 607 additions and 328 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2005-08-22 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
|
* gst-libs/gst/audio/gstaudiosrc.h:
|
||||||
|
* gst-libs/gst/audio/gstaudiosrc.c: Implement open_device and
|
||||||
|
close_device in the ring buffer, like gstaudiosink.
|
||||||
|
|
||||||
|
* ext/alsa/gstalsamixer.h:
|
||||||
|
* ext/alsa/gstalsamixer.c: Not a GObject any more. Include a nifty
|
||||||
|
macro to implement the interface without much code. Cleanups.
|
||||||
|
|
||||||
|
* ext/alsa/gstalsasrc.h:
|
||||||
|
* ext/alsa/gstalsasrc.c: Be a mixer. Open device and mixer in
|
||||||
|
READY.
|
||||||
|
|
||||||
|
* ext/alsa/Makefile.am: Add new files.
|
||||||
|
* ext/alsa/gstalsamixerelement.c:
|
||||||
|
* ext/alsa/gstalsamixerelement.c: Split element code out from
|
||||||
|
mixer code so that alsasrc can be a mixer too.
|
||||||
|
|
||||||
2005-08-21 Thomas Vander Stichele <thomas at apestaart dot org>
|
2005-08-21 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* check/elements/volume.c: (setup_volume), (cleanup_volume),
|
* check/elements/volume.c: (setup_volume), (cleanup_volume),
|
||||||
|
|
|
@ -3,6 +3,7 @@ plugin_LTLIBRARIES = libgstalsa.la
|
||||||
libgstalsa_la_SOURCES = \
|
libgstalsa_la_SOURCES = \
|
||||||
gstalsaplugin.c \
|
gstalsaplugin.c \
|
||||||
gstalsamixer.c \
|
gstalsamixer.c \
|
||||||
|
gstalsamixerelement.c \
|
||||||
gstalsamixertrack.c \
|
gstalsamixertrack.c \
|
||||||
gstalsamixeroptions.c \
|
gstalsamixeroptions.c \
|
||||||
gstalsasink.c \
|
gstalsasink.c \
|
||||||
|
@ -20,5 +21,6 @@ noinst_HEADERS = \
|
||||||
gstalsasink.h \
|
gstalsasink.h \
|
||||||
gstalsasrc.h \
|
gstalsasrc.h \
|
||||||
gstalsamixer.h \
|
gstalsamixer.h \
|
||||||
|
gstalsamixerelement.h \
|
||||||
gstalsamixertrack.h \
|
gstalsamixertrack.h \
|
||||||
gstalsamixeroptions.h
|
gstalsamixeroptions.h
|
||||||
|
|
|
@ -25,194 +25,92 @@
|
||||||
#include "gstalsamixer.h"
|
#include "gstalsamixer.h"
|
||||||
|
|
||||||
|
|
||||||
static GstElementDetails gst_alsa_mixer_details =
|
/* First some utils, then the mixer implementation */
|
||||||
GST_ELEMENT_DETAILS ("Alsa Mixer",
|
|
||||||
"Generic/Audio",
|
|
||||||
"Control sound input and output levels with ALSA",
|
|
||||||
"Leif Johnson <leif@ambient.2y.net>");
|
|
||||||
|
|
||||||
|
|
||||||
#define GST_BOILERPLATE_WITH_INTERFACE(type, type_as_function, parent_type, \
|
|
||||||
parent_type_as_macro, interface_type, interface_type_as_macro, \
|
|
||||||
interface_as_function) \
|
|
||||||
\
|
|
||||||
static void interface_as_function ## _interface_init (interface_type ## Class *klass); \
|
|
||||||
static gboolean interface_as_function ## _supported (type *object, GType iface_type); \
|
|
||||||
\
|
|
||||||
static void \
|
|
||||||
type_as_function ## _implements_interface_init (GstImplementsInterfaceClass *klass) \
|
|
||||||
{ \
|
|
||||||
klass->supported = (gpointer)interface_as_function ## _supported; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
static void \
|
|
||||||
type_as_function ## _init_interfaces (GType type) \
|
|
||||||
{ \
|
|
||||||
static const GInterfaceInfo implements_iface_info = { \
|
|
||||||
(GInterfaceInitFunc) type_as_function ## _implements_interface_init, \
|
|
||||||
NULL, \
|
|
||||||
NULL, \
|
|
||||||
}; \
|
|
||||||
static const GInterfaceInfo iface_info = { \
|
|
||||||
(GInterfaceInitFunc) interface_as_function ## _interface_init, \
|
|
||||||
NULL, \
|
|
||||||
NULL, \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, \
|
|
||||||
&implements_iface_info); \
|
|
||||||
g_type_add_interface_static (type, interface_type_as_macro, &iface_info); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
GST_BOILERPLATE_FULL (type, type_as_function, parent_type, \
|
|
||||||
parent_type_as_macro, type_as_function ## _init_interfaces)
|
|
||||||
|
|
||||||
GST_BOILERPLATE_WITH_INTERFACE (GstAlsaMixer, gst_alsa_mixer, GstElement,
|
|
||||||
GST_TYPE_ELEMENT, GstMixer, GST_TYPE_MIXER, gst_alsa_mixer);
|
|
||||||
|
|
||||||
static GstElementStateReturn gst_alsa_mixer_change_state (GstElement * element);
|
|
||||||
|
|
||||||
/* GstMixer */
|
|
||||||
static const GList *gst_alsa_mixer_list_tracks (GstMixer * mixer);
|
|
||||||
static void gst_alsa_mixer_set_volume (GstMixer * mixer,
|
|
||||||
GstMixerTrack * track, gint * volumes);
|
|
||||||
static void gst_alsa_mixer_get_volume (GstMixer * mixer,
|
|
||||||
GstMixerTrack * track, gint * volumes);
|
|
||||||
static void gst_alsa_mixer_set_record (GstMixer * mixer,
|
|
||||||
GstMixerTrack * track, gboolean record);
|
|
||||||
static void gst_alsa_mixer_set_mute (GstMixer * mixer,
|
|
||||||
GstMixerTrack * track, gboolean mute);
|
|
||||||
static void gst_alsa_mixer_set_option (GstMixer * mixer,
|
|
||||||
GstMixerOptions * opts, gchar * value);
|
|
||||||
static const gchar *gst_alsa_mixer_get_option (GstMixer * mixer,
|
|
||||||
GstMixerOptions * opts);
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_alsa_mixer_base_init (gpointer klass)
|
|
||||||
{
|
|
||||||
gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
|
|
||||||
&gst_alsa_mixer_details);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_alsa_mixer_class_init (GstAlsaMixerClass * klass)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class;
|
|
||||||
|
|
||||||
element_class = (GstElementClass *) klass;
|
|
||||||
|
|
||||||
element_class->change_state = gst_alsa_mixer_change_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_alsa_mixer_init (GstAlsaMixer * mixer)
|
|
||||||
{
|
|
||||||
mixer->mixer_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_alsa_mixer_open (GstAlsaMixer * mixer)
|
gst_alsa_mixer_open (GstAlsaMixer * mixer)
|
||||||
{
|
{
|
||||||
gint err, device;
|
gint err, devicenum;
|
||||||
gchar *nocomma = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (mixer->mixer_handle == NULL, FALSE);
|
g_return_val_if_fail (mixer->handle == NULL, FALSE);
|
||||||
|
|
||||||
/* open and initialize the mixer device */
|
/* open and initialize the mixer device */
|
||||||
err = snd_mixer_open (&mixer->mixer_handle, 0);
|
err = snd_mixer_open (&mixer->handle, 0);
|
||||||
if (err < 0 || mixer->mixer_handle == NULL) {
|
if (err < 0 || mixer->handle == NULL) {
|
||||||
GST_ERROR_OBJECT (GST_OBJECT (mixer), "Cannot open mixer device.");
|
GST_WARNING ("Cannot open empty mixer.");
|
||||||
mixer->mixer_handle = NULL;
|
mixer->handle = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
GstAlsa *alsa = GST_ALSA (mixer);
|
|
||||||
|
|
||||||
if (!strncmp (alsa->device, "hw:", 3))
|
/* hack hack hack hack hack!!!!! */
|
||||||
nocomma = g_strdup (alsa->device);
|
if (strncmp (mixer->device, "default", 7) == 0) {
|
||||||
else if (!strncmp (alsa->device, "plughw:", 7))
|
/* hack! */
|
||||||
nocomma = g_strdup (alsa->device + 4);
|
g_free (mixer->device);
|
||||||
else
|
mixer->device = g_strdup ("hw:0");
|
||||||
goto error;
|
} else if (strncmp (mixer->device, "hw:", 3) == 0) {
|
||||||
#else
|
/* ok */
|
||||||
nocomma = g_strdup ("hw:0");
|
} else if (strncmp (mixer->device, "plughw:", 7) == 0) {
|
||||||
#endif
|
gchar *freeme = mixer->device;
|
||||||
|
|
||||||
if (strchr (nocomma, ','))
|
mixer->device = g_strdup (freeme + 4);
|
||||||
strchr (nocomma, ',')[0] = '\0';
|
g_free (freeme);
|
||||||
|
} else {
|
||||||
if ((err = snd_mixer_attach (mixer->mixer_handle, nocomma)) < 0) {
|
|
||||||
GST_ERROR_OBJECT (GST_OBJECT (mixer),
|
|
||||||
"Cannot attach mixer to sound device `%s'.", nocomma);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_mixer_selem_register (mixer->mixer_handle, NULL, NULL)) < 0) {
|
if (strchr (mixer->device, ','))
|
||||||
GST_ERROR_OBJECT (GST_OBJECT (mixer), "Cannot register mixer elements.");
|
strchr (mixer->device, ',')[0] = '\0';
|
||||||
|
|
||||||
|
if ((err = snd_mixer_attach (mixer->handle, mixer->device)) < 0) {
|
||||||
|
GST_WARNING ("Cannot open mixer for sound device `%s'.", mixer->device);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_mixer_load (mixer->mixer_handle)) < 0) {
|
if ((err = snd_mixer_selem_register (mixer->handle, NULL, NULL)) < 0) {
|
||||||
GST_ERROR_OBJECT (GST_OBJECT (mixer), "Cannot load mixer settings.");
|
GST_WARNING ("Cannot register mixer elements.");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = snd_mixer_load (mixer->handle)) < 0) {
|
||||||
|
GST_WARNING ("Cannot load mixer settings.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I don't know how to get a device name from a mixer handle. So on
|
/* I don't know how to get a device name from a mixer handle. So on
|
||||||
* to the ugly hacks here, then... */
|
* to the ugly hacks here, then... */
|
||||||
if (sscanf (nocomma, "hw:%d", &device) == 1) {
|
if (sscanf (mixer->device, "hw:%d", &devicenum) == 1) {
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
|
||||||
if (!snd_card_get_name (device, &name))
|
if (!snd_card_get_name (devicenum, &name))
|
||||||
mixer->cardname = name;
|
mixer->cardname = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (nocomma);
|
GST_INFO ("Successfully opened mixer for device `%s'.", mixer->device);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
snd_mixer_close (mixer->mixer_handle);
|
snd_mixer_close (mixer->handle);
|
||||||
mixer->mixer_handle = NULL;
|
mixer->handle = NULL;
|
||||||
g_free (nocomma);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alsa_mixer_close (GstAlsaMixer * mixer)
|
gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer)
|
||||||
{
|
|
||||||
if (mixer->mixer_handle == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mixer->cardname) {
|
|
||||||
free (mixer->cardname);
|
|
||||||
mixer->cardname = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_mixer_close (mixer->mixer_handle);
|
|
||||||
mixer->mixer_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_alsa_mixer_build_list (GstAlsaMixer * mixer)
|
|
||||||
{
|
{
|
||||||
gint i, count;
|
gint i, count;
|
||||||
snd_mixer_elem_t *element;
|
snd_mixer_elem_t *element;
|
||||||
GstMixerTrack *track;
|
GstMixerTrack *track;
|
||||||
GstMixerOptions *opts;
|
GstMixerOptions *opts;
|
||||||
const GList *templates;
|
|
||||||
GstPadDirection dir = GST_PAD_UNKNOWN;
|
|
||||||
gboolean first = TRUE;
|
gboolean first = TRUE;
|
||||||
|
|
||||||
g_return_if_fail (mixer->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
/* find direction */
|
if (mixer->tracklist)
|
||||||
templates =
|
return;
|
||||||
gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS (mixer));
|
|
||||||
if (templates)
|
|
||||||
dir = GST_PAD_TEMPLATE (templates->data)->direction;
|
|
||||||
|
|
||||||
count = snd_mixer_get_count (mixer->mixer_handle);
|
count = snd_mixer_get_count (mixer->handle);
|
||||||
element = snd_mixer_first_elem (mixer->mixer_handle);
|
element = snd_mixer_first_elem (mixer->handle);
|
||||||
|
|
||||||
/* build track list */
|
/* build track list */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
|
@ -222,11 +120,11 @@ gst_alsa_mixer_build_list (GstAlsaMixer * mixer)
|
||||||
gboolean got_it = FALSE;
|
gboolean got_it = FALSE;
|
||||||
|
|
||||||
if (snd_mixer_selem_has_capture_switch (element)) {
|
if (snd_mixer_selem_has_capture_switch (element)) {
|
||||||
if (dir != GST_PAD_SRC && dir != GST_PAD_UNKNOWN)
|
if (!(mixer->dir & GST_ALSA_MIXER_CAPTURE))
|
||||||
goto next;
|
goto next;
|
||||||
flags = GST_MIXER_TRACK_INPUT;
|
flags = GST_MIXER_TRACK_INPUT;
|
||||||
} else {
|
} else {
|
||||||
if (dir != GST_PAD_SINK && dir != GST_PAD_UNKNOWN)
|
if (!(mixer->dir & GST_ALSA_MIXER_PLAYBACK))
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,92 +189,81 @@ gst_alsa_mixer_build_list (GstAlsaMixer * mixer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_alsa_mixer_free_list (GstAlsaMixer * mixer)
|
|
||||||
{
|
|
||||||
g_return_if_fail (mixer->mixer_handle != NULL);
|
|
||||||
|
|
||||||
g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
|
/* API */
|
||||||
g_list_free (mixer->tracklist);
|
|
||||||
mixer->tracklist = NULL;
|
GstAlsaMixer *
|
||||||
|
gst_alsa_mixer_new (const char *device, GstAlsaMixerDirection dir)
|
||||||
|
{
|
||||||
|
GstAlsaMixer *ret = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (device != NULL, NULL);
|
||||||
|
|
||||||
|
ret = g_new0 (GstAlsaMixer, 1);
|
||||||
|
|
||||||
|
ret->device = g_strdup (device);
|
||||||
|
ret->dir = dir;
|
||||||
|
|
||||||
|
if (!gst_alsa_mixer_open (ret))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (ret)
|
||||||
|
gst_alsa_mixer_free (ret);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstElementStateReturn
|
void
|
||||||
gst_alsa_mixer_change_state (GstElement * element)
|
gst_alsa_mixer_free (GstAlsaMixer * mixer)
|
||||||
{
|
{
|
||||||
GstAlsaMixer *this;
|
g_return_if_fail (mixer != NULL);
|
||||||
|
|
||||||
g_return_val_if_fail (element != NULL, FALSE);
|
if (mixer->device) {
|
||||||
this = GST_ALSA_MIXER (element);
|
g_free (mixer->device);
|
||||||
|
mixer->device = NULL;
|
||||||
switch (GST_STATE_TRANSITION (element)) {
|
|
||||||
case GST_STATE_NULL_TO_READY:
|
|
||||||
if (gst_alsa_mixer_open (this))
|
|
||||||
gst_alsa_mixer_build_list (this);
|
|
||||||
break;
|
|
||||||
case GST_STATE_READY_TO_NULL:
|
|
||||||
if (this->mixer_handle != NULL) {
|
|
||||||
gst_alsa_mixer_free_list (this);
|
|
||||||
gst_alsa_mixer_close (this);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
if (mixer->cardname) {
|
||||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
g_free (mixer->cardname);
|
||||||
|
mixer->cardname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return GST_STATE_SUCCESS;
|
if (mixer->tracklist) {
|
||||||
|
g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
|
||||||
|
g_list_free (mixer->tracklist);
|
||||||
|
mixer->tracklist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mixer->handle) {
|
||||||
|
snd_mixer_close (mixer->handle);
|
||||||
|
mixer->handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (mixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** INTERFACE IMPLEMENTATION *************************************************/
|
const GList *
|
||||||
|
gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer)
|
||||||
static void
|
|
||||||
gst_alsa_mixer_interface_init (GstMixerClass * klass)
|
|
||||||
{
|
{
|
||||||
GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE;
|
g_return_val_if_fail (mixer->handle != NULL, NULL);
|
||||||
|
|
||||||
/* set up the interface hooks */
|
gst_alsa_mixer_ensure_track_list (mixer);
|
||||||
klass->list_tracks = gst_alsa_mixer_list_tracks;
|
|
||||||
klass->set_volume = gst_alsa_mixer_set_volume;
|
|
||||||
klass->get_volume = gst_alsa_mixer_get_volume;
|
|
||||||
klass->set_mute = gst_alsa_mixer_set_mute;
|
|
||||||
klass->set_record = gst_alsa_mixer_set_record;
|
|
||||||
klass->set_option = gst_alsa_mixer_set_option;
|
|
||||||
klass->get_option = gst_alsa_mixer_get_option;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
return (const GList *) mixer->tracklist;
|
||||||
gst_alsa_mixer_supported (GstAlsaMixer * object, GType iface_type)
|
|
||||||
{
|
|
||||||
g_assert (iface_type == GST_TYPE_MIXER);
|
|
||||||
|
|
||||||
return (object->mixer_handle != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GList *
|
|
||||||
gst_alsa_mixer_list_tracks (GstMixer * mixer)
|
|
||||||
{
|
|
||||||
GstAlsaMixer *alsa_mixer = GST_ALSA_MIXER (mixer);
|
|
||||||
|
|
||||||
if (!alsa_mixer->mixer_handle)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return (const GList *) alsa_mixer->tracklist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alsa_mixer_update (GstAlsaMixer * alsa_mixer,
|
gst_alsa_mixer_update (GstAlsaMixer * mixer, GstAlsaMixerTrack * alsa_track)
|
||||||
GstAlsaMixerTrack * alsa_track)
|
|
||||||
{
|
{
|
||||||
GstMixerTrack *track;
|
GstMixerTrack *track = (GstMixerTrack *) alsa_track;
|
||||||
int v = 0;
|
int v = 0;
|
||||||
|
|
||||||
snd_mixer_handle_events (alsa_mixer->mixer_handle);
|
snd_mixer_handle_events (mixer->handle);
|
||||||
if (!alsa_track)
|
if (!alsa_track)
|
||||||
return;
|
return;
|
||||||
track = (GstMixerTrack *) alsa_track;
|
|
||||||
|
|
||||||
/* Any updates in flags? */
|
/* Any updates in flags? */
|
||||||
if (snd_mixer_selem_has_playback_switch (alsa_track->element)) {
|
if (snd_mixer_selem_has_playback_switch (alsa_track->element)) {
|
||||||
|
@ -395,16 +282,16 @@ gst_alsa_mixer_update (GstAlsaMixer * alsa_mixer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_alsa_mixer_get_volume (GstMixer * mixer,
|
gst_alsa_mixer_get_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
|
||||||
GstMixerTrack * track, gint * volumes)
|
gint * volumes)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
GstAlsaMixerTrack *alsa_track = (GstAlsaMixerTrack *) track;
|
GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
|
||||||
|
|
||||||
g_return_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), alsa_track);
|
gst_alsa_mixer_update (mixer, alsa_track);
|
||||||
|
|
||||||
if (track->flags & GST_MIXER_TRACK_MUTE &&
|
if (track->flags & GST_MIXER_TRACK_MUTE &&
|
||||||
!snd_mixer_selem_has_playback_switch (alsa_track->element)) {
|
!snd_mixer_selem_has_playback_switch (alsa_track->element)) {
|
||||||
|
@ -426,16 +313,16 @@ gst_alsa_mixer_get_volume (GstMixer * mixer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_alsa_mixer_set_volume (GstMixer * mixer,
|
gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
|
||||||
GstMixerTrack * track, gint * volumes)
|
gint * volumes)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
GstAlsaMixerTrack *alsa_track = (GstAlsaMixerTrack *) track;
|
GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
|
||||||
|
|
||||||
g_return_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), alsa_track);
|
gst_alsa_mixer_update (mixer, alsa_track);
|
||||||
|
|
||||||
/* only set the volume with ALSA lib if the track isn't muted. */
|
/* only set the volume with ALSA lib if the track isn't muted. */
|
||||||
for (i = 0; i < track->num_channels; i++) {
|
for (i = 0; i < track->num_channels; i++) {
|
||||||
|
@ -454,15 +341,16 @@ gst_alsa_mixer_set_volume (GstMixer * mixer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_alsa_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
|
gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track,
|
||||||
|
gboolean mute)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
GstAlsaMixerTrack *alsa_track = (GstAlsaMixerTrack *) track;
|
GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
|
||||||
|
|
||||||
g_return_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), alsa_track);
|
gst_alsa_mixer_update (mixer, alsa_track);
|
||||||
|
|
||||||
if (mute) {
|
if (mute) {
|
||||||
track->flags |= GST_MIXER_TRACK_MUTE;
|
track->flags |= GST_MIXER_TRACK_MUTE;
|
||||||
|
@ -485,15 +373,15 @@ gst_alsa_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_alsa_mixer_set_record (GstMixer * mixer,
|
gst_alsa_mixer_set_record (GstAlsaMixer * mixer,
|
||||||
GstMixerTrack * track, gboolean record)
|
GstMixerTrack * track, gboolean record)
|
||||||
{
|
{
|
||||||
GstAlsaMixerTrack *alsa_track = (GstAlsaMixerTrack *) track;
|
GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
|
||||||
|
|
||||||
g_return_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), alsa_track);
|
gst_alsa_mixer_update (mixer, alsa_track);
|
||||||
|
|
||||||
if (record) {
|
if (record) {
|
||||||
track->flags |= GST_MIXER_TRACK_RECORD;
|
track->flags |= GST_MIXER_TRACK_RECORD;
|
||||||
|
@ -504,17 +392,17 @@ gst_alsa_mixer_set_record (GstMixer * mixer,
|
||||||
snd_mixer_selem_set_capture_switch_all (alsa_track->element, record ? 1 : 0);
|
snd_mixer_selem_set_capture_switch_all (alsa_track->element, record ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_alsa_mixer_set_option (GstMixer * mixer,
|
gst_alsa_mixer_set_option (GstAlsaMixer * mixer,
|
||||||
GstMixerOptions * opts, gchar * value)
|
GstMixerOptions * opts, gchar * value)
|
||||||
{
|
{
|
||||||
gint idx = -1, n = 0;
|
gint idx = -1, n = 0;
|
||||||
GList *item;
|
GList *item;
|
||||||
GstAlsaMixerOptions *alsa_opts = (GstAlsaMixerOptions *) opts;
|
GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
|
||||||
|
|
||||||
g_return_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL);
|
g_return_if_fail (mixer->handle != NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), NULL);
|
gst_alsa_mixer_update (mixer, NULL);
|
||||||
|
|
||||||
for (item = opts->values; item != NULL; item = item->next, n++) {
|
for (item = opts->values; item != NULL; item = item->next, n++) {
|
||||||
if (!strcmp (item->data, value)) {
|
if (!strcmp (item->data, value)) {
|
||||||
|
@ -528,16 +416,16 @@ gst_alsa_mixer_set_option (GstMixer * mixer,
|
||||||
snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx);
|
snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *
|
const gchar *
|
||||||
gst_alsa_mixer_get_option (GstMixer * mixer, GstMixerOptions * opts)
|
gst_alsa_mixer_get_option (GstAlsaMixer * mixer, GstMixerOptions * opts)
|
||||||
{
|
{
|
||||||
GstAlsaMixerOptions *alsa_opts = (GstAlsaMixerOptions *) opts;
|
|
||||||
gint ret;
|
gint ret;
|
||||||
guint idx;
|
guint idx;
|
||||||
|
GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
|
||||||
|
|
||||||
g_return_val_if_fail (GST_ALSA_MIXER (mixer)->mixer_handle != NULL, NULL);
|
g_return_val_if_fail (mixer->handle != NULL, NULL);
|
||||||
|
|
||||||
gst_alsa_mixer_update (GST_ALSA_MIXER (mixer), NULL);
|
gst_alsa_mixer_update (mixer, NULL);
|
||||||
|
|
||||||
ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
|
ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
|
|
||||||
#include "gstalsa.h"
|
#include "gstalsa.h"
|
||||||
#include <gst/interfaces/mixer.h>
|
|
||||||
|
|
||||||
|
#include <gst/interfaces/mixer.h>
|
||||||
#include "gstalsamixeroptions.h"
|
#include "gstalsamixeroptions.h"
|
||||||
#include "gstalsamixertrack.h"
|
#include "gstalsamixertrack.h"
|
||||||
|
|
||||||
|
@ -31,33 +31,160 @@
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
#define GST_ALSA_MIXER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER,GstAlsaMixer))
|
#define GST_ALSA_MIXER(obj) ((GstAlsaMixer*)(obj))
|
||||||
#define GST_ALSA_MIXER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER,GstAlsaMixerClass))
|
|
||||||
#define GST_IS_ALSA_MIXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER))
|
|
||||||
#define GST_IS_ALSA_MIXER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER))
|
|
||||||
#define GST_TYPE_ALSA_MIXER (gst_alsa_mixer_get_type())
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_ALSA_MIXER_CAPTURE = 1<<0,
|
||||||
|
GST_ALSA_MIXER_PLAYBACK = 1<<1,
|
||||||
|
GST_ALSA_MIXER_ALL = GST_ALSA_MIXER_CAPTURE | GST_ALSA_MIXER_PLAYBACK
|
||||||
|
} GstAlsaMixerDirection;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _GstAlsaMixer GstAlsaMixer;
|
typedef struct _GstAlsaMixer GstAlsaMixer;
|
||||||
typedef struct _GstAlsaMixerClass GstAlsaMixerClass;
|
|
||||||
|
|
||||||
|
|
||||||
struct _GstAlsaMixer {
|
struct _GstAlsaMixer {
|
||||||
GstElement parent;
|
|
||||||
|
|
||||||
GList * tracklist; /* list of available tracks */
|
GList * tracklist; /* list of available tracks */
|
||||||
|
|
||||||
snd_mixer_t * mixer_handle;
|
snd_mixer_t * handle;
|
||||||
|
|
||||||
|
gchar * device;
|
||||||
gchar * cardname;
|
gchar * cardname;
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstAlsaMixerClass {
|
GstAlsaMixerDirection dir;
|
||||||
GstElementClass parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GType gst_alsa_mixer_get_type (void);
|
GstAlsaMixer* gst_alsa_mixer_new (const gchar *device,
|
||||||
|
GstAlsaMixerDirection dir);
|
||||||
|
void gst_alsa_mixer_free (GstAlsaMixer *mixer);
|
||||||
|
|
||||||
|
const GList* gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer);
|
||||||
|
void gst_alsa_mixer_set_volume (GstAlsaMixer * mixer,
|
||||||
|
GstMixerTrack * track,
|
||||||
|
gint * volumes);
|
||||||
|
void gst_alsa_mixer_get_volume (GstAlsaMixer * mixer,
|
||||||
|
GstMixerTrack * track,
|
||||||
|
gint * volumes);
|
||||||
|
void gst_alsa_mixer_set_record (GstAlsaMixer * mixer,
|
||||||
|
GstMixerTrack * track,
|
||||||
|
gboolean record);
|
||||||
|
void gst_alsa_mixer_set_mute (GstAlsaMixer * mixer,
|
||||||
|
GstMixerTrack * track,
|
||||||
|
gboolean mute);
|
||||||
|
void gst_alsa_mixer_set_option (GstAlsaMixer * mixer,
|
||||||
|
GstMixerOptions * opts,
|
||||||
|
gchar * value);
|
||||||
|
const gchar* gst_alsa_mixer_get_option (GstAlsaMixer * mixer,
|
||||||
|
GstMixerOptions * opts);
|
||||||
|
|
||||||
|
|
||||||
|
#define GST_IMPLEMENT_ALSA_MIXER_METHODS(Type, interface_as_function) \
|
||||||
|
static gboolean \
|
||||||
|
interface_as_function ## _supported (Type *this, GType iface_type) \
|
||||||
|
{ \
|
||||||
|
g_assert (iface_type == GST_TYPE_MIXER); \
|
||||||
|
\
|
||||||
|
return (this->mixer != NULL); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static const GList* \
|
||||||
|
interface_as_function ## _list_tracks (GstMixer * mixer) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (this != NULL, NULL); \
|
||||||
|
g_return_val_if_fail (this->mixer != NULL, NULL); \
|
||||||
|
\
|
||||||
|
return gst_alsa_mixer_list_tracks (this->mixer); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
|
||||||
|
gint * volumes) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (this != NULL); \
|
||||||
|
g_return_if_fail (this->mixer != NULL); \
|
||||||
|
\
|
||||||
|
gst_alsa_mixer_set_volume (this->mixer, track, volumes); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
|
||||||
|
gint * volumes) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (this != NULL); \
|
||||||
|
g_return_if_fail (this->mixer != NULL); \
|
||||||
|
\
|
||||||
|
gst_alsa_mixer_get_volume (this->mixer, track, volumes); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
|
||||||
|
gboolean record) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (this != NULL); \
|
||||||
|
g_return_if_fail (this->mixer != NULL); \
|
||||||
|
\
|
||||||
|
gst_alsa_mixer_set_record (this->mixer, track, record); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
|
||||||
|
gboolean mute) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (this != NULL); \
|
||||||
|
g_return_if_fail (this->mixer != NULL); \
|
||||||
|
\
|
||||||
|
gst_alsa_mixer_set_mute (this->mixer, track, mute); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _set_option (GstMixer * mixer, GstMixerOptions * opts, \
|
||||||
|
gchar * value) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (this != NULL); \
|
||||||
|
g_return_if_fail (this->mixer != NULL); \
|
||||||
|
\
|
||||||
|
gst_alsa_mixer_set_option (this->mixer, opts, value); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static const gchar* \
|
||||||
|
interface_as_function ## _get_option (GstMixer * mixer, GstMixerOptions * opts) \
|
||||||
|
{ \
|
||||||
|
Type *this = (Type*) mixer; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (this != NULL, NULL); \
|
||||||
|
g_return_val_if_fail (this->mixer != NULL, NULL); \
|
||||||
|
\
|
||||||
|
return gst_alsa_mixer_get_option (this->mixer, opts); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static void \
|
||||||
|
interface_as_function ## _interface_init (GstMixerClass * klass) \
|
||||||
|
{ \
|
||||||
|
GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \
|
||||||
|
\
|
||||||
|
/* set up the interface hooks */ \
|
||||||
|
klass->list_tracks = interface_as_function ## _list_tracks; \
|
||||||
|
klass->set_volume = interface_as_function ## _set_volume; \
|
||||||
|
klass->get_volume = interface_as_function ## _get_volume; \
|
||||||
|
klass->set_mute = interface_as_function ## _set_mute; \
|
||||||
|
klass->set_record = interface_as_function ## _set_record; \
|
||||||
|
klass->set_option = interface_as_function ## _set_option; \
|
||||||
|
klass->get_option = interface_as_function ## _get_option; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
92
ext/alsa/gstalsamixerelement.c
Normal file
92
ext/alsa/gstalsamixerelement.c
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/* ALSA mixer implementation.
|
||||||
|
* Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstalsamixerelement.h"
|
||||||
|
|
||||||
|
|
||||||
|
static GstElementDetails gst_alsa_mixer_element_details =
|
||||||
|
GST_ELEMENT_DETAILS ("Alsa Mixer",
|
||||||
|
"Generic/Audio",
|
||||||
|
"Control sound input and output levels with ALSA",
|
||||||
|
"Leif Johnson <leif@ambient.2y.net>");
|
||||||
|
|
||||||
|
|
||||||
|
GST_BOILERPLATE_WITH_INTERFACE (GstAlsaMixerElement, gst_alsa_mixer_element,
|
||||||
|
GstElement, GST_TYPE_ELEMENT, GstMixer, GST_TYPE_MIXER,
|
||||||
|
gst_alsa_mixer_element);
|
||||||
|
|
||||||
|
GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaMixerElement, gst_alsa_mixer_element);
|
||||||
|
|
||||||
|
static GstElementStateReturn gst_alsa_mixer_element_change_state (GstElement *
|
||||||
|
element);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_alsa_mixer_element_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
|
||||||
|
&gst_alsa_mixer_element_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_alsa_mixer_element_class_init (GstAlsaMixerElementClass * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class;
|
||||||
|
|
||||||
|
element_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
element_class->change_state = gst_alsa_mixer_element_change_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_alsa_mixer_element_init (GstAlsaMixerElement * this)
|
||||||
|
{
|
||||||
|
this->mixer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstElementStateReturn
|
||||||
|
gst_alsa_mixer_element_change_state (GstElement * element)
|
||||||
|
{
|
||||||
|
GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (element);
|
||||||
|
|
||||||
|
switch (GST_STATE_TRANSITION (element)) {
|
||||||
|
case GST_STATE_NULL_TO_READY:
|
||||||
|
if (!this->mixer) {
|
||||||
|
this->mixer = gst_alsa_mixer_new ("hw:0", GST_ALSA_MIXER_ALL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GST_STATE_READY_TO_NULL:
|
||||||
|
if (this->mixer) {
|
||||||
|
gst_alsa_mixer_free (this->mixer);
|
||||||
|
this->mixer = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||||
|
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||||
|
|
||||||
|
return GST_STATE_SUCCESS;
|
||||||
|
}
|
59
ext/alsa/gstalsamixerelement.h
Normal file
59
ext/alsa/gstalsamixerelement.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* ALSA mixer interface implementation.
|
||||||
|
* Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
|
||||||
|
*
|
||||||
|
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_ALSA_MIXER_ELEMENT_H__
|
||||||
|
#define __GST_ALSA_MIXER_ELEMENT_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include "gstalsa.h"
|
||||||
|
#include "gstalsamixer.h"
|
||||||
|
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#define GST_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElement))
|
||||||
|
#define GST_ALSA_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElementClass))
|
||||||
|
#define GST_IS_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_ELEMENT))
|
||||||
|
#define GST_IS_ALSA_MIXER_ELEMENT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_ELEMENT))
|
||||||
|
#define GST_TYPE_ALSA_MIXER_ELEMENT (gst_alsa_mixer_element_get_type())
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GstAlsaMixerElement GstAlsaMixerElement;
|
||||||
|
typedef struct _GstAlsaMixerElementClass GstAlsaMixerElementClass;
|
||||||
|
|
||||||
|
|
||||||
|
struct _GstAlsaMixerElement {
|
||||||
|
GstElement parent;
|
||||||
|
|
||||||
|
GstAlsaMixer *mixer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAlsaMixerElementClass {
|
||||||
|
GstElementClass parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GType gst_alsa_mixer_element_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __GST_ALSA_MIXER_ELEMENT_H__ */
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include "gstalsasink.h"
|
#include "gstalsasink.h"
|
||||||
#include "gstalsasrc.h"
|
#include "gstalsasrc.h"
|
||||||
#include "gstalsamixer.h"
|
#include "gstalsamixerelement.h"
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (alsa_debug);
|
GST_DEBUG_CATEGORY (alsa_debug);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ plugin_init (GstPlugin * plugin)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!gst_element_register (plugin, "alsamixer", GST_RANK_NONE,
|
if (!gst_element_register (plugin, "alsamixer", GST_RANK_NONE,
|
||||||
GST_TYPE_ALSA_MIXER))
|
GST_TYPE_ALSA_MIXER_ELEMENT))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!gst_element_register (plugin, "alsasrc", GST_RANK_PRIMARY,
|
if (!gst_element_register (plugin, "alsasrc", GST_RANK_PRIMARY,
|
||||||
GST_TYPE_ALSA_SRC))
|
GST_TYPE_ALSA_SRC))
|
||||||
|
|
|
@ -46,9 +46,11 @@ enum
|
||||||
PROP_DEVICE,
|
PROP_DEVICE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_alsasrc_base_init (gpointer g_class);
|
GST_BOILERPLATE_WITH_INTERFACE (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
|
||||||
static void gst_alsasrc_class_init (GstAlsaSrcClass * klass);
|
GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_alsasrc_mixer);
|
||||||
static void gst_alsasrc_init (GstAlsaSrc * alsasrc);
|
|
||||||
|
GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
|
||||||
|
|
||||||
static void gst_alsasrc_dispose (GObject * object);
|
static void gst_alsasrc_dispose (GObject * object);
|
||||||
static void gst_alsasrc_set_property (GObject * object,
|
static void gst_alsasrc_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -57,7 +59,10 @@ static void gst_alsasrc_get_property (GObject * object,
|
||||||
|
|
||||||
static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
|
static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
|
||||||
|
|
||||||
static gboolean gst_alsasrc_open (GstAudioSrc * asrc, GstRingBufferSpec * spec);
|
static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
|
||||||
|
static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
|
||||||
|
GstRingBufferSpec * spec);
|
||||||
|
static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
|
||||||
static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
|
static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
|
||||||
static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
|
static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
|
||||||
static guint gst_alsasrc_delay (GstAudioSrc * asrc);
|
static guint gst_alsasrc_delay (GstAudioSrc * asrc);
|
||||||
|
@ -86,36 +91,6 @@ static GstStaticPadTemplate alsasrc_src_factory =
|
||||||
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
|
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
|
||||||
|
|
||||||
/* static guint gst_alsasrc_signals[LAST_SIGNAL] = { 0 }; */
|
|
||||||
|
|
||||||
GType
|
|
||||||
gst_alsasrc_get_type (void)
|
|
||||||
{
|
|
||||||
static GType alsasrc_type = 0;
|
|
||||||
|
|
||||||
if (!alsasrc_type) {
|
|
||||||
static const GTypeInfo alsasrc_info = {
|
|
||||||
sizeof (GstAlsaSrcClass),
|
|
||||||
gst_alsasrc_base_init,
|
|
||||||
NULL,
|
|
||||||
(GClassInitFunc) gst_alsasrc_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstAlsaSrc),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_alsasrc_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
alsasrc_type =
|
|
||||||
g_type_register_static (GST_TYPE_AUDIO_SRC, "GstAlsaSrc",
|
|
||||||
&alsasrc_info, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return alsasrc_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alsasrc_dispose (GObject * object)
|
gst_alsasrc_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -147,8 +122,6 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
|
||||||
gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
|
gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
|
||||||
gstaudiosrc_class = (GstAudioSrcClass *) klass;
|
gstaudiosrc_class = (GstAudioSrcClass *) klass;
|
||||||
|
|
||||||
parent_class = g_type_class_ref (GST_TYPE_BASE_AUDIO_SRC);
|
|
||||||
|
|
||||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_alsasrc_dispose);
|
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_alsasrc_dispose);
|
||||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
|
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
|
||||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
|
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
|
||||||
|
@ -156,6 +129,8 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
|
||||||
gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
|
gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
|
||||||
|
|
||||||
gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
|
gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
|
||||||
|
gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
|
||||||
|
gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
|
||||||
gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
|
gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
|
||||||
gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
|
gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
|
||||||
gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
|
gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
|
||||||
|
@ -475,7 +450,32 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_alsasrc_open (GstAudioSrc * asrc, GstRingBufferSpec * spec)
|
gst_alsasrc_open (GstAudioSrc * asrc)
|
||||||
|
{
|
||||||
|
GstAlsaSrc *alsa;
|
||||||
|
gint err;
|
||||||
|
|
||||||
|
alsa = GST_ALSA_SRC (asrc);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
|
||||||
|
SND_PCM_NONBLOCK), open_error);
|
||||||
|
|
||||||
|
if (!alsa->mixer)
|
||||||
|
alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
open_error:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
||||||
|
("Capture open error: %s", snd_strerror (err)), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
|
||||||
{
|
{
|
||||||
GstAlsaSrc *alsa;
|
GstAlsaSrc *alsa;
|
||||||
gint err;
|
gint err;
|
||||||
|
@ -485,9 +485,6 @@ gst_alsasrc_open (GstAudioSrc * asrc, GstRingBufferSpec * spec)
|
||||||
if (!alsasrc_parse_spec (alsa, spec))
|
if (!alsasrc_parse_spec (alsa, spec))
|
||||||
goto spec_parse;
|
goto spec_parse;
|
||||||
|
|
||||||
CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
|
|
||||||
SND_PCM_NONBLOCK), open_error);
|
|
||||||
|
|
||||||
CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
|
CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
|
||||||
|
|
||||||
CHECK (set_hwparams (alsa), hw_params_failed);
|
CHECK (set_hwparams (alsa), hw_params_failed);
|
||||||
|
@ -511,12 +508,6 @@ spec_parse:
|
||||||
("Error parsing spec"), (NULL));
|
("Error parsing spec"), (NULL));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
open_error:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
|
||||||
("Recording open error: %s", snd_strerror (err)), (NULL));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
non_block:
|
non_block:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
||||||
|
@ -544,18 +535,58 @@ prepare_failed:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_alsasrc_close (GstAudioSrc * asrc)
|
gst_alsasrc_unprepare (GstAudioSrc * asrc)
|
||||||
{
|
{
|
||||||
GstAlsaSrc *alsa;
|
GstAlsaSrc *alsa;
|
||||||
|
gint err;
|
||||||
|
|
||||||
alsa = GST_ALSA_SRC (asrc);
|
alsa = GST_ALSA_SRC (asrc);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_drop (alsa->handle), drop);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
|
||||||
|
|
||||||
|
CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
drop:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
||||||
|
("Could not drop samples: %s", snd_strerror (err)), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
hw_free:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
||||||
|
("Could not free hw params: %s", snd_strerror (err)), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
non_block:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
|
||||||
|
("Could not set device to nonblocking: %s", snd_strerror (err)),
|
||||||
|
(NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_alsasrc_close (GstAudioSrc * asrc)
|
||||||
|
{
|
||||||
|
GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
|
||||||
|
|
||||||
snd_pcm_close (alsa->handle);
|
snd_pcm_close (alsa->handle);
|
||||||
|
|
||||||
|
if (alsa->mixer) {
|
||||||
|
gst_alsa_mixer_free (alsa->mixer);
|
||||||
|
alsa->mixer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Underrun and suspend recovery
|
* Underrun and suspend recovery
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,9 +24,10 @@
|
||||||
#define __GST_ALSASRC_H__
|
#define __GST_ALSASRC_H__
|
||||||
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <gst/audio/gstaudiosrc.h>
|
#include <gst/audio/gstaudiosrc.h>
|
||||||
#include <alsa/asoundlib.h>
|
#include "gstalsa.h"
|
||||||
|
#include "gstalsamixer.h"
|
||||||
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ typedef struct _GstAlsaSrc GstAlsaSrc;
|
||||||
typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
|
typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
|
||||||
|
|
||||||
struct _GstAlsaSrc {
|
struct _GstAlsaSrc {
|
||||||
GstAudioSrc src;
|
GstAudioSrc src;
|
||||||
|
|
||||||
gchar *device;
|
gchar *device;
|
||||||
|
|
||||||
|
@ -48,16 +49,18 @@ struct _GstAlsaSrc {
|
||||||
snd_pcm_hw_params_t *hwparams;
|
snd_pcm_hw_params_t *hwparams;
|
||||||
snd_pcm_sw_params_t *swparams;
|
snd_pcm_sw_params_t *swparams;
|
||||||
|
|
||||||
snd_pcm_access_t access;
|
snd_pcm_access_t access;
|
||||||
snd_pcm_format_t format;
|
snd_pcm_format_t format;
|
||||||
guint rate;
|
guint rate;
|
||||||
guint channels;
|
guint channels;
|
||||||
gint bytes_per_sample;
|
gint bytes_per_sample;
|
||||||
|
|
||||||
guint buffer_time;
|
guint buffer_time;
|
||||||
guint period_time;
|
guint period_time;
|
||||||
snd_pcm_uframes_t buffer_size;
|
snd_pcm_uframes_t buffer_size;
|
||||||
snd_pcm_uframes_t period_size;
|
snd_pcm_uframes_t period_size;
|
||||||
|
|
||||||
|
GstAlsaMixer *mixer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAlsaSrcClass {
|
struct _GstAlsaSrcClass {
|
||||||
|
|
|
@ -70,6 +70,8 @@ static void gst_audioringbuffer_finalize (GObject * object);
|
||||||
|
|
||||||
static GstRingBufferClass *ring_parent_class = NULL;
|
static GstRingBufferClass *ring_parent_class = NULL;
|
||||||
|
|
||||||
|
static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf);
|
||||||
|
static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf);
|
||||||
static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
|
static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf,
|
||||||
GstRingBufferSpec * spec);
|
GstRingBufferSpec * spec);
|
||||||
static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
|
static gboolean gst_audioringbuffer_release (GstRingBuffer * buf);
|
||||||
|
@ -120,6 +122,10 @@ gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass)
|
||||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_audioringbuffer_dispose);
|
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_audioringbuffer_dispose);
|
||||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_audioringbuffer_finalize);
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_audioringbuffer_finalize);
|
||||||
|
|
||||||
|
gstringbuffer_class->open_device =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device);
|
||||||
|
gstringbuffer_class->close_device =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device);
|
||||||
gstringbuffer_class->acquire =
|
gstringbuffer_class->acquire =
|
||||||
GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
|
GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire);
|
||||||
gstringbuffer_class->release =
|
gstringbuffer_class->release =
|
||||||
|
@ -232,6 +238,54 @@ gst_audioringbuffer_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (ring_parent_class)->finalize (object);
|
G_OBJECT_CLASS (ring_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_audioringbuffer_open_device (GstRingBuffer * buf)
|
||||||
|
{
|
||||||
|
GstAudioSrc *src;
|
||||||
|
GstAudioSrcClass *csrc;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
|
||||||
|
src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
|
||||||
|
csrc = GST_AUDIO_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
|
if (csrc->open)
|
||||||
|
result = csrc->open (src);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
goto could_not_open;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
could_not_open:
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_audioringbuffer_close_device (GstRingBuffer * buf)
|
||||||
|
{
|
||||||
|
GstAudioSrc *src;
|
||||||
|
GstAudioSrcClass *csrc;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
|
||||||
|
src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
|
||||||
|
csrc = GST_AUDIO_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
|
if (csrc->close)
|
||||||
|
result = csrc->close (src);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
goto could_not_open;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
could_not_open:
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
|
gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
|
||||||
{
|
{
|
||||||
|
@ -243,8 +297,8 @@ gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
|
||||||
src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
|
src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf));
|
||||||
csrc = GST_AUDIO_SRC_GET_CLASS (src);
|
csrc = GST_AUDIO_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
if (csrc->open)
|
if (csrc->prepare)
|
||||||
result = csrc->open (src, spec);
|
result = csrc->prepare (src, spec);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
goto could_not_open;
|
goto could_not_open;
|
||||||
|
@ -297,8 +351,8 @@ gst_audioringbuffer_release (GstRingBuffer * buf)
|
||||||
gst_buffer_unref (buf->data);
|
gst_buffer_unref (buf->data);
|
||||||
buf->data = NULL;
|
buf->data = NULL;
|
||||||
|
|
||||||
if (csrc->close)
|
if (csrc->unprepare)
|
||||||
result = csrc->close (src);
|
result = csrc->unprepare (src);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,15 +69,19 @@ struct _GstAudioSrcClass {
|
||||||
/* vtable */
|
/* vtable */
|
||||||
|
|
||||||
/* open the device with given specs */
|
/* open the device with given specs */
|
||||||
gboolean (*open) (GstAudioSrc *src, GstRingBufferSpec *spec);
|
gboolean (*open) (GstAudioSrc *src);
|
||||||
|
/* prepare resources and state to operate with the given specs */
|
||||||
|
gboolean (*prepare) (GstAudioSrc *src, GstRingBufferSpec *spec);
|
||||||
|
/* undo anything that was done in prepare() */
|
||||||
|
gboolean (*unprepare) (GstAudioSrc *src);
|
||||||
/* close the device */
|
/* close the device */
|
||||||
gboolean (*close) (GstAudioSrc *src);
|
gboolean (*close) (GstAudioSrc *src);
|
||||||
/* read samples from the device */
|
/* read samples from the device */
|
||||||
guint (*read) (GstAudioSrc *src, gpointer data, guint length);
|
guint (*read) (GstAudioSrc *src, gpointer data, guint length);
|
||||||
/* get number of samples queued in the device */
|
/* get number of samples queued in the device */
|
||||||
guint (*delay) (GstAudioSrc *src);
|
guint (*delay) (GstAudioSrc *src);
|
||||||
/* reset the audio device, unblock from a write */
|
/* reset the audio device, unblock from a write */
|
||||||
void (*reset) (GstAudioSrc *src);
|
void (*reset) (GstAudioSrc *src);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
|
Loading…
Reference in a new issue