summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2006-05-12 00:20:30 +0000
committerLennart Poettering <lennart@poettering.net>2006-05-12 00:20:30 +0000
commit547ce2fd805f6a008df03e6deef215bbb1bb5c65 (patch)
treea92bc67616a09168bb6b87d7f3d96db62cf8238c
parent743b4b1ef29046ec07846daa9ae0c2869044c832 (diff)
add mixer interface to GstSource
git-svn-id: file:///home/lennart/svn/public/gst-pulse/trunk@28 bb39ca4e-bce3-0310-b5d4-eea78a553289
-rw-r--r--src/polypmixer.c2
-rw-r--r--src/polypmixerctrl.c43
-rw-r--r--src/polypmixerctrl.h11
-rw-r--r--src/polypsrc.c77
-rw-r--r--src/polypsrc.h4
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 <polyp/polypaudio.h>
#include <polyp/thread-mainloop.h>
+#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 {