diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2007-08-26 14:14:34 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2007-08-26 14:14:34 +0000 | 
| commit | aea33a86fd7cced1796504c2a62f33c7a801a10e (patch) | |
| tree | 60ad3dbf7e0870ae4c281fba0bd2294f6e41c3b6 | |
| parent | 7e8ae7f5bd23a425674180df138d3dcc3b21afb6 (diff) | |
Add possible capabilities and connect to audio server
| -rw-r--r-- | audio/gsta2dpsink.c | 169 | ||||
| -rw-r--r-- | audio/gsta2dpsink.h | 4 | 
2 files changed, 118 insertions, 55 deletions
diff --git a/audio/gsta2dpsink.c b/audio/gsta2dpsink.c index 08832524..8a6a44f1 100644 --- a/audio/gsta2dpsink.c +++ b/audio/gsta2dpsink.c @@ -25,14 +25,24 @@  #include <config.h>  #endif +#include <unistd.h> +#include <sys/un.h> +#include <sys/socket.h> +  #include "ipc.h" -#include "sbc.h"  #include "gsta2dpsink.h"  GST_DEBUG_CATEGORY_STATIC(a2dp_sink_debug);  #define GST_CAT_DEFAULT a2dp_sink_debug +#define DEFAULT_DEVICE "default" + +enum { +	PROP_0, +	PROP_DEVICE, +}; +  GST_BOILERPLATE(GstA2dpSink, gst_a2dp_sink, GstAudioSink, GST_TYPE_AUDIO_SINK);  static const GstElementDetails a2dp_sink_details = @@ -41,138 +51,187 @@ static const GstElementDetails a2dp_sink_details =  				"Plays audio to an A2DP device",  				"Marcel Holtmann <marcel@holtmann.org>"); -static GstStaticPadTemplate sink_factory = +static GstStaticPadTemplate a2dp_sink_factory =  	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, -							GST_STATIC_CAPS("ANY")); +		GST_STATIC_CAPS("audio/x-sbc, " +				"rate = (int) { 16000, 32000, 44100, 48000 }, " +				"channels = (int) [ 1, 2 ], " +				"mode = (string) { mono, dual, stereo, joint }, " +				"blocks = (int) { 4, 8, 12, 16 }, " +				"subbands = (int) { 4, 8 }, " +				"allocation = (string) { snr, loudness }; " + +				"audio/mpeg, " +				"mpegversion = (int) 1, " +				"layer = (int) [ 1, 3 ], " +				"rate = (int) { 16000, 22050, 24000, 32000, 44100, 48000 }, " +				"channels = (int) [ 1, 2 ]"));  static void gst_a2dp_sink_base_init(gpointer g_class)  {  	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class); -	GST_DEBUG(""); -  	gst_element_class_add_pad_template(element_class, -			gst_static_pad_template_get(&sink_factory)); +		gst_static_pad_template_get(&a2dp_sink_factory));  	gst_element_class_set_details(element_class, &a2dp_sink_details);  } -static void gst_a2dp_sink_dispose(GObject *object) -{ -	G_OBJECT_CLASS(parent_class)->dispose(object); -} -  static void gst_a2dp_sink_finalize(GObject *object)  { +	GstA2dpSink *sink = GST_A2DP_SINK(object); + +	g_io_channel_close(sink->server); + +	g_free(sink->device); +  	G_OBJECT_CLASS(parent_class)->finalize(object);  } -static void gst_a2dp_sink_get_property(GObject *object, guint prop_id, -					GValue *value, GParamSpec *pspec) +static void gst_a2dp_sink_set_property(GObject *object, guint prop_id, +					const GValue *value, GParamSpec *pspec)  { +	GstA2dpSink *sink = GST_A2DP_SINK(object); +  	switch (prop_id) { +	case PROP_DEVICE: +		g_free(sink->device); +		sink->device = g_value_dup_string(value); + +		if (sink->device == NULL) +			sink->device = g_strdup(DEFAULT_DEVICE); +		break; +  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);  		break;  	}  } -static void gst_a2dp_sink_set_property(GObject *object, guint prop_id, -					const GValue *value, GParamSpec *pspec) +static void gst_a2dp_sink_get_property(GObject *object, guint prop_id, +					GValue *value, GParamSpec *pspec)  { +	GstA2dpSink *sink = GST_A2DP_SINK(object); +  	switch (prop_id) { +	case PROP_DEVICE: +		g_value_set_string(value, sink->device); +		break; +  	default:  		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);  		break;  	}  } -static GstCaps *gst_a2dp_sink_getcaps(GstBaseSink *basesink) +static gboolean gst_a2dp_sink_open(GstAudioSink *self)  { -	GST_DEBUG_OBJECT(basesink, ""); +	GstA2dpSink *sink = GST_A2DP_SINK(self); -	return NULL; -} - -static gboolean gst_a2dp_sink_open(GstAudioSink *audiosink) -{ -	GST_DEBUG_OBJECT(audiosink, ""); +	printf("device %s\n", sink->device); +	printf("open\n");  	return TRUE;  } -static gboolean gst_a2dp_sink_prepare(GstAudioSink *audiosink, +static gboolean gst_a2dp_sink_prepare(GstAudioSink *self,  						GstRingBufferSpec *spec)  { -	GST_DEBUG_OBJECT(audiosink, "spec %p", spec); +	printf("perpare\n"); +	printf("rate %d\n", spec->rate); +	printf("channels %d\n", spec->channels);  	return TRUE;  } -static gboolean gst_a2dp_sink_unprepare(GstAudioSink *audiosink) +static gboolean gst_a2dp_sink_unprepare(GstAudioSink *self)  { -	GST_DEBUG_OBJECT(audiosink, ""); +	printf("unprepare\n");  	return TRUE;  } -static gboolean gst_a2dp_sink_close(GstAudioSink *audiosink) +static gboolean gst_a2dp_sink_close(GstAudioSink *self)  { -	GST_DEBUG_OBJECT(audiosink, ""); +	printf("close\n");  	return TRUE;  } -static guint gst_a2dp_sink_write(GstAudioSink *audiosink, -						gpointer data, guint length) +static guint gst_a2dp_sink_write(GstAudioSink *self, +					gpointer data, guint length)  { -	GST_DEBUG_OBJECT(audiosink, "data %p length %d", data, length); - -	return length; +	return 0;  }  static guint gst_a2dp_sink_delay(GstAudioSink *audiosink)  { -	GST_DEBUG_OBJECT(audiosink, ""); +	printf("delay\n");  	return 0;  }  static void gst_a2dp_sink_reset(GstAudioSink *audiosink)  { -	GST_DEBUG_OBJECT(audiosink, ""); +	printf("reset\n");  } -static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) +static gboolean server_callback(GIOChannel *chan, +					GIOCondition cond, gpointer data)  { -	GObjectClass *gobject_class = G_OBJECT_CLASS(klass); -	GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS(klass); -	GstAudioSinkClass *gstaudiosink_class = GST_AUDIO_SINK_CLASS(klass); +	printf("callback\n"); -	GST_DEBUG(""); +	return TRUE; +} + +static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass) +{ +	GObjectClass *object_class = G_OBJECT_CLASS(klass); +	GstAudioSinkClass *audiosink_class = GST_AUDIO_SINK_CLASS(klass);  	parent_class = g_type_class_peek_parent(klass); -	gobject_class->dispose = GST_DEBUG_FUNCPTR(gst_a2dp_sink_dispose); -	gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_a2dp_sink_finalize); -	gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_a2dp_sink_get_property); -	gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_property); +	object_class->finalize = GST_DEBUG_FUNCPTR(gst_a2dp_sink_finalize); +	object_class->set_property = GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_property); +	object_class->get_property = GST_DEBUG_FUNCPTR(gst_a2dp_sink_get_property); -	gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_a2dp_sink_getcaps); +	audiosink_class->open = GST_DEBUG_FUNCPTR(gst_a2dp_sink_open); +	audiosink_class->prepare = GST_DEBUG_FUNCPTR(gst_a2dp_sink_prepare); +	audiosink_class->unprepare = GST_DEBUG_FUNCPTR(gst_a2dp_sink_unprepare); +	audiosink_class->close = GST_DEBUG_FUNCPTR(gst_a2dp_sink_close); +	audiosink_class->write = GST_DEBUG_FUNCPTR(gst_a2dp_sink_write); +	audiosink_class->delay = GST_DEBUG_FUNCPTR(gst_a2dp_sink_delay); +	audiosink_class->reset = GST_DEBUG_FUNCPTR(gst_a2dp_sink_reset); -	gstaudiosink_class->open = GST_DEBUG_FUNCPTR(gst_a2dp_sink_open); -	gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR(gst_a2dp_sink_prepare); -	gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR(gst_a2dp_sink_unprepare); -	gstaudiosink_class->close = GST_DEBUG_FUNCPTR(gst_a2dp_sink_close); -	gstaudiosink_class->write = GST_DEBUG_FUNCPTR(gst_a2dp_sink_write); -	gstaudiosink_class->delay = GST_DEBUG_FUNCPTR(gst_a2dp_sink_delay); -	gstaudiosink_class->reset = GST_DEBUG_FUNCPTR(gst_a2dp_sink_reset); +	g_object_class_install_property(object_class, PROP_DEVICE, +				g_param_spec_string("device", "Device", +					"Bluetooth remote device", +					DEFAULT_DEVICE, G_PARAM_READWRITE));  	GST_DEBUG_CATEGORY_INIT(a2dp_sink_debug, "a2dpsink", 0,  						"A2DP sink element");  } -static void gst_a2dp_sink_init(GstA2dpSink *a2dpsink, GstA2dpSinkClass *klass) +static void gst_a2dp_sink_init(GstA2dpSink *self, GstA2dpSinkClass *klass)  { -	GST_DEBUG_OBJECT(a2dpsink, ""); +	struct sockaddr_un addr = { AF_UNIX, IPC_SOCKET_NAME }; +	int sk; + +	self->device = g_strdup(DEFAULT_DEVICE); + +	sk = socket(PF_LOCAL, SOCK_STREAM, 0); +	if (sk < 0) +		return; + +	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { +		close(sk); +		return; +	} + +	self->server = g_io_channel_unix_new(sk); + +	g_io_add_watch(self->server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, +							server_callback, self); + +	g_io_channel_unref(self->server);  } diff --git a/audio/gsta2dpsink.h b/audio/gsta2dpsink.h index 9575bc44..c83ec66c 100644 --- a/audio/gsta2dpsink.h +++ b/audio/gsta2dpsink.h @@ -42,6 +42,10 @@ typedef struct _GstA2dpSinkClass GstA2dpSinkClass;  struct _GstA2dpSink {  	GstAudioSink sink; + +	gchar *device; + +	GIOChannel *server;  };  struct _GstA2dpSinkClass {  | 
