diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-04-10 11:44:10 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-04-10 11:44:10 +0000 | 
| commit | 35f12dee95378056a2ed7c0d325b2c3b68022da8 (patch) | |
| tree | 240c99b1f3d926fd19b00ff91513d264bf678e9f /audio/headset.c | |
| parent | 5daebe3831a85cc39a74c25798fb5123f2bdc633 (diff) | |
Audio service refactoring: move all manager functions to manager.c
Diffstat (limited to 'audio/headset.c')
| -rw-r--r-- | audio/headset.c | 459 | 
1 files changed, 64 insertions, 395 deletions
| diff --git a/audio/headset.c b/audio/headset.c index 44a6ce03..85c233d5 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -51,14 +51,11 @@  #include "dbus.h"  #include "logging.h" - -#define BUF_SIZE 1024 +#include "manager.h" +#include "headset.h"  #define RING_INTERVAL 3000 -#define AUDIO_MANAGER_PATH "/org/bluez/audio" -#define AUDIO_HEADSET_PATH_BASE "/org/bluez/audio/headset" -  typedef enum {  	HEADSET_EVENT_KEYPRESS,  	HEADSET_EVENT_GAIN, @@ -77,7 +74,6 @@ typedef enum {  struct pending_connect {  	int ch; -	DBusConnection *conn;  	DBusMessage *msg;  	GIOChannel *io;  }; @@ -102,31 +98,10 @@ struct headset {  	headset_state_t state;  	struct pending_connect *pending_connect; -}; -struct manager { -	GIOChannel *server_sk; -	uint32_t record_id; -	int default_hs; -	GSList *headset_list; +	DBusConnection *conn;  }; -static DBusConnection *connection = NULL; - -struct manager *audio_manager_new(DBusConnection *conn); -void audio_manager_free(struct manager *manager); -struct headset *audio_manager_find_headset_by_bda(struct manager *manager, const bdaddr_t *bda); -void audio_manager_add_headset(struct manager *manager, struct headset *hs); -gboolean audio_manager_create_headset_server(struct manager *manager, uint8_t chan); - -struct headset *audio_headset_new(DBusConnection *conn, const bdaddr_t *bda); -void audio_headset_unref(struct headset *hs); -gboolean audio_headset_close_input(struct headset *hs); -gboolean audio_headset_open_input(struct headset *hs, const char *audio_input); -gboolean audio_headset_close_output(struct headset *hs); -gboolean audio_headset_open_output(struct headset *hs, const char *audio_output); -GIOError audio_headset_send_ring(struct headset *hs); -  static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg);  static void pending_connect_free(struct pending_connect *c) @@ -135,8 +110,6 @@ static void pending_connect_free(struct pending_connect *c)  		g_io_channel_unref(c->io);  	if (c->msg)  		dbus_message_unref(c->msg); -	if (c->conn) -		dbus_connection_unref(c->conn);  	g_free(c);  } @@ -157,13 +130,6 @@ static DBusHandlerResult error_reply(DBusConnection *conn, DBusMessage *msg,  	return send_message_and_unref(conn, derr);  } -static DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg, -						const char *descr) -{ -	return error_reply(conn, msg, "org.bluez.Error.InvalidArguments", -			descr ? descr : "Invalid arguments in method call"); -} -  static DBusHandlerResult err_already_connected(DBusConnection *conn, DBusMessage *msg)  {  	return error_reply(conn, msg, "org.bluez.Error.AlreadyConnected", @@ -226,7 +192,7 @@ static void hs_signal_gain_setting(struct headset *hs, const char *buf)  	dbus_message_append_args(signal, DBUS_TYPE_UINT16, &gain,  					DBUS_TYPE_INVALID); -	send_message_and_unref(connection, signal); +	send_message_and_unref(hs->conn, signal);  }  static void hs_signal(struct headset *hs, const char *name) @@ -239,7 +205,7 @@ static void hs_signal(struct headset *hs, const char *name)  		return;  	} -	send_message_and_unref(connection, signal); +	send_message_and_unref(hs->conn, signal);  }  static headset_event_t parse_headset_event(const char *buf, char *rsp, int rsp_len) @@ -398,7 +364,7 @@ static void send_cancel_auth(struct headset *hs)  	dbus_message_append_args(cancel, DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); -	send_message_and_unref(connection, cancel); +	send_message_and_unref(hs->conn, cancel);  }  static void auth_callback(DBusPendingCall *call, void *data) @@ -435,7 +401,7 @@ static void auth_callback(DBusPendingCall *call, void *data)  	dbus_message_unref(reply);  } -static gboolean server_io_cb(GIOChannel *chan, GIOCondition cond, +gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond,  				struct manager *manager)  {  	int srv_sk, cli_sk; @@ -468,16 +434,17 @@ static gboolean server_io_cb(GIOChannel *chan, GIOCondition cond,  		return TRUE;  	} -	hs = audio_manager_find_headset_by_bda(manager, &addr.rc_bdaddr); +	hs = manager_find_headset_by_bda(manager, &addr.rc_bdaddr);  	if (!hs) { -		hs = audio_headset_new(connection, &addr.rc_bdaddr); +		hs = audio_headset_new(manager_get_dbus_conn(manager), +					&addr.rc_bdaddr);  		if (!hs) {  			error("Unable to create a new headset object");  			close(cli_sk);  			return TRUE;  		} -		audio_manager_add_headset(manager, hs); +		manager_add_headset(manager, hs);  	}  	if (hs->state > HEADSET_STATE_DISCONNECTED || hs->rfcomm) { @@ -505,7 +472,7 @@ static gboolean server_io_cb(GIOChannel *chan, GIOCondition cond,  	dbus_message_append_args(auth, DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); -	if (dbus_connection_send_with_reply(connection, auth, &pending, -1) == FALSE) { +	if (dbus_connection_send_with_reply(hs->conn, auth, &pending, -1) == FALSE) {  		error("Sending of authorization request failed");  		goto failed;  	} @@ -655,7 +622,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,  		reply = dbus_message_new_method_return(hs->pending_connect->msg);  		if (reply) -			send_message_and_unref(connection, reply); +			send_message_and_unref(hs->conn, reply);  	}  	/* FIXME: do we allow both? pull & push model at the same time on sco && audio_input? */ @@ -672,7 +639,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,  failed:  	if (hs->pending_connect) { -		err_connect_failed(hs->pending_connect->conn, hs->pending_connect->msg, err); +		err_connect_failed(hs->conn, hs->pending_connect->msg, err);  		if (hs->pending_connect->io)  			g_io_channel_close(hs->pending_connect->io);  		pending_connect_free(hs->pending_connect); @@ -731,7 +698,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct he  			reply = dbus_message_new_method_return(hs->pending_connect->msg);  			if (reply) -				send_message_and_unref(hs->pending_connect->conn, reply); +				send_message_and_unref(hs->conn, reply);  		}  		pending_connect_free(hs->pending_connect); @@ -742,7 +709,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct he  failed:  	if (hs->pending_connect) { -		err_connect_failed(hs->pending_connect->conn, hs->pending_connect->msg, err); +		err_connect_failed(hs->conn, hs->pending_connect->msg, err);  		if (hs->pending_connect->io)  			g_io_channel_close(hs->pending_connect->io);  		pending_connect_free(hs->pending_connect); @@ -828,47 +795,11 @@ failed:  	return -1;  } -static int server_socket(uint8_t *channel) +gint headset_bda_cmp(gconstpointer headset, gconstpointer bda)  { -	int sock, lm; -	struct sockaddr_rc addr; -	socklen_t sa_len; - -	sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); -	if (sock < 0) { -		error("server socket: %s (%d)", strerror(errno), errno); -		return -1; -	} - -	lm = RFCOMM_LM_SECURE; -	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { -		error("server setsockopt: %s (%d)", strerror(errno), errno); -		close(sock); -		return -1; -	} - -	memset(&addr, 0, sizeof(addr)); -	addr.rc_family = AF_BLUETOOTH; -	bacpy(&addr.rc_bdaddr, BDADDR_ANY); -	addr.rc_channel = 0; - -	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { -		error("server bind: %s", strerror(errno), errno); -		close(sock); -		return -1; -	} - -	if (listen(sock, 1) < 0) { -		error("server listen: %s", strerror(errno), errno); -		close(sock); -		return -1; -	} - -	sa_len = sizeof(struct sockaddr_rc); -	getsockname(sock, (struct sockaddr *) &addr, &sa_len); -	*channel = addr.rc_channel; +	const struct headset *hs = headset; -	return sock; +	return bacmp(&hs->bda, bda);  }  static int create_ag_record(sdp_buf_t *buf, uint8_t ch) @@ -932,7 +863,7 @@ static int create_ag_record(sdp_buf_t *buf, uint8_t ch)  	return ret;  } -static uint32_t add_ag_record(uint8_t channel) +uint32_t headset_add_ag_record(DBusConnection *conn, uint8_t channel)  {  	DBusMessage *msg, *reply;  	DBusError derr; @@ -956,7 +887,7 @@ static uint32_t add_ag_record(uint8_t channel)  				&buf.data, buf.data_size, DBUS_TYPE_INVALID);  	dbus_error_init(&derr); -	reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &derr); +	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr);  	free(buf.data);  	dbus_message_unref(msg); @@ -984,7 +915,7 @@ static uint32_t add_ag_record(uint8_t channel)  	return rec_id;  } -static int remove_ag_record(uint32_t rec_id) +int headset_remove_ag_record(DBusConnection *conn, uint32_t rec_id)  {  	DBusMessage *msg, *reply;  	DBusError derr; @@ -1000,7 +931,7 @@ static int remove_ag_record(uint32_t rec_id)  						DBUS_TYPE_INVALID);  	dbus_error_init(&derr); -	reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &derr); +	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr);  	dbus_message_unref(msg); @@ -1035,7 +966,7 @@ static void get_record_reply(DBusPendingCall *call, void *data)  	if (dbus_set_error_from_message(&derr, reply)) {  		error("GetRemoteServiceRecord failed: %s", derr.message);  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		dbus_error_free(&derr);  		goto failed;  	} @@ -1045,14 +976,14 @@ static void get_record_reply(DBusPendingCall *call, void *data)  				DBUS_TYPE_INVALID)) {  		error("Unable to get args from GetRecordReply");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	}  	if (!array) {  		error("Unable to get handle array from reply");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	} @@ -1060,7 +991,7 @@ static void get_record_reply(DBusPendingCall *call, void *data)  	if (!record) {  		error("Unable to extract service record from reply");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	} @@ -1078,14 +1009,14 @@ static void get_record_reply(DBusPendingCall *call, void *data)  	if (c->ch == -1) {  		error("Unable to extract RFCOMM channel from service record");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	}  	if (rfcomm_connect(hs, &err) < 0) {  		error("Unable to connect");  		if (c->msg)  -			err_connect_failed(c->conn, c->msg, err); +			err_connect_failed(hs->conn, c->msg, err);  		goto failed;  	} @@ -1109,7 +1040,7 @@ static DBusHandlerResult hs_stop(struct headset *hs, DBusMessage *msg)  	DBusMessage *reply = NULL;  	if (!hs || !hs->sco) -		return err_not_connected(connection, msg); +		return err_not_connected(hs->conn, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1120,8 +1051,7 @@ static DBusHandlerResult hs_stop(struct headset *hs, DBusMessage *msg)  	if (hs->state == HEADSET_STATE_PLAY_IN_PROGRESS && hs->pending_connect) {  		g_io_channel_close(hs->pending_connect->io);  		if (hs->pending_connect->msg) -			err_connect_failed(hs->pending_connect->conn, -						hs->pending_connect->msg, +			err_connect_failed(hs->conn, hs->pending_connect->msg,  						EINTR);  		pending_connect_free(hs->pending_connect);  		hs->pending_connect = NULL; @@ -1131,7 +1061,7 @@ static DBusHandlerResult hs_stop(struct headset *hs, DBusMessage *msg)  	close_sco(hs);  	if (reply) -		send_message_and_unref(connection, reply); +		send_message_and_unref(hs->conn, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1162,8 +1092,7 @@ static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg)  		if (hs->pending_connect->io)  			g_io_channel_close(hs->pending_connect->io);  		if (hs->pending_connect->msg) -			err_connect_failed(hs->pending_connect->conn, -						hs->pending_connect->msg, +			err_connect_failed(hs->conn, hs->pending_connect->msg,  						EINTR);  		pending_connect_free(hs->pending_connect);  		hs->pending_connect = NULL; @@ -1180,7 +1109,7 @@ static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg)  	hs->data_length = 0;  	if (reply) -		send_message_and_unref(connection, reply); +		send_message_and_unref(hs->conn, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1204,7 +1133,7 @@ static DBusHandlerResult hs_is_connected(struct headset *hs, DBusMessage *msg)  	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected,  					DBUS_TYPE_INVALID); -	send_message_and_unref(connection, reply); +	send_message_and_unref(hs->conn, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1231,9 +1160,9 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  		error("GetRemoteServiceHandles failed: %s", derr.message);  		if (c->msg) {  			if (dbus_error_has_name(&derr, "org.bluez.Error.ConnectionAttemptFailed")) -				err_connect_failed(c->conn, c->msg, EHOSTDOWN); +				err_connect_failed(hs->conn, c->msg, EHOSTDOWN);  			else -				err_not_supported(c->conn, c->msg); +				err_not_supported(hs->conn, c->msg);  		}  		dbus_error_free(&derr);  		goto failed; @@ -1245,21 +1174,21 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  		error("Unable to get args from reply");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	}  	if (!array) {  		error("Unable to get handle array from reply");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	}  	if (array_len < 1) {  		debug("No record handles found");  		if (c->msg)  -			err_not_supported(c->conn, c->msg); +			err_not_supported(hs->conn, c->msg);  		goto failed;  	} @@ -1272,7 +1201,7 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  	if (!msg) {  		error("Unable to allocate new method call");  		if (c->msg)  -			err_connect_failed(c->conn, c->msg, ENOMEM); +			err_connect_failed(hs->conn, c->msg, ENOMEM);  		goto failed;  	} @@ -1284,10 +1213,10 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  					DBUS_TYPE_UINT32, &handle,  					DBUS_TYPE_INVALID); -	if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) { +	if (!dbus_connection_send_with_reply(hs->conn, msg, &pending, -1)) {  		error("Sending GetRemoteServiceRecord failed");  		if (c->msg)  -			err_connect_failed(c->conn, c->msg, EIO); +			err_connect_failed(hs->conn, c->msg, EIO);  		goto failed;  	} @@ -1327,7 +1256,6 @@ static DBusHandlerResult hs_connect(struct headset *hs, DBusMessage *msg)  	hs->state = HEADSET_STATE_CONNECT_IN_PROGRESS; -	hs->pending_connect->conn = dbus_connection_ref(connection);  	hs->pending_connect->msg = msg ? dbus_message_ref(msg) : NULL;  	msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0", @@ -1347,13 +1275,13 @@ static DBusHandlerResult hs_connect(struct headset *hs, DBusMessage *msg)  					DBUS_TYPE_STRING, &hs_svc,  					DBUS_TYPE_INVALID); -	if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) { +	if (!dbus_connection_send_with_reply(hs->conn, msg, &pending, -1)) {  		error("Sending GetRemoteServiceHandles failed");  		pending_connect_free(hs->pending_connect);  		hs->pending_connect = NULL;  		hs->state = HEADSET_STATE_DISCONNECTED;  		dbus_message_unref(msg); -		return err_connect_failed(connection, msg, EIO); +		return err_connect_failed(hs->conn, msg, EIO);  	}  	dbus_pending_call_set_notify(pending, get_handles_reply, hs, NULL); @@ -1363,7 +1291,7 @@ static DBusHandlerResult hs_connect(struct headset *hs, DBusMessage *msg)  	return DBUS_HANDLER_RESULT_HANDLED;;  } -GIOError audio_headset_send_ring(struct headset *hs) +static GIOError audio_headset_send_ring(struct headset *hs)  {  	const char *ring_str = "\r\nRING\r\n";  	GIOError err; @@ -1408,7 +1336,7 @@ static DBusHandlerResult hs_ring(struct headset *hs, DBusMessage *msg)  	assert(hs != NULL);  	if (hs->state < HEADSET_STATE_CONNECTED) -		return err_not_connected(connection, msg); +		return err_not_connected(hs->conn, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1423,14 +1351,14 @@ static DBusHandlerResult hs_ring(struct headset *hs, DBusMessage *msg)  	if (audio_headset_send_ring(hs) != G_IO_ERROR_NONE) {  		dbus_message_unref(reply); -		return err_failed(connection, msg); +		return err_failed(hs->conn, msg);  	}  	hs->ring_timer = g_timeout_add(RING_INTERVAL, ring_timer_cb, hs);  done:  	if (reply) -		send_message_and_unref(connection, reply); +		send_message_and_unref(hs->conn, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1439,8 +1367,8 @@ static DBusHandlerResult hs_cancel_ringing(struct headset *hs, DBusMessage *msg)  {  	DBusMessage *reply = NULL; -	if (!hs) -		return err_not_connected(connection, msg); +	if (hs->state < HEADSET_STATE_CONNECTED) +		return err_not_connected(hs->conn, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1458,7 +1386,7 @@ static DBusHandlerResult hs_cancel_ringing(struct headset *hs, DBusMessage *msg)  done:  	if (reply) -		send_message_and_unref(connection, reply); +		send_message_and_unref(hs->conn, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1469,17 +1397,14 @@ static DBusHandlerResult hs_play(struct headset *hs, DBusMessage *msg)  	struct pending_connect *c;  	int sk, err; -	if (!hs) -		return err_not_connected(connection, msg); -  	if (hs->state < HEADSET_STATE_CONNECTED) -		return err_not_connected(connection, msg); /* FIXME: in progress error? */ +		return err_not_connected(hs->conn, msg); /* FIXME: in progress error? */  	if (hs->state >= HEADSET_STATE_PLAY_IN_PROGRESS || hs->pending_connect) -		return err_already_connected(connection, msg); +		return err_already_connected(hs->conn, msg);  	if (hs->sco) -		return err_already_connected(connection, msg); +		return err_already_connected(hs->conn, msg);  	c = g_try_new0(struct pending_connect, 1);  	if (!c) @@ -1487,14 +1412,13 @@ static DBusHandlerResult hs_play(struct headset *hs, DBusMessage *msg)  	hs->state = HEADSET_STATE_PLAY_IN_PROGRESS; -	c->conn = dbus_connection_ref(connection);  	c->msg = msg ? dbus_message_ref(msg) : NULL;  	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);  	if (sk < 0) {  		err = errno;  		error("socket(BTPROTO_SCO): %s (%d)", strerror(err), err); -		err_connect_failed(connection, msg, err); +		err_connect_failed(hs->conn, msg, err);  		goto failed;  	} @@ -1512,13 +1436,13 @@ static DBusHandlerResult hs_play(struct headset *hs, DBusMessage *msg)  	if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {  		err = errno;  		error("socket(BTPROTO_SCO): %s (%d)", strerror(err), err); -		err_connect_failed(connection, msg, err); +		err_connect_failed(hs->conn, msg, err);  		goto failed;  	}  	if (set_nonblocking(sk) < 0) {  		err = errno; -		err_connect_failed(connection, msg, err); +		err_connect_failed(hs->conn, msg, err);  		goto failed;  	} @@ -1626,6 +1550,8 @@ struct headset *audio_headset_new(DBusConnection *conn, const bdaddr_t *bda)  	bacpy(&hs->bda, bda); +	hs->conn = dbus_connection_ref(conn); +  	return hs;  } @@ -1633,6 +1559,8 @@ void audio_headset_unref(struct headset *hs)  {  	assert(hs != NULL); +	dbus_connection_unref(hs->conn); +  	g_free(hs);  } @@ -1727,266 +1655,7 @@ gboolean audio_headset_open_input(struct headset *hs, const char *input)  	return TRUE;  } -gboolean audio_manager_create_headset_server(struct manager *manager, uint8_t chan) -{ -	int srv_sk; - -	assert(manager != NULL); - -	if (manager->server_sk) { -		error("Server socket already created"); -		return FALSE; -	} - -	srv_sk = server_socket(&chan); -	if (srv_sk < 0) { -		error("Unable to create server socket"); -		return FALSE; -	} - -	if (!manager->record_id) -		manager->record_id = add_ag_record(chan); - -	if (!manager->record_id) { -		error("Unable to register service record"); -		close(srv_sk); -		return FALSE; -	} - -	manager->server_sk = g_io_channel_unix_new(srv_sk); -	if (!manager->server_sk) { -		error("Unable to allocate new GIOChannel"); -		remove_ag_record(manager->record_id); -		manager->record_id = 0; -		close(srv_sk); -		return FALSE; -	} - -	g_io_add_watch(manager->server_sk, -			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, -			(GIOFunc) server_io_cb, manager); - -	return TRUE; -} - -static gint headset_bda_cmp(gconstpointer headset, gconstpointer bda) -{ -	const struct headset *hs = headset; - -	return bacmp(&hs->bda, bda); -} - -struct headset *audio_manager_find_headset_by_bda(struct manager *manager, const bdaddr_t *bda) -{ -	GSList *elem; - -	assert(manager); -	elem = g_slist_find_custom(manager->headset_list, bda, headset_bda_cmp); - -	return elem ? elem->data : NULL; -} - -void audio_manager_add_headset(struct manager *manager, struct headset *hs) -{ -	assert(manager && hs); - -	if (g_slist_find(manager->headset_list, hs)) -		return; - -	manager->headset_list = g_slist_append(manager->headset_list, hs); -} - -static DBusHandlerResult am_create_headset(struct manager *manager,  -						DBusMessage *msg) +const char *audio_headset_get_path(struct headset *hs)  { -	const char *object_path; -	const char *address; -	struct headset *hs; -	bdaddr_t bda; -	DBusMessage *reply; -	DBusError derr; - -	if (!manager) -		return err_not_connected(connection, msg); -	 -	dbus_error_init(&derr); -	if (!dbus_message_get_args(msg, &derr, -					DBUS_TYPE_STRING, &address, -					DBUS_TYPE_INVALID)) { -		err_invalid_args(connection, msg, derr.message); -		return DBUS_HANDLER_RESULT_HANDLED; -	} -	if (dbus_error_is_set(&derr)) { -		err_invalid_args(connection, msg, derr.message); -		dbus_error_free(&derr); -		return DBUS_HANDLER_RESULT_HANDLED; -	} - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return DBUS_HANDLER_RESULT_NEED_MEMORY; - -	str2ba(address, &bda); -	hs = audio_manager_find_headset_by_bda(manager, &bda); -	if (!hs) { -		hs = audio_headset_new(connection, &bda); -		if (!hs) -			return error_reply(connection, msg, -					"org.bluez.Error.Failed", -					"Unable to create new headset object"); -		audio_manager_add_headset(manager, hs); -	} - -	object_path = hs->object_path; -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &object_path, -					DBUS_TYPE_INVALID); - -	return send_message_and_unref(connection, reply); -} - -static DBusHandlerResult am_remove_headset(struct manager *manager,  -						DBusMessage *msg) -{ -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult am_list_headsets(struct manager *manager,  -						DBusMessage *msg) -{ -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult am_get_default_headset(struct manager *manager,  -						DBusMessage *msg) -{ -	DBusMessage *reply; -	char object_path[128]; -	const char *opath = object_path; - -	if (!manager) -		return err_not_connected(connection, msg); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return DBUS_HANDLER_RESULT_NEED_MEMORY; - -	snprintf(object_path, sizeof(object_path), AUDIO_HEADSET_PATH_BASE "%d", -			manager->default_hs); -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &opath, -					DBUS_TYPE_INVALID); - -	return send_message_and_unref(connection, reply); -} - -static DBusHandlerResult am_change_default_headset(struct manager *manager,  -							DBusMessage *msg) -{ -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult am_message(DBusConnection *conn, -					DBusMessage *msg, void *data) -{ -	const char *interface, *member; -	struct manager *manager = data; - -	interface = dbus_message_get_interface(msg); -	member = dbus_message_get_member(msg); - -	if (!strcmp(DBUS_INTERFACE_INTROSPECTABLE, interface) && -			!strcmp("Introspect", member)) -		return simple_introspect(conn, msg, data); - -	if (strcmp(interface, "org.bluez.audio.Manager") != 0) -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	if (strcmp(member, "CreateHeadset") == 0) -		return am_create_headset(manager, msg); - -	if (strcmp(member, "RemoveHeadset") == 0) -		return am_remove_headset(manager, msg); - -	if (strcmp(member, "ListHeadsets") == 0) -		return am_list_headsets(manager, msg); - -	if (strcmp(member, "DefaultHeadset") == 0) -		return am_get_default_headset(manager, msg); - -	if (strcmp(member, "ChangeDefaultHeadset") == 0) -		return am_change_default_headset(manager, msg); - -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static const DBusObjectPathVTable am_table = { -	.message_function = am_message, -}; - -struct manager *audio_manager_new(DBusConnection *conn) -{ -	struct manager *manager; - -	manager = g_new0(struct manager, 1); - -	if (!dbus_connection_register_object_path(conn, AUDIO_MANAGER_PATH, -						&am_table, manager)) { -		error("D-Bus failed to register %s path", AUDIO_MANAGER_PATH); -		g_free(manager); -		return NULL; -	} - -	return manager; -} - -void audio_manager_free(struct manager *manager) -{ -	assert(manager != NULL); - -	if (manager->record_id) { -		remove_ag_record(manager->record_id); -		manager->record_id = 0; -	} - -	if (manager->server_sk) { -		g_io_channel_unref(manager->server_sk); -		manager->server_sk = NULL; -	} - -	if (manager->headset_list) { -		g_slist_foreach(manager->headset_list, (GFunc) audio_headset_unref, -				manager); -		g_slist_free(manager->headset_list); -		manager->headset_list = NULL; -	} - -	g_free(manager); -} - -static struct manager *manager = NULL; - -int headset_init(DBusConnection *conn) -{ -	connection = dbus_connection_ref(conn); - -	manager = audio_manager_new(connection); -	if (!manager) { -		error("Failed to create an audio manager"); -		dbus_connection_unref(connection); -		return -1; -	} - -	audio_manager_create_headset_server(manager, 12); - -	return 0; -} - -void headset_exit(void) -{ -	audio_manager_free(manager); - -	manager = NULL; - -	dbus_connection_unref(connection); - -	connection = NULL; +	return hs->object_path;  } | 
