Home | History | Annotate | Download | only in audio
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2006-2007  Nokia Corporation
      6  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel (at) holtmann.org>
      7  *  Copyright (C) 2009-2010  Motorola Inc.
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include <config.h>
     27 #endif
     28 
     29 #include <stdint.h>
     30 #include <errno.h>
     31 
     32 #include <bluetooth/bluetooth.h>
     33 #include <bluetooth/sdp.h>
     34 
     35 #include <glib.h>
     36 #include <dbus/dbus.h>
     37 #include <gdbus.h>
     38 
     39 #include "log.h"
     40 
     41 #include "device.h"
     42 #include "avdtp.h"
     43 #include "media.h"
     44 #include "a2dp.h"
     45 #include "error.h"
     46 #include "sink.h"
     47 #include "dbus-common.h"
     48 #include "../src/adapter.h"
     49 #include "../src/device.h"
     50 
     51 #define STREAM_SETUP_RETRY_TIMER 2
     52 
     53 struct pending_request {
     54 	DBusConnection *conn;
     55 	DBusMessage *msg;
     56 	unsigned int id;
     57 };
     58 
     59 struct sink {
     60 	struct audio_device *dev;
     61 	struct avdtp *session;
     62 	struct avdtp_stream *stream;
     63 	unsigned int cb_id;
     64 	guint retry_id;
     65 	avdtp_session_state_t session_state;
     66 	avdtp_state_t stream_state;
     67 	sink_state_t state;
     68 	struct pending_request *connect;
     69 	struct pending_request *disconnect;
     70 	DBusConnection *conn;
     71 };
     72 
     73 struct sink_state_callback {
     74 	sink_state_cb cb;
     75 	void *user_data;
     76 	unsigned int id;
     77 };
     78 
     79 static GSList *sink_callbacks = NULL;
     80 
     81 static unsigned int avdtp_callback_id = 0;
     82 
     83 static char *str_state[] = {
     84 	"SINK_STATE_DISCONNECTED",
     85 	"SINK_STATE_CONNECTING",
     86 	"SINK_STATE_CONNECTED",
     87 	"SINK_STATE_PLAYING",
     88 };
     89 
     90 static const char *state2str(sink_state_t state)
     91 {
     92 	switch (state) {
     93 	case SINK_STATE_DISCONNECTED:
     94 		return "disconnected";
     95 	case SINK_STATE_CONNECTING:
     96 		return "connecting";
     97 	case SINK_STATE_CONNECTED:
     98 		return "connected";
     99 	case SINK_STATE_PLAYING:
    100 		return "playing";
    101 	default:
    102 		error("Invalid sink state %d", state);
    103 		return NULL;
    104 	}
    105 }
    106 
    107 static void sink_set_state(struct audio_device *dev, sink_state_t new_state)
    108 {
    109 	struct sink *sink = dev->sink;
    110 	const char *state_str;
    111 	sink_state_t old_state = sink->state;
    112 	GSList *l;
    113 
    114 	sink->state = new_state;
    115 
    116 	state_str = state2str(new_state);
    117 	if (state_str)
    118 		emit_property_changed(dev->conn, dev->path,
    119 					AUDIO_SINK_INTERFACE, "State",
    120 					DBUS_TYPE_STRING, &state_str);
    121 
    122 	DBG("State changed %s: %s -> %s", dev->path, str_state[old_state],
    123 		str_state[new_state]);
    124 
    125 	for (l = sink_callbacks; l != NULL; l = l->next) {
    126 		struct sink_state_callback *cb = l->data;
    127 		cb->cb(dev, old_state, new_state, cb->user_data);
    128 	}
    129 }
    130 
    131 static void avdtp_state_callback(struct audio_device *dev,
    132 					struct avdtp *session,
    133 					avdtp_session_state_t old_state,
    134 					avdtp_session_state_t new_state,
    135 					void *user_data)
    136 {
    137 	struct sink *sink = dev->sink;
    138 
    139 	if (sink == NULL)
    140 		return;
    141 
    142 	switch (new_state) {
    143 	case AVDTP_SESSION_STATE_DISCONNECTED:
    144 		if (sink->state != SINK_STATE_CONNECTING) {
    145 			gboolean value = FALSE;
    146 			g_dbus_emit_signal(dev->conn, dev->path,
    147 					AUDIO_SINK_INTERFACE, "Disconnected",
    148 					DBUS_TYPE_INVALID);
    149 			emit_property_changed(dev->conn, dev->path,
    150 					AUDIO_SINK_INTERFACE, "Connected",
    151 					DBUS_TYPE_BOOLEAN, &value);
    152 		}
    153 		sink_set_state(dev, SINK_STATE_DISCONNECTED);
    154 		break;
    155 	case AVDTP_SESSION_STATE_CONNECTING:
    156 		sink_set_state(dev, SINK_STATE_CONNECTING);
    157 		break;
    158 	case AVDTP_SESSION_STATE_CONNECTED:
    159 		break;
    160 	}
    161 
    162 	sink->session_state = new_state;
    163 }
    164 
    165 static void pending_request_free(struct audio_device *dev,
    166 					struct pending_request *pending)
    167 {
    168 	if (pending->conn)
    169 		dbus_connection_unref(pending->conn);
    170 	if (pending->msg)
    171 		dbus_message_unref(pending->msg);
    172 	if (pending->id)
    173 		a2dp_cancel(dev, pending->id);
    174 
    175 	g_free(pending);
    176 }
    177 
    178 static void stream_state_changed(struct avdtp_stream *stream,
    179 					avdtp_state_t old_state,
    180 					avdtp_state_t new_state,
    181 					struct avdtp_error *err,
    182 					void *user_data)
    183 {
    184 	struct audio_device *dev = user_data;
    185 	struct sink *sink = dev->sink;
    186 	gboolean value;
    187 
    188 	if (err)
    189 		return;
    190 
    191 	switch (new_state) {
    192 	case AVDTP_STATE_IDLE:
    193 		if (sink->disconnect) {
    194 			DBusMessage *reply;
    195 			struct pending_request *p;
    196 
    197 			p = sink->disconnect;
    198 			sink->disconnect = NULL;
    199 
    200 			reply = dbus_message_new_method_return(p->msg);
    201 			g_dbus_send_message(p->conn, reply);
    202 			pending_request_free(dev, p);
    203 		}
    204 
    205 		if (sink->session) {
    206 			avdtp_unref(sink->session);
    207 			sink->session = NULL;
    208 		}
    209 		sink->stream = NULL;
    210 		sink->cb_id = 0;
    211 		break;
    212 	case AVDTP_STATE_OPEN:
    213 		if (old_state == AVDTP_STATE_CONFIGURED &&
    214 				sink->state == SINK_STATE_CONNECTING) {
    215 			value = TRUE;
    216 			g_dbus_emit_signal(dev->conn, dev->path,
    217 						AUDIO_SINK_INTERFACE,
    218 						"Connected",
    219 						DBUS_TYPE_INVALID);
    220 			emit_property_changed(dev->conn, dev->path,
    221 						AUDIO_SINK_INTERFACE,
    222 						"Connected",
    223 						DBUS_TYPE_BOOLEAN, &value);
    224 		} else if (old_state == AVDTP_STATE_STREAMING) {
    225 			value = FALSE;
    226 			g_dbus_emit_signal(dev->conn, dev->path,
    227 						AUDIO_SINK_INTERFACE,
    228 						"Stopped",
    229 						DBUS_TYPE_INVALID);
    230 			emit_property_changed(dev->conn, dev->path,
    231 						AUDIO_SINK_INTERFACE,
    232 						"Playing",
    233 						DBUS_TYPE_BOOLEAN, &value);
    234 		}
    235 		sink_set_state(dev, SINK_STATE_CONNECTED);
    236 		break;
    237 	case AVDTP_STATE_STREAMING:
    238 		value = TRUE;
    239 		g_dbus_emit_signal(dev->conn, dev->path, AUDIO_SINK_INTERFACE,
    240 					"Playing", DBUS_TYPE_INVALID);
    241 		emit_property_changed(dev->conn, dev->path,
    242 					AUDIO_SINK_INTERFACE, "Playing",
    243 					DBUS_TYPE_BOOLEAN, &value);
    244 		sink_set_state(dev, SINK_STATE_PLAYING);
    245 		break;
    246 	case AVDTP_STATE_CONFIGURED:
    247 	case AVDTP_STATE_CLOSING:
    248 	case AVDTP_STATE_ABORTING:
    249 	default:
    250 		break;
    251 	}
    252 
    253 	sink->stream_state = new_state;
    254 }
    255 
    256 static void error_failed(DBusConnection *conn, DBusMessage *msg,
    257 							const char *desc)
    258 {
    259 	DBusMessage *reply = btd_error_failed(msg, desc);
    260 	g_dbus_send_message(conn, reply);
    261 }
    262 
    263 static gboolean stream_setup_retry(gpointer user_data)
    264 {
    265 	struct sink *sink = user_data;
    266 	struct pending_request *pending = sink->connect;
    267 
    268 	sink->retry_id = 0;
    269 
    270 	if (sink->stream_state >= AVDTP_STATE_OPEN) {
    271 		DBG("Stream successfully created, after XCASE connect:connect");
    272 		if (pending->msg) {
    273 			DBusMessage *reply;
    274 			reply = dbus_message_new_method_return(pending->msg);
    275 			g_dbus_send_message(pending->conn, reply);
    276 		}
    277 	} else {
    278 		DBG("Stream setup failed, after XCASE connect:connect");
    279 		if (pending->msg)
    280 			error_failed(pending->conn, pending->msg, "Stream setup failed");
    281 	}
    282 
    283 	sink->connect = NULL;
    284 	pending_request_free(sink->dev, pending);
    285 
    286 	return FALSE;
    287 }
    288 
    289 static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
    290 					struct avdtp_stream *stream,
    291 					struct avdtp_error *err, void *user_data)
    292 {
    293 	struct sink *sink = user_data;
    294 	struct pending_request *pending;
    295 
    296 	pending = sink->connect;
    297 
    298 	pending->id = 0;
    299 
    300 	if (stream) {
    301 		DBG("Stream successfully created");
    302 
    303 		if (pending->msg) {
    304 			DBusMessage *reply;
    305 			reply = dbus_message_new_method_return(pending->msg);
    306 			g_dbus_send_message(pending->conn, reply);
    307 		}
    308 
    309 		sink->connect = NULL;
    310 		pending_request_free(sink->dev, pending);
    311 
    312 		return;
    313 	}
    314 
    315 	avdtp_unref(sink->session);
    316 	sink->session = NULL;
    317 	if (avdtp_error_category(err) == AVDTP_ERRNO
    318 			&& avdtp_error_posix_errno(err) != EHOSTDOWN) {
    319 		DBG("connect:connect XCASE detected");
    320 		sink->retry_id = g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
    321 							stream_setup_retry,
    322 							sink);
    323 	} else {
    324 		if (pending->msg)
    325 			error_failed(pending->conn, pending->msg, "Stream setup failed");
    326 		sink->connect = NULL;
    327 		pending_request_free(sink->dev, pending);
    328 		DBG("Stream setup failed : %s", avdtp_strerror(err));
    329 	}
    330 }
    331 
    332 static void select_complete(struct avdtp *session, struct a2dp_sep *sep,
    333 			GSList *caps, void *user_data)
    334 {
    335 	struct sink *sink = user_data;
    336 	struct pending_request *pending;
    337 	int id;
    338 
    339 	pending = sink->connect;
    340 	pending->id = 0;
    341 
    342 	id = a2dp_config(session, sep, stream_setup_complete, caps, sink);
    343 	if (id == 0)
    344 		goto failed;
    345 
    346 	pending->id = id;
    347 	return;
    348 
    349 failed:
    350 	if (pending->msg)
    351 		error_failed(pending->conn, pending->msg, "Stream setup failed");
    352 	pending_request_free(sink->dev, pending);
    353 	sink->connect = NULL;
    354 	avdtp_unref(sink->session);
    355 	sink->session = NULL;
    356 }
    357 
    358 static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err,
    359 				void *user_data)
    360 {
    361 	struct sink *sink = user_data;
    362 	struct pending_request *pending;
    363 	int id;
    364 
    365 	if (!sink->connect) {
    366 		avdtp_unref(sink->session);
    367 		sink->session = NULL;
    368 		return;
    369 	}
    370 
    371 	pending = sink->connect;
    372 
    373 	if (err) {
    374 		avdtp_unref(sink->session);
    375 		sink->session = NULL;
    376 		if (avdtp_error_category(err) == AVDTP_ERRNO
    377 				&& avdtp_error_posix_errno(err) != EHOSTDOWN) {
    378 			DBG("connect:connect XCASE detected");
    379 			sink->retry_id =
    380 				g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER,
    381 							stream_setup_retry,
    382 							sink);
    383 		} else
    384 			goto failed;
    385 		return;
    386 	}
    387 
    388 	DBG("Discovery complete");
    389 
    390 	id = a2dp_select_capabilities(sink->session, AVDTP_SEP_TYPE_SINK, NULL,
    391 						select_complete, sink);
    392 	if (id == 0)
    393 		goto failed;
    394 
    395 	pending->id = id;
    396 	return;
    397 
    398 failed:
    399 	if (pending->msg)
    400 		error_failed(pending->conn, pending->msg, "Stream setup failed");
    401 	pending_request_free(sink->dev, pending);
    402 	sink->connect = NULL;
    403 	avdtp_unref(sink->session);
    404 	sink->session = NULL;
    405 }
    406 
    407 gboolean sink_setup_stream(struct sink *sink, struct avdtp *session)
    408 {
    409 	if (sink->connect || sink->disconnect)
    410 		return FALSE;
    411 
    412 	if (session && !sink->session)
    413 		sink->session = avdtp_ref(session);
    414 
    415 	if (!sink->session)
    416 		return FALSE;
    417 
    418 	avdtp_set_auto_disconnect(sink->session, FALSE);
    419 
    420 	if (avdtp_discover(sink->session, discovery_complete, sink) < 0)
    421 		return FALSE;
    422 
    423 	sink->connect = g_new0(struct pending_request, 1);
    424 
    425 	return TRUE;
    426 }
    427 
    428 static DBusMessage *sink_connect(DBusConnection *conn,
    429 				DBusMessage *msg, void *data)
    430 {
    431 	struct audio_device *dev = data;
    432 	struct sink *sink = dev->sink;
    433 	struct pending_request *pending;
    434 
    435 	if (!sink->session)
    436 		sink->session = avdtp_get(&dev->src, &dev->dst);
    437 
    438 	if (!sink->session)
    439 		return btd_error_failed(msg, "Unable to get a session");
    440 
    441 	if (sink->connect || sink->disconnect)
    442 		return btd_error_busy(msg);
    443 
    444 	if (sink->stream_state >= AVDTP_STATE_OPEN)
    445 		return btd_error_already_connected(msg);
    446 
    447 	if (!sink_setup_stream(sink, NULL))
    448 		return btd_error_failed(msg, "Failed to create a stream");
    449 
    450 	dev->auto_connect = FALSE;
    451 
    452 	pending = sink->connect;
    453 
    454 	pending->conn = dbus_connection_ref(conn);
    455 	pending->msg = dbus_message_ref(msg);
    456 
    457 	DBG("stream creation in progress");
    458 
    459 	return NULL;
    460 }
    461 
    462 static DBusMessage *sink_disconnect(DBusConnection *conn,
    463 					DBusMessage *msg, void *data)
    464 {
    465 	struct audio_device *device = data;
    466 	struct sink *sink = device->sink;
    467 	struct pending_request *pending;
    468 	int err;
    469 
    470 	if (!sink->session)
    471 		return btd_error_not_connected(msg);
    472 
    473 	if (sink->connect || sink->disconnect)
    474 		return btd_error_busy(msg);
    475 
    476 	if (sink->stream_state < AVDTP_STATE_OPEN) {
    477 		DBusMessage *reply = dbus_message_new_method_return(msg);
    478 		if (!reply)
    479 			return NULL;
    480 		avdtp_unref(sink->session);
    481 		sink->session = NULL;
    482 		return reply;
    483 	}
    484 
    485 	err = avdtp_close(sink->session, sink->stream, FALSE);
    486 	if (err < 0)
    487 		return btd_error_failed(msg, strerror(-err));
    488 
    489 	pending = g_new0(struct pending_request, 1);
    490 	pending->conn = dbus_connection_ref(conn);
    491 	pending->msg = dbus_message_ref(msg);
    492 	sink->disconnect = pending;
    493 
    494 	return NULL;
    495 }
    496 
    497 static DBusMessage *sink_suspend(DBusConnection *conn,
    498 					DBusMessage *msg, void *data)
    499 {
    500 	struct audio_device *device = data;
    501 	struct sink *sink = device->sink;
    502 	struct pending_request *pending;
    503 	int err;
    504 
    505 	if (!sink->session)
    506 		return g_dbus_create_error(msg, ERROR_INTERFACE
    507 						".NotConnected",
    508 						"Device not Connected");
    509 
    510 	if (sink->connect || sink->disconnect)
    511 		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    512 						"%s", strerror(EBUSY));
    513 
    514 	if (sink->state < AVDTP_STATE_OPEN) {
    515 		DBusMessage *reply = dbus_message_new_method_return(msg);
    516 		if (!reply)
    517 			return NULL;
    518 		avdtp_unref(sink->session);
    519 		sink->session = NULL;
    520 		return reply;
    521 	}
    522 
    523 	err = avdtp_suspend(sink->session, sink->stream);
    524 	if (err < 0)
    525 		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    526 						"%s", strerror(-err));
    527 
    528 	return NULL;
    529 }
    530 
    531 static DBusMessage *sink_resume(DBusConnection *conn,
    532 					DBusMessage *msg, void *data)
    533 {
    534 	struct audio_device *device = data;
    535 	struct sink *sink = device->sink;
    536 	struct pending_request *pending;
    537 	int err;
    538 
    539 	if (!sink->session)
    540 		return g_dbus_create_error(msg, ERROR_INTERFACE
    541 						".NotConnected",
    542 						"Device not Connected");
    543 
    544 	if (sink->connect || sink->disconnect)
    545 		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    546 						"%s", strerror(EBUSY));
    547 
    548 	if (sink->state < AVDTP_STATE_OPEN) {
    549 		DBusMessage *reply = dbus_message_new_method_return(msg);
    550 		if (!reply)
    551 			return NULL;
    552 		avdtp_unref(sink->session);
    553 		sink->session = NULL;
    554 		return reply;
    555 	}
    556 
    557 	err = avdtp_start(sink->session, sink->stream);
    558 	if (err < 0)
    559 		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
    560 						"%s", strerror(-err));
    561 
    562 	return NULL;
    563 }
    564 
    565 static DBusMessage *sink_is_connected(DBusConnection *conn,
    566 					DBusMessage *msg,
    567 					void *data)
    568 {
    569 	struct audio_device *device = data;
    570 	struct sink *sink = device->sink;
    571 	DBusMessage *reply;
    572 	dbus_bool_t connected;
    573 
    574 	reply = dbus_message_new_method_return(msg);
    575 	if (!reply)
    576 		return NULL;
    577 
    578 	connected = (sink->stream_state >= AVDTP_STATE_CONFIGURED);
    579 
    580 	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected,
    581 					DBUS_TYPE_INVALID);
    582 
    583 	return reply;
    584 }
    585 
    586 static DBusMessage *sink_get_properties(DBusConnection *conn,
    587 					DBusMessage *msg, void *data)
    588 {
    589 	struct audio_device *device = data;
    590 	struct sink *sink = device->sink;
    591 	DBusMessage *reply;
    592 	DBusMessageIter iter;
    593 	DBusMessageIter dict;
    594 	const char *state;
    595 	gboolean value;
    596 
    597 	reply = dbus_message_new_method_return(msg);
    598 	if (!reply)
    599 		return NULL;
    600 
    601 	dbus_message_iter_init_append(reply, &iter);
    602 
    603 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    604 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    605 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    606 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    607 
    608 	/* Playing */
    609 	value = (sink->stream_state == AVDTP_STATE_STREAMING);
    610 	dict_append_entry(&dict, "Playing", DBUS_TYPE_BOOLEAN, &value);
    611 
    612 	/* Connected */
    613 	value = (sink->stream_state >= AVDTP_STATE_CONFIGURED);
    614 	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &value);
    615 
    616 	/* State */
    617 	state = state2str(sink->state);
    618 	if (state)
    619 		dict_append_entry(&dict, "State", DBUS_TYPE_STRING, &state);
    620 
    621 	dbus_message_iter_close_container(&iter, &dict);
    622 
    623 	return reply;
    624 }
    625 
    626 static GDBusMethodTable sink_methods[] = {
    627 	{ "Connect",		"",	"",	sink_connect,
    628 						G_DBUS_METHOD_FLAG_ASYNC },
    629 	{ "Disconnect",		"",	"",	sink_disconnect,
    630 						G_DBUS_METHOD_FLAG_ASYNC },
    631 	{ "Suspend",        "", "", sink_suspend,
    632                         G_DBUS_METHOD_FLAG_ASYNC },
    633 	{ "Resume",         "", "", sink_resume,
    634                         G_DBUS_METHOD_FLAG_ASYNC },
    635 	{ "IsConnected",	"",	"b",	sink_is_connected,
    636 						G_DBUS_METHOD_FLAG_DEPRECATED },
    637 	{ "GetProperties",	"",	"a{sv}",sink_get_properties },
    638 	{ NULL, NULL, NULL, NULL }
    639 };
    640 
    641 static GDBusSignalTable sink_signals[] = {
    642 	{ "Connected",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },
    643 	{ "Disconnected",		"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },
    644 	{ "Playing",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },
    645 	{ "Stopped",			"",	G_DBUS_SIGNAL_FLAG_DEPRECATED },
    646 	{ "PropertyChanged",		"sv"	},
    647 	{ NULL, NULL }
    648 };
    649 
    650 static void sink_free(struct audio_device *dev)
    651 {
    652 	struct sink *sink = dev->sink;
    653 
    654 	if (sink->cb_id)
    655 		avdtp_stream_remove_cb(sink->session, sink->stream,
    656 					sink->cb_id);
    657 
    658 	if (sink->session)
    659 		avdtp_unref(sink->session);
    660 
    661 	if (sink->connect)
    662 		pending_request_free(dev, sink->connect);
    663 
    664 	if (sink->disconnect)
    665 		pending_request_free(dev, sink->disconnect);
    666 
    667 	if (sink->retry_id)
    668 		g_source_remove(sink->retry_id);
    669 
    670 	g_free(sink);
    671 	dev->sink = NULL;
    672 }
    673 
    674 static void path_unregister(void *data)
    675 {
    676 	struct audio_device *dev = data;
    677 
    678 	DBG("Unregistered interface %s on path %s",
    679 		AUDIO_SINK_INTERFACE, dev->path);
    680 
    681 	sink_free(dev);
    682 }
    683 
    684 void sink_unregister(struct audio_device *dev)
    685 {
    686 	g_dbus_unregister_interface(dev->conn, dev->path,
    687 		AUDIO_SINK_INTERFACE);
    688 }
    689 
    690 struct sink *sink_init(struct audio_device *dev)
    691 {
    692 	struct sink *sink;
    693 
    694 	if (!g_dbus_register_interface(dev->conn, dev->path,
    695 					AUDIO_SINK_INTERFACE,
    696 					sink_methods, sink_signals, NULL,
    697 					dev, path_unregister))
    698 		return NULL;
    699 
    700 	DBG("Registered interface %s on path %s",
    701 		AUDIO_SINK_INTERFACE, dev->path);
    702 
    703 	if (avdtp_callback_id == 0)
    704 		avdtp_callback_id = avdtp_add_state_cb(avdtp_state_callback,
    705 									NULL);
    706 
    707 	sink = g_new0(struct sink, 1);
    708 
    709 	sink->dev = dev;
    710 
    711 	return sink;
    712 }
    713 
    714 gboolean sink_is_active(struct audio_device *dev)
    715 {
    716 	struct sink *sink = dev->sink;
    717 
    718 	if (sink->session)
    719 		return TRUE;
    720 
    721 	return FALSE;
    722 }
    723 
    724 avdtp_state_t sink_get_state(struct audio_device *dev)
    725 {
    726 	struct sink *sink = dev->sink;
    727 
    728 	return sink->stream_state;
    729 }
    730 
    731 gboolean sink_new_stream(struct audio_device *dev, struct avdtp *session,
    732 				struct avdtp_stream *stream)
    733 {
    734 	struct sink *sink = dev->sink;
    735 
    736 	if (sink->stream)
    737 		return FALSE;
    738 
    739 	if (!sink->session)
    740 		sink->session = avdtp_ref(session);
    741 
    742 	sink->stream = stream;
    743 
    744 	sink->cb_id = avdtp_stream_add_cb(session, stream,
    745 						stream_state_changed, dev);
    746 
    747 	return TRUE;
    748 }
    749 
    750 gboolean sink_shutdown(struct sink *sink)
    751 {
    752 	if (!sink->session)
    753 		return FALSE;
    754 
    755 	avdtp_set_device_disconnect(sink->session, TRUE);
    756 
    757 	/* cancel pending connect */
    758 	if (sink->connect) {
    759 		struct pending_request *pending = sink->connect;
    760 
    761 		if (pending->msg)
    762 			error_failed(pending->conn, pending->msg,
    763 							"Stream setup failed");
    764 		pending_request_free(sink->dev, pending);
    765 		sink->connect = NULL;
    766 
    767 		avdtp_unref(sink->session);
    768 		sink->session = NULL;
    769 
    770 		return TRUE;
    771 	}
    772 
    773 	/* disconnect already ongoing */
    774 	if (sink->disconnect)
    775 		return TRUE;
    776 
    777 	if (!sink->stream)
    778 		return FALSE;
    779 
    780 	if (avdtp_close(sink->session, sink->stream, FALSE) < 0)
    781 		return FALSE;
    782 
    783 	return TRUE;
    784 }
    785 
    786 unsigned int sink_add_state_cb(sink_state_cb cb, void *user_data)
    787 {
    788 	struct sink_state_callback *state_cb;
    789 	static unsigned int id = 0;
    790 
    791 	state_cb = g_new(struct sink_state_callback, 1);
    792 	state_cb->cb = cb;
    793 	state_cb->user_data = user_data;
    794 	state_cb->id = ++id;
    795 
    796 	sink_callbacks = g_slist_append(sink_callbacks, state_cb);
    797 
    798 	return state_cb->id;
    799 }
    800 
    801 gboolean sink_remove_state_cb(unsigned int id)
    802 {
    803 	GSList *l;
    804 
    805 	for (l = sink_callbacks; l != NULL; l = l->next) {
    806 		struct sink_state_callback *cb = l->data;
    807 		if (cb && cb->id == id) {
    808 			sink_callbacks = g_slist_remove(sink_callbacks, cb);
    809 			g_free(cb);
    810 			return TRUE;
    811 		}
    812 	}
    813 
    814 	return FALSE;
    815 }
    816