⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsta2dpsink.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org> * * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Lesser General Public *  License as published by the Free Software Foundation; either *  version 2.1 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 *  Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <unistd.h>#include <pthread.h>#include "gsta2dpsink.h"GST_DEBUG_CATEGORY_STATIC(gst_a2dp_sink_debug);#define GST_CAT_DEFAULT gst_a2dp_sink_debug#define A2DP_SBC_RTP_PAYLOAD_TYPE 1#define TEMPLATE_MAX_BITPOOL_STR "64"#define DEFAULT_AUTOCONNECT TRUEenum {	PROP_0,	PROP_DEVICE,	PROP_AUTOCONNECT};GST_BOILERPLATE(GstA2dpSink, gst_a2dp_sink, GstBin, GST_TYPE_BIN);static const GstElementDetails gst_a2dp_sink_details =	GST_ELEMENT_DETAILS("Bluetooth A2DP sink",				"Sink/Audio",				"Plays audio to an A2DP device",				"Marcel Holtmann <marcel@holtmann.org>");static GstStaticPadTemplate gst_a2dp_sink_factory =	GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,			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\" }, "				"bitpool = (int) [ 2, "				TEMPLATE_MAX_BITPOOL_STR " ]; "				"audio/mpeg"				));static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event);static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps);static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad);static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self);static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self);static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self);static void gst_a2dp_sink_finalize(GObject *obj){	GstA2dpSink *self = GST_A2DP_SINK(obj);	g_mutex_free(self->cb_mutex);	G_OBJECT_CLASS (parent_class)->finalize (obj);}static GstState gst_a2dp_sink_get_state(GstA2dpSink *self){	GstState current, pending;	gst_element_get_state(GST_ELEMENT(self), &current, &pending, 0);	if (pending == GST_STATE_VOID_PENDING)		return current;	return pending;}/* * Helper function to create elements, add to the bin and link it * to another element. */static GstElement* gst_a2dp_sink_init_element(GstA2dpSink *self,			const gchar* elementname, const gchar* name,			GstElement *link_to){	GstElement *element;	GstState state;	GST_LOG_OBJECT(self, "Initializing %s", elementname);	element = gst_element_factory_make(elementname, name);	if (element == NULL) {		GST_DEBUG_OBJECT(self, "Couldn't create %s", elementname);		return NULL;	}	if (!gst_bin_add(GST_BIN(self), element)) {		GST_DEBUG_OBJECT(self, "failed to add %s to the bin",						elementname);		goto cleanup_and_fail;	}	state = gst_a2dp_sink_get_state(self);	if (gst_element_set_state(element, state) ==			GST_STATE_CHANGE_FAILURE) {		GST_DEBUG_OBJECT(self, "%s failed to go to playing",						elementname);		goto remove_element_and_fail;	}	if (link_to != NULL)		if (!gst_element_link(link_to, element)) {			GST_DEBUG_OBJECT(self, "couldn't link %s",					elementname);			goto remove_element_and_fail;		}	return element;remove_element_and_fail:	gst_element_set_state(element, GST_STATE_NULL);	gst_bin_remove(GST_BIN(self), element);	return NULL;cleanup_and_fail:	if (element != NULL)		g_object_unref(G_OBJECT(element));	return NULL;}static void gst_a2dp_sink_base_init(gpointer g_class){	GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);	gst_element_class_set_details(element_class,		&gst_a2dp_sink_details);	gst_element_class_add_pad_template(element_class,		gst_static_pad_template_get(&gst_a2dp_sink_factory));}static void gst_a2dp_sink_set_property(GObject *object, guint prop_id,					const GValue *value, GParamSpec *pspec){	GstA2dpSink *self = GST_A2DP_SINK(object);	switch (prop_id) {	case PROP_DEVICE:		if (self->sink != NULL)			gst_avdtp_sink_set_device(self->sink,				g_value_get_string(value));		if (self->device != NULL)			g_free(self->device);		self->device = g_value_dup_string(value);		break;	case PROP_AUTOCONNECT:		self->autoconnect = g_value_get_boolean(value);		if (self->sink != NULL)			g_object_set(G_OBJECT(self->sink), "auto-connect",					self->autoconnect, NULL);		break;	default:		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);		break;	}}static void gst_a2dp_sink_get_property(GObject *object, guint prop_id,					GValue *value, GParamSpec *pspec){	GstA2dpSink *self = GST_A2DP_SINK(object);	gchar *device;	switch (prop_id) {	case PROP_DEVICE:		if (self->sink != NULL) {			device = gst_avdtp_sink_get_device(self->sink);			if (device != NULL)				g_value_take_string(value, device);		}		break;	case PROP_AUTOCONNECT:		if (self->sink != NULL)			g_object_get(G_OBJECT(self->sink), "auto-connect",				&self->autoconnect, NULL);		g_value_set_boolean(value, self->autoconnect);		break;	default:		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);		break;	}}static gboolean gst_a2dp_sink_init_ghost_pad(GstA2dpSink *self){	GstPad *capsfilter_pad;	/* we search for the capsfilter sinkpad */	capsfilter_pad = gst_element_get_static_pad(self->capsfilter, "sink");	/* now we add a ghostpad */	self->ghostpad = GST_GHOST_PAD(gst_ghost_pad_new("sink",		capsfilter_pad));	g_object_unref(capsfilter_pad);	/* the getcaps of our ghostpad must reflect the device caps */	gst_pad_set_getcaps_function(GST_PAD(self->ghostpad),				gst_a2dp_sink_get_caps);	self->ghostpad_setcapsfunc = GST_PAD_SETCAPSFUNC(self->ghostpad);	gst_pad_set_setcaps_function(GST_PAD(self->ghostpad),			GST_DEBUG_FUNCPTR(gst_a2dp_sink_set_caps));	/* we need to handle events on our own and we also need the eventfunc	 * of the ghostpad for forwarding calls */	self->ghostpad_eventfunc = GST_PAD_EVENTFUNC(GST_PAD(self->ghostpad));	gst_pad_set_event_function(GST_PAD(self->ghostpad),			gst_a2dp_sink_handle_event);	if (!gst_element_add_pad(GST_ELEMENT(self), GST_PAD(self->ghostpad)))		GST_ERROR_OBJECT(self, "failed to add ghostpad");	return TRUE;}static void gst_a2dp_sink_remove_dynamic_elements(GstA2dpSink *self){	if (self->rtp) {		GST_LOG_OBJECT(self, "removing rtp element from the bin");		if (!gst_bin_remove(GST_BIN(self), GST_ELEMENT(self->rtp)))			GST_WARNING_OBJECT(self, "failed to remove rtp "					"element from bin");		else			self->rtp = NULL;	}}static GstStateChangeReturn gst_a2dp_sink_change_state(GstElement *element,			GstStateChange transition){	GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;	GstA2dpSink *self = GST_A2DP_SINK(element);	switch (transition) {	case GST_STATE_CHANGE_READY_TO_PAUSED:		self->taglist = gst_tag_list_new();		gst_a2dp_sink_init_fakesink(self);		break;	case GST_STATE_CHANGE_NULL_TO_READY:		self->sink_is_in_bin = FALSE;		self->sink = GST_AVDTP_SINK(gst_element_factory_make(				"avdtpsink", "avdtpsink"));		if (self->sink == NULL) {			GST_WARNING_OBJECT(self, "failed to create avdtpsink");			return GST_STATE_CHANGE_FAILURE;		}		if (self->device != NULL)			gst_avdtp_sink_set_device(self->sink,					self->device);		g_object_set(G_OBJECT(self->sink), "auto-connect",					self->autoconnect, NULL);		ret = gst_element_set_state(GST_ELEMENT(self->sink),			GST_STATE_READY);		break;	default:		break;	}	if (ret == GST_STATE_CHANGE_FAILURE)		return ret;	ret = GST_ELEMENT_CLASS(parent_class)->change_state(element,                        transition);	switch (transition) {	case GST_STATE_CHANGE_PAUSED_TO_READY:		if (self->taglist) {			gst_tag_list_free(self->taglist);			self->taglist = NULL;		}		if (self->newseg_event != NULL) {			gst_event_unref(self->newseg_event);			self->newseg_event = NULL;		}		gst_a2dp_sink_remove_fakesink(self);		break;	case GST_STATE_CHANGE_READY_TO_NULL:		if (self->sink_is_in_bin) {			if (!gst_bin_remove(GST_BIN(self),						GST_ELEMENT(self->sink)))				GST_WARNING_OBJECT(self, "Failed to remove "						"avdtpsink from bin");		} else if (self->sink != NULL) {			gst_element_set_state(GST_ELEMENT(self->sink),					GST_STATE_NULL);			g_object_unref(G_OBJECT(self->sink));		}		self->sink = NULL;		gst_a2dp_sink_remove_dynamic_elements(self);		break;	default:		break;	}	return ret;}static void gst_a2dp_sink_class_init(GstA2dpSinkClass *klass){	GObjectClass *object_class = G_OBJECT_CLASS(klass);	GstElementClass *element_class = GST_ELEMENT_CLASS(klass);	parent_class = g_type_class_peek_parent(klass);	object_class->set_property = GST_DEBUG_FUNCPTR(					gst_a2dp_sink_set_property);	object_class->get_property = GST_DEBUG_FUNCPTR(					gst_a2dp_sink_get_property);	object_class->finalize = GST_DEBUG_FUNCPTR(					gst_a2dp_sink_finalize);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -