From 547ce2fd805f6a008df03e6deef215bbb1bb5c65 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 May 2006 00:20:30 +0000 Subject: add mixer interface to GstSource git-svn-id: file:///home/lennart/svn/public/gst-pulse/trunk@28 bb39ca4e-bce3-0310-b5d4-eea78a553289 --- src/polypmixer.c | 2 +- src/polypmixerctrl.c | 43 +++++++++++++++-------------- src/polypmixerctrl.h | 11 ++++++-- src/polypsrc.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/polypsrc.h | 4 +++ 5 files changed, 112 insertions(+), 25 deletions(-) diff --git a/src/polypmixer.c b/src/polypmixer.c index 0b18325..57fa162 100644 --- a/src/polypmixer.c +++ b/src/polypmixer.c @@ -222,7 +222,7 @@ static GstStateChangeReturn gst_polypmixer_change_state(GstElement *element, Gst case GST_STATE_CHANGE_NULL_TO_READY: if (!this->mixer) - this->mixer = gst_polypmixer_ctrl_new(this->server, this->device); + this->mixer = gst_polypmixer_ctrl_new(this->server, this->device, GST_POLYPMIXER_UNKNOWN); break; diff --git a/src/polypmixerctrl.c b/src/polypmixerctrl.c index 5b89acc..42cea8a 100644 --- a/src/polypmixerctrl.c +++ b/src/polypmixerctrl.c @@ -210,28 +210,28 @@ static gboolean gst_polypmixer_ctrl_open(GstPolypMixerCtrl *c) { /* Get sink info */ - if (!(o = pa_context_get_sink_info_by_name(c->context, c->device, gst_polypmixer_ctrl_sink_info_cb, c))) { - GST_WARNING("Failed to get sink info: %s", pa_strerror(pa_context_errno(c->context))); - goto unlock_and_fail; - } - - c->operation_success = 0; - while (pa_operation_get_state(o) != PA_OPERATION_DONE) { - pa_threaded_mainloop_wait(c->mainloop); - CHECK_DEAD_GOTO(c, unlock_and_fail); - } - - if (!c->operation_success) { - - if (pa_context_errno(c->context) != PA_ERR_NOENTITY) { + if (c->type == GST_POLYPMIXER_UNKNOWN || c->type == GST_POLYPMIXER_SINK) { + if (!(o = pa_context_get_sink_info_by_name(c->context, c->device, gst_polypmixer_ctrl_sink_info_cb, c))) { GST_WARNING("Failed to get sink info: %s", pa_strerror(pa_context_errno(c->context))); goto unlock_and_fail; } - - /* This device wasn't a sink, hence look for a source */ + + c->operation_success = 0; + while (pa_operation_get_state(o) != PA_OPERATION_DONE) { + pa_threaded_mainloop_wait(c->mainloop); + CHECK_DEAD_GOTO(c, unlock_and_fail); + } pa_operation_unref(o); + o = NULL; + + if (!c->operation_success && (c->type == GST_POLYPMIXER_SINK || pa_context_errno(c->context) != PA_ERR_NOENTITY)) { + GST_WARNING("Failed to get sink info: %s", pa_strerror(pa_context_errno(c->context))); + goto unlock_and_fail; + } + } + if (c->type == GST_POLYPMIXER_UNKNOWN || c->type == GST_POLYPMIXER_SOURCE) { if (!(o = pa_context_get_source_info_by_name(c->context, c->device, gst_polypmixer_ctrl_source_info_cb, c))) { GST_WARNING("Failed to get source info: %s", pa_strerror(pa_context_errno(c->context))); goto unlock_and_fail; @@ -243,17 +243,20 @@ static gboolean gst_polypmixer_ctrl_open(GstPolypMixerCtrl *c) { CHECK_DEAD_GOTO(c, unlock_and_fail); } + pa_operation_unref(o); + o = NULL; + if (!c->operation_success) { GST_WARNING("Failed to get source info: %s", pa_strerror(pa_context_errno(c->context))); goto unlock_and_fail; } } + g_assert(c->type != GST_POLYPMIXER_UNKNOWN); + c->track = gst_polypmixer_track_new(c); c->tracklist = g_list_append(c->tracklist, c->track); - pa_operation_unref(o); - pa_threaded_mainloop_unlock(c->mainloop); g_free(name); @@ -302,7 +305,7 @@ static void gst_polypmixer_ctrl_close(GstPolypMixerCtrl *c) { } } -GstPolypMixerCtrl* gst_polypmixer_ctrl_new(const gchar *server, const gchar *device) { +GstPolypMixerCtrl* gst_polypmixer_ctrl_new(const gchar *server, const gchar *device, GstPolypMixerType type) { GstPolypMixerCtrl *c = NULL; c = g_new(GstPolypMixerCtrl, 1); @@ -317,7 +320,7 @@ GstPolypMixerCtrl* gst_polypmixer_ctrl_new(const gchar *server, const gchar *dev pa_channel_map_init(&c->channel_map); c->muted = 0; c->index = PA_INVALID_INDEX; - c->type = GST_POLYPMIXER_UNKNOWN; + c->type = type; c->name = NULL; c->description = NULL; diff --git a/src/polypmixerctrl.h b/src/polypmixerctrl.h index 4833c6e..2f22c54 100644 --- a/src/polypmixerctrl.h +++ b/src/polypmixerctrl.h @@ -34,6 +34,13 @@ G_BEGIN_DECLS typedef struct _GstPolypMixerCtrl GstPolypMixerCtrl; + +typedef enum { + GST_POLYPMIXER_UNKNOWN, + GST_POLYPMIXER_SINK, + GST_POLYPMIXER_SOURCE } +GstPolypMixerType; + struct _GstPolypMixerCtrl { GList *tracklist; @@ -47,7 +54,7 @@ struct _GstPolypMixerCtrl { pa_cvolume volume; int muted; guint32 index; - enum { GST_POLYPMIXER_UNKNOWN, GST_POLYPMIXER_SINK, GST_POLYPMIXER_SOURCE } type; + GstPolypMixerType type; int operation_success; GstMixerTrack *track; @@ -55,7 +62,7 @@ struct _GstPolypMixerCtrl { pa_time_event *time_event; }; -GstPolypMixerCtrl* gst_polypmixer_ctrl_new(const gchar *server, const gchar *device); +GstPolypMixerCtrl* gst_polypmixer_ctrl_new(const gchar *server, const gchar *device, GstPolypMixerType type); void gst_polypmixer_ctrl_free(GstPolypMixerCtrl*mixer); const GList* gst_polypmixer_ctrl_list_tracks(GstPolypMixerCtrl *mixer); diff --git a/src/polypsrc.c b/src/polypsrc.c index 5bd9e70..306ffff 100644 --- a/src/polypsrc.c +++ b/src/polypsrc.c @@ -31,6 +31,7 @@ #include "polypsrc.h" #include "polyputil.h" +#include "polypmixerctrl.h" GST_DEBUG_CATEGORY_EXTERN(polyp_debug); #define GST_CAT_DEFAULT polyp_debug @@ -42,6 +43,8 @@ enum { static GstAudioSrcClass *parent_class = NULL; +GST_IMPLEMENT_POLYPMIXER_CTRL_METHODS(GstPolypSrc, gst_polypsrc) + static void gst_polypsrc_destroy_stream(GstPolypSrc *polypsrc); static void gst_polypsrc_destroy_context(GstPolypSrc *polypsrc); @@ -59,12 +62,43 @@ static gboolean gst_polypsrc_unprepare(GstAudioSrc *asrc); static guint gst_polypsrc_read(GstAudioSrc *asrc, gpointer data, guint length); static guint gst_polypsrc_delay(GstAudioSrc *asrc); +static GstStateChangeReturn gst_polypsrc_change_state(GstElement *element, GstStateChange transition); + #if (G_BYTE_ORDER == G_LITTLE_ENDIAN) # define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN" #else # define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN" #endif +static gboolean gst_polypsrc_interface_supported(GstImplementsInterface* iface, GType interface_type) { + GstPolypSrc *this = GST_POLYPSRC(iface); + + if (interface_type == GST_TYPE_MIXER && this->mixer) + return TRUE; + + return FALSE; +} + +static void gst_polypsrc_implements_interface_init(GstImplementsInterfaceClass* klass) { + klass->supported = gst_polypsrc_interface_supported; +} + +static void gst_polypsrc_init_interfaces(GType type) { + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_polypsrc_implements_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) gst_polypsrc_mixer_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static(type, GST_TYPE_IMPLEMENTS_INTERFACE, &implements_iface_info); + g_type_add_interface_static(type, GST_TYPE_MIXER, &mixer_iface_info); +} + static void gst_polypsrc_base_init(gpointer g_class) { static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE( @@ -122,8 +156,11 @@ static void gst_polypsrc_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS(g_class); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS(g_class); parent_class = g_type_class_peek_parent(g_class); - + + gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_polypsrc_change_state); + gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_polypsrc_dispose); gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_polypsrc_finalize); gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_polypsrc_set_property); @@ -167,6 +204,8 @@ static void gst_polypsrc_init( e = pa_threaded_mainloop_start(polypsrc->mainloop); g_assert(e == 0); + + polypsrc->mixer = NULL; } static void gst_polypsrc_destroy_stream(GstPolypSrc* polypsrc) { @@ -200,6 +239,9 @@ static void gst_polypsrc_finalize(GObject * object) { pa_threaded_mainloop_free(polypsrc->mainloop); + if (polypsrc->mixer) + gst_polypmixer_ctrl_free(polypsrc->mixer); + G_OBJECT_CLASS(parent_class)->finalize(object); } @@ -479,7 +521,6 @@ static guint gst_polypsrc_read(GstAudioSrc *asrc, gpointer data, guint length) { return sum; unlock_and_fail: - pa_threaded_mainloop_unlock(polypsrc->mainloop); return 0; } @@ -515,6 +556,36 @@ unlock_and_fail: return 0; } +static GstStateChangeReturn gst_polypsrc_change_state(GstElement *element, GstStateChange transition) { + GstPolypSrc *this = GST_POLYPSRC(element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + + if (!this->mixer) + this->mixer = gst_polypmixer_ctrl_new(this->server, this->device, GST_POLYPMIXER_SOURCE); + + break; + + case GST_STATE_CHANGE_READY_TO_NULL: + + if (this->mixer) { + gst_polypmixer_ctrl_free(this->mixer); + this->mixer = NULL; + } + + break; + + default: + ; + } + + if (GST_ELEMENT_CLASS(parent_class)->change_state) + return GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + + return GST_STATE_CHANGE_SUCCESS; +} + GType gst_polypsrc_get_type(void) { static GType polypsrc_type = 0; @@ -537,6 +608,8 @@ GType gst_polypsrc_get_type(void) { "GstPolypSrc", &polypsrc_info, 0); + + gst_polypsrc_init_interfaces(polypsrc_type); } return polypsrc_type; diff --git a/src/polypsrc.h b/src/polypsrc.h index 0f77c8f..d426c7d 100644 --- a/src/polypsrc.h +++ b/src/polypsrc.h @@ -28,6 +28,8 @@ #include #include +#include "polypmixerctrl.h" + G_BEGIN_DECLS #define GST_TYPE_POLYPSRC \ @@ -58,6 +60,8 @@ struct _GstPolypSrc { const void *read_buffer; size_t read_buffer_length; + + GstPolypMixerCtrl *mixer; }; struct _GstPolypSrcClass { -- cgit