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

📄 sink.c

📁 BlueZ源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return TRUE;}static gboolean select_capabilities(struct avdtp *session,					struct avdtp_remote_sep *rsep,					GSList **caps){	struct avdtp_service_capability *media_transport, *media_codec;	struct sbc_codec_cap sbc_cap;	media_codec = avdtp_get_codec(rsep);	if (!media_codec)		return FALSE;	select_sbc_params(&sbc_cap, (struct sbc_codec_cap *) media_codec->data);	media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,						NULL, 0);	*caps = g_slist_append(*caps, media_transport);	media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,						sizeof(sbc_cap));	*caps = g_slist_append(*caps, media_codec);	return TRUE;}static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err,				void *user_data){	struct sink *sink = user_data;	struct pending_request *pending;	struct avdtp_local_sep *lsep;	struct avdtp_remote_sep *rsep;	GSList *caps = NULL;	int id;	pending = sink->connect;	if (err) {		avdtp_unref(sink->session);		sink->session = NULL;		if (avdtp_error_type(err) == AVDTP_ERROR_ERRNO				&& avdtp_error_posix_errno(err) != EHOSTDOWN) {			debug("connect:connect XCASE detected");			g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,					stream_setup_retry, sink);		} else			goto failed;		return;	}	debug("Discovery complete");	if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, AVDTP_MEDIA_TYPE_AUDIO,				A2DP_CODEC_SBC, &lsep, &rsep) < 0) {		error("No matching ACP and INT SEPs found");		goto failed;	}	if (!select_capabilities(session, rsep, &caps)) {		error("Unable to select remote SEP capabilities");		goto failed;	}	id = a2dp_source_config(sink->session, stream_setup_complete,				caps, sink);	if (id == 0)		goto failed;	pending->id = id;	return;failed:	error_failed(pending->conn, pending->msg, "Stream setup failed");	pending_request_free(pending);	sink->connect = NULL;	avdtp_unref(sink->session);	sink->session = NULL;}static DBusMessage *sink_connect(DBusConnection *conn,				DBusMessage *msg, void *data){	struct audio_device *dev = data;	struct sink *sink = dev->sink;	struct pending_request *pending;	if (!sink->session)		sink->session = avdtp_get(&dev->src, &dev->dst);	if (!sink->session)		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",						"Unable to get a session");	if (sink->connect || sink->disconnect)		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",						"%s", strerror(EBUSY));	if (sink->state >= AVDTP_STATE_OPEN)		return g_dbus_create_error(msg, ERROR_INTERFACE						".AlreadyConnected",						"Device Already Connected");	pending = g_new0(struct pending_request, 1);	pending->conn = dbus_connection_ref(conn);	pending->msg = dbus_message_ref(msg);	sink->connect = pending;	avdtp_discover(sink->session, discovery_complete, sink);	debug("stream creation in progress");	return NULL;}static DBusMessage *sink_disconnect(DBusConnection *conn,					DBusMessage *msg, void *data){	struct audio_device *device = data;	struct sink *sink = device->sink;	struct pending_request *pending;	int err;	if (!sink->session)		return g_dbus_create_error(msg, ERROR_INTERFACE						".NotConnected",						"Device not Connected");	if (sink->connect || sink->disconnect)		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",						"%s", strerror(EBUSY));	if (sink->state < AVDTP_STATE_OPEN) {		DBusMessage *reply = dbus_message_new_method_return(msg);		if (!reply)			return NULL;		avdtp_unref(sink->session);		sink->session = NULL;		return reply;	}	err = avdtp_close(sink->session, sink->stream);	if (err < 0)		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",						"%s", strerror(-err));	pending = g_new0(struct pending_request, 1);	pending->conn = dbus_connection_ref(conn);	pending->msg = dbus_message_ref(msg);	sink->disconnect = pending;	return NULL;}static DBusMessage *sink_is_connected(DBusConnection *conn,					DBusMessage *msg,					void *data){	struct audio_device *device = data;	struct sink *sink = device->sink;	DBusMessage *reply;	dbus_bool_t connected;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	connected = (sink->state >= AVDTP_STATE_CONFIGURED);	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected,					DBUS_TYPE_INVALID);	return reply;}static DBusMessage *sink_get_properties(DBusConnection *conn,					DBusMessage *msg, void *data){	struct audio_device *device = data;	DBusMessage *reply;	DBusMessageIter iter;	DBusMessageIter dict;	gboolean value;	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);	/* Playing */	value = (device->sink->state == AVDTP_STATE_STREAMING);	dict_append_entry(&dict, "Playing", DBUS_TYPE_BOOLEAN, &value);	/* Connected */	value = (device->sink->state >= AVDTP_STATE_CONFIGURED);	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &value);	dbus_message_iter_close_container(&iter, &dict);	return reply;}static GDBusMethodTable sink_methods[] = {	{ "Connect",		"",	"",	sink_connect,						G_DBUS_METHOD_FLAG_ASYNC },	{ "Disconnect",		"",	"",	sink_disconnect,						G_DBUS_METHOD_FLAG_ASYNC },	{ "IsConnected",	"",	"b",	sink_is_connected,						G_DBUS_METHOD_FLAG_DEPRECATED },	{ "GetProperties",	"",	"a{sv}",sink_get_properties },	{ NULL, NULL, NULL, NULL }};static GDBusSignalTable sink_signals[] = {	{ "Connected",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },	{ "Disconnected",		"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },	{ "Playing",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },	{ "Stopped",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },	{ "PropertyChanged",		"sv"	},	{ NULL, NULL }};static void sink_free(struct audio_device *dev){	struct sink *sink = dev->sink;	if (sink->cb_id)		avdtp_stream_remove_cb(sink->session, sink->stream,					sink->cb_id);	if (sink->session)		avdtp_unref(sink->session);	if (sink->connect)		pending_request_free(sink->connect);	if (sink->disconnect)		pending_request_free(sink->disconnect);	g_free(sink);	dev->sink = NULL;}static void path_unregister(void *data){	struct audio_device *dev = data;	info("Unregistered interface %s on path %s",		AUDIO_SINK_INTERFACE, dev->path);	sink_free(dev);}void sink_unregister(struct audio_device *dev){	g_dbus_unregister_interface(dev->conn, dev->path,		AUDIO_SINK_INTERFACE);}struct sink *sink_init(struct audio_device *dev){	if (!g_dbus_register_interface(dev->conn, dev->path,					AUDIO_SINK_INTERFACE,					sink_methods, sink_signals, NULL,					dev, path_unregister))		return NULL;	info("Registered interface %s on path %s",		AUDIO_SINK_INTERFACE, dev->path);	return g_new0(struct sink, 1);}gboolean sink_is_active(struct audio_device *dev){	struct sink *sink = dev->sink;	if (sink->session)		return TRUE;	return FALSE;}avdtp_state_t sink_get_state(struct audio_device *dev){	struct sink *sink = dev->sink;	return sink->state;}gboolean sink_new_stream(struct audio_device *dev, struct avdtp *session,				struct avdtp_stream *stream){	struct sink *sink = dev->sink;	if (sink->stream)		return FALSE;	if (!sink->session)		sink->session = avdtp_ref(session);	sink->stream = stream;	sink->cb_id = avdtp_stream_add_cb(session, stream,						stream_state_changed, dev);	return TRUE;}

⌨️ 快捷键说明

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