diff options
| -rw-r--r-- | audio/headset.c | 350 | ||||
| -rw-r--r-- | audio/headset.h | 24 | ||||
| -rw-r--r-- | audio/main.c | 4 | ||||
| -rw-r--r-- | audio/manager.c | 90 | ||||
| -rw-r--r-- | audio/manager.h | 2 | 
5 files changed, 225 insertions, 245 deletions
| diff --git a/audio/headset.c b/audio/headset.c index 0592d9fa..c08489ff 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -98,12 +98,14 @@ struct headset {  	headset_state_t state;  	struct pending_connect *pending_connect; - -	DBusConnection *conn;  };  static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg); +static GSList *headsets = NULL; + +static DBusConnection *connection = NULL; +  static void pending_connect_free(struct pending_connect *c)  {  	if (c->io) @@ -158,6 +160,99 @@ static DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg)  	return error_reply(conn, msg, "org.bluez.Error.Failed", "Failed");  } +static gboolean headset_close_output(struct headset *hs) +{ +	assert(hs != NULL); + +	if (hs->audio_output == NULL)  +		return FALSE; + +	g_io_channel_close(hs->audio_output); +	g_io_channel_unref(hs->audio_output); +	hs->audio_output = NULL; + +	return TRUE; +} + +/* FIXME: in the furture, that would be great to provide user space alsa driver (not plugin) */ +static gboolean headset_open_output(struct headset *hs, const char *output) +{ +	int out; + +	assert(hs != NULL && output != NULL); + +	headset_close_output(hs); +	if (output && hs->output) { +		g_free(hs->output); +		hs->output = g_strdup(output); +	} + +	assert(hs->output); + +	out = open(hs->output, O_WRONLY | O_SYNC | O_CREAT); + +	if (out < 0) { +		error("open(%s): %s %d", hs->output, strerror(errno), errno); +		return FALSE; +	} + +	hs->audio_output = g_io_channel_unix_new(out); +	if (!hs->audio_output) { +		error("Allocating new channel for audio output!"); +		return FALSE; +	} + +	g_io_channel_set_close_on_unref(hs->audio_output, TRUE); + +	return TRUE; +} + +static gboolean headset_close_input(struct headset *hs) +{ +	assert(hs != NULL); + +	if (hs->audio_input == NULL)  +		return FALSE; + +	g_io_channel_close(hs->audio_input); +	g_io_channel_unref(hs->audio_input); +	hs->audio_input = NULL; + +	return TRUE; +} + +#if 0 +static gboolean headset_open_input(struct headset *hs, const char *input) +{ +	int in; + +	assert(hs != NULL); +	 +	/* we keep the input name, and NULL can be use to reopen */ +	if (input && hs->input) { +		g_free(hs->input); +		hs->input = g_strdup(input); +	} + +	assert(hs->input); + +	in = open(hs->input, O_RDONLY | O_NOCTTY); + +	if (in < 0) { +		error("open(%s): %s %d", hs->input, strerror(errno), errno); +		return FALSE; +	} + +	hs->audio_input = g_io_channel_unix_new(in); +	if (!hs->audio_input) { +		error("Allocating new channel for audio input!"); +		return FALSE; +	} + +	return TRUE; +} +#endif +  static void hs_signal_gain_setting(struct headset *hs, const char *buf)  {  	const char *name; @@ -192,7 +287,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(hs->conn, signal); +	send_message_and_unref(connection, signal);  }  static void hs_signal(struct headset *hs, const char *name) @@ -205,7 +300,7 @@ static void hs_signal(struct headset *hs, const char *name)  		return;  	} -	send_message_and_unref(hs->conn, signal); +	send_message_and_unref(connection, signal);  }  static headset_event_t parse_headset_event(const char *buf, char *rsp, int rsp_len) @@ -364,7 +459,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(hs->conn, cancel); +	send_message_and_unref(connection, cancel);  }  static void auth_callback(DBusPendingCall *call, void *data) @@ -406,7 +501,7 @@ gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data)  	int srv_sk, cli_sk;  	struct sockaddr_rc addr;  	socklen_t size; -	char hs_address[18], *address = hs_address; +	char hs_address[18], *address = hs_address, *path;  	const char *uuid = "";  	struct headset *hs = NULL;  	DBusMessage *auth; @@ -431,18 +526,16 @@ gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data)  		return TRUE;  	} -	hs = manager_find_headset_by_bda(&addr.rc_bdaddr); -	if (!hs) { -		hs = headset_new(manager_get_dbus_conn(), &addr.rc_bdaddr); -		if (!hs) { -			error("Unable to create a new headset object"); -			close(cli_sk); -			return TRUE; -		} - -		manager_add_headset(hs); +	/* This returns an existing path if the headset already exists */ +	path = headset_add(&addr.rc_bdaddr); +	if (!path) { +		error("Unable to create a new headset object"); +		close(cli_sk); +		return TRUE;  	} +	manager_add_headset(path); +  	if (hs->state > HEADSET_STATE_DISCONNECTED || hs->rfcomm) {  		debug("Refusing new connection since one already exists");  		close(cli_sk); @@ -468,7 +561,7 @@ gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data)  	dbus_message_append_args(auth, DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); -	if (dbus_connection_send_with_reply(hs->conn, auth, &pending, -1) == FALSE) { +	if (dbus_connection_send_with_reply(connection, auth, &pending, -1) == FALSE) {  		error("Sending of authorization request failed");  		goto failed;  	} @@ -618,7 +711,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(hs->conn, reply); +			send_message_and_unref(connection, reply);  	}  	/* FIXME: do we allow both? pull & push model at the same time on sco && audio_input? */ @@ -635,7 +728,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,  failed:  	if (hs->pending_connect) { -		err_connect_failed(hs->conn, hs->pending_connect->msg, err); +		err_connect_failed(connection, hs->pending_connect->msg, err);  		if (hs->pending_connect->io)  			g_io_channel_close(hs->pending_connect->io);  		pending_connect_free(hs->pending_connect); @@ -694,7 +787,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->conn, reply); +				send_message_and_unref(connection, reply);  		}  		pending_connect_free(hs->pending_connect); @@ -705,7 +798,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct he  failed:  	if (hs->pending_connect) { -		err_connect_failed(hs->conn, hs->pending_connect->msg, err); +		err_connect_failed(connection, hs->pending_connect->msg, err);  		if (hs->pending_connect->io)  			g_io_channel_close(hs->pending_connect->io);  		pending_connect_free(hs->pending_connect); @@ -791,14 +884,7 @@ failed:  	return -1;  } -gint headset_path_cmp(gconstpointer headset, gconstpointer path) -{ -	const struct headset *hs = headset; - -	return strcmp(hs->object_path, path); -} - -gint headset_bda_cmp(gconstpointer headset, gconstpointer bda) +static gint headset_bda_cmp(gconstpointer headset, gconstpointer bda)  {  	const struct headset *hs = headset; @@ -866,7 +952,7 @@ static int create_ag_record(sdp_buf_t *buf, uint8_t ch)  	return ret;  } -uint32_t headset_add_ag_record(DBusConnection *conn, uint8_t channel) +uint32_t headset_add_ag_record(uint8_t channel)  {  	DBusMessage *msg, *reply;  	DBusError derr; @@ -890,7 +976,8 @@ uint32_t headset_add_ag_record(DBusConnection *conn, uint8_t channel)  				&buf.data, buf.data_size, DBUS_TYPE_INVALID);  	dbus_error_init(&derr); -	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); +	reply = dbus_connection_send_with_reply_and_block(connection, msg, +								-1, &derr);  	free(buf.data);  	dbus_message_unref(msg); @@ -918,7 +1005,7 @@ uint32_t headset_add_ag_record(DBusConnection *conn, uint8_t channel)  	return rec_id;  } -int headset_remove_ag_record(DBusConnection *conn, uint32_t rec_id) +int headset_remove_ag_record(uint32_t rec_id)  {  	DBusMessage *msg, *reply;  	DBusError derr; @@ -934,7 +1021,8 @@ int headset_remove_ag_record(DBusConnection *conn, uint32_t rec_id)  						DBUS_TYPE_INVALID);  	dbus_error_init(&derr); -	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); +	reply = dbus_connection_send_with_reply_and_block(connection, msg, +								-1, &derr);  	dbus_message_unref(msg); @@ -969,7 +1057,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(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		dbus_error_free(&derr);  		goto failed;  	} @@ -979,14 +1067,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(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	}  	if (!array) {  		error("Unable to get handle array from reply");  		if (c->msg)  -			err_not_supported(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	} @@ -994,7 +1082,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(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	} @@ -1012,14 +1100,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(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	}  	if (rfcomm_connect(hs, &err) < 0) {  		error("Unable to connect");  		if (c->msg)  -			err_connect_failed(hs->conn, c->msg, err); +			err_connect_failed(connection, c->msg, err);  		goto failed;  	} @@ -1043,7 +1131,7 @@ static DBusHandlerResult hs_stop(struct headset *hs, DBusMessage *msg)  	DBusMessage *reply = NULL;  	if (!hs || !hs->sco) -		return err_not_connected(hs->conn, msg); +		return err_not_connected(connection, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1054,7 +1142,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->conn, hs->pending_connect->msg, +			err_connect_failed(connection, hs->pending_connect->msg,  						EINTR);  		pending_connect_free(hs->pending_connect);  		hs->pending_connect = NULL; @@ -1064,7 +1152,7 @@ static DBusHandlerResult hs_stop(struct headset *hs, DBusMessage *msg)  	close_sco(hs);  	if (reply) -		send_message_and_unref(hs->conn, reply); +		send_message_and_unref(connection, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1095,7 +1183,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->conn, hs->pending_connect->msg, +			err_connect_failed(connection, hs->pending_connect->msg,  						EINTR);  		pending_connect_free(hs->pending_connect);  		hs->pending_connect = NULL; @@ -1112,7 +1200,7 @@ static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg)  	hs->data_length = 0;  	if (reply) -		send_message_and_unref(hs->conn, reply); +		send_message_and_unref(connection, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1136,7 +1224,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(hs->conn, reply); +	send_message_and_unref(connection, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1163,9 +1251,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(hs->conn, c->msg, EHOSTDOWN); +				err_connect_failed(connection, c->msg, EHOSTDOWN);  			else -				err_not_supported(hs->conn, c->msg); +				err_not_supported(connection, c->msg);  		}  		dbus_error_free(&derr);  		goto failed; @@ -1177,21 +1265,21 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  		error("Unable to get args from reply");  		if (c->msg)  -			err_not_supported(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	}  	if (!array) {  		error("Unable to get handle array from reply");  		if (c->msg)  -			err_not_supported(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	}  	if (array_len < 1) {  		debug("No record handles found");  		if (c->msg)  -			err_not_supported(hs->conn, c->msg); +			err_not_supported(connection, c->msg);  		goto failed;  	} @@ -1204,7 +1292,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(hs->conn, c->msg, ENOMEM); +			err_connect_failed(connection, c->msg, ENOMEM);  		goto failed;  	} @@ -1216,10 +1304,10 @@ static void get_handles_reply(DBusPendingCall *call, void *data)  					DBUS_TYPE_UINT32, &handle,  					DBUS_TYPE_INVALID); -	if (!dbus_connection_send_with_reply(hs->conn, msg, &pending, -1)) { +	if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {  		error("Sending GetRemoteServiceRecord failed");  		if (c->msg)  -			err_connect_failed(hs->conn, c->msg, EIO); +			err_connect_failed(connection, c->msg, EIO);  		goto failed;  	} @@ -1278,13 +1366,13 @@ static DBusHandlerResult hs_connect(struct headset *hs, DBusMessage *msg)  					DBUS_TYPE_STRING, &hs_svc,  					DBUS_TYPE_INVALID); -	if (!dbus_connection_send_with_reply(hs->conn, msg, &pending, -1)) { +	if (!dbus_connection_send_with_reply(connection, 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(hs->conn, msg, EIO); +		return err_connect_failed(connection, msg, EIO);  	}  	dbus_pending_call_set_notify(pending, get_handles_reply, hs, NULL); @@ -1339,7 +1427,7 @@ static DBusHandlerResult hs_ring(struct headset *hs, DBusMessage *msg)  	assert(hs != NULL);  	if (hs->state < HEADSET_STATE_CONNECTED) -		return err_not_connected(hs->conn, msg); +		return err_not_connected(connection, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1354,14 +1442,14 @@ static DBusHandlerResult hs_ring(struct headset *hs, DBusMessage *msg)  	if (headset_send_ring(hs) != G_IO_ERROR_NONE) {  		dbus_message_unref(reply); -		return err_failed(hs->conn, msg); +		return err_failed(connection, msg);  	}  	hs->ring_timer = g_timeout_add(RING_INTERVAL, ring_timer_cb, hs);  done:  	if (reply) -		send_message_and_unref(hs->conn, reply); +		send_message_and_unref(connection, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1371,7 +1459,7 @@ static DBusHandlerResult hs_cancel_ringing(struct headset *hs, DBusMessage *msg)  	DBusMessage *reply = NULL;  	if (hs->state < HEADSET_STATE_CONNECTED) -		return err_not_connected(hs->conn, msg); +		return err_not_connected(connection, msg);  	if (msg) {  		reply = dbus_message_new_method_return(msg); @@ -1389,7 +1477,7 @@ static DBusHandlerResult hs_cancel_ringing(struct headset *hs, DBusMessage *msg)  done:  	if (reply) -		send_message_and_unref(hs->conn, reply); +		send_message_and_unref(connection, reply);  	return DBUS_HANDLER_RESULT_HANDLED;  } @@ -1401,13 +1489,13 @@ static DBusHandlerResult hs_play(struct headset *hs, DBusMessage *msg)  	int sk, err;  	if (hs->state < HEADSET_STATE_CONNECTED) -		return err_not_connected(hs->conn, msg); /* FIXME: in progress error? */ +		return err_not_connected(connection, msg); /* FIXME: in progress error? */  	if (hs->state >= HEADSET_STATE_PLAY_IN_PROGRESS || hs->pending_connect) -		return err_already_connected(hs->conn, msg); +		return err_already_connected(connection, msg);  	if (hs->sco) -		return err_already_connected(hs->conn, msg); +		return err_already_connected(connection, msg);  	c = g_try_new0(struct pending_connect, 1);  	if (!c) @@ -1421,7 +1509,7 @@ static DBusHandlerResult hs_play(struct headset *hs, DBusMessage *msg)  	if (sk < 0) {  		err = errno;  		error("socket(BTPROTO_SCO): %s (%d)", strerror(err), err); -		err_connect_failed(hs->conn, msg, err); +		err_connect_failed(connection, msg, err);  		goto failed;  	} @@ -1439,13 +1527,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(hs->conn, msg, err); +		err_connect_failed(connection, msg, err);  		goto failed;  	}  	if (set_nonblocking(sk) < 0) {  		err = errno; -		err_connect_failed(hs->conn, msg, err); +		err_connect_failed(connection, msg, err);  		goto failed;  	} @@ -1525,15 +1613,17 @@ static const DBusObjectPathVTable hs_table = {  	.message_function = hs_message,  }; -/* -** audio_headset_new: -** Create a unique dbus object path for the headset and allocates a new -** headset or return NULL if fail -*/ -struct headset *headset_new(DBusConnection *conn, const bdaddr_t *bda) +char *headset_add(const bdaddr_t *bda)  {  	static int headset_uid = 0;  	struct headset *hs; +	GSList *match; + +	match = g_slist_find_custom(headsets, bda, headset_bda_cmp); +	if (match) { +		hs = match->data; +		return hs->object_path; +	}  	hs = g_try_new0(struct headset, 1);  	if (!hs) { @@ -1544,7 +1634,7 @@ struct headset *headset_new(DBusConnection *conn, const bdaddr_t *bda)  	snprintf(hs->object_path, sizeof(hs->object_path),  			HEADSET_PATH_BASE "%d", headset_uid++); -	if (!dbus_connection_register_object_path(conn, hs->object_path, +	if (!dbus_connection_register_object_path(connection, hs->object_path,  						&hs_table, hs)) {  		error("D-Bus failed to register %s path", hs->object_path);  		free (hs); @@ -1553,118 +1643,38 @@ struct headset *headset_new(DBusConnection *conn, const bdaddr_t *bda)  	bacpy(&hs->bda, bda); -	hs->conn = dbus_connection_ref(conn); +	headsets = g_slist_append(headsets, hs); -	return hs; +	return g_strdup(hs->object_path);  } -void headset_unref(struct headset *hs) +void headset_remove(char *path)  { -	assert(hs != NULL); +	struct headset *hs; + +	if (!dbus_connection_get_object_path_data(connection, path, (void *) +							&hs)) +		return;  	if (hs->state > HEADSET_STATE_DISCONNECTED)  		hs_disconnect(hs, NULL); -	if (!dbus_connection_unregister_object_path(hs->conn, hs->object_path)) -		error("D-Bus failed to unregister %s path", hs->object_path); +	if (!dbus_connection_unregister_object_path(connection, path)) +		error("D-Bus failed to unregister %s path", path); -	dbus_connection_unref(hs->conn); +	headsets = g_slist_remove(headsets, hs);  	g_free(hs); +	g_free(path);  } -gboolean headset_close_output(struct headset *hs) -{ -	assert(hs != NULL); - -	if (hs->audio_output == NULL)  -		return FALSE; - -	g_io_channel_close(hs->audio_output); -	g_io_channel_unref(hs->audio_output); -	hs->audio_output = NULL; - -	return TRUE; -} - -/* FIXME: in the furture, that would be great to provide user space alsa driver (not plugin) */ -gboolean headset_open_output(struct headset *hs, const char *output) -{ -	int out; - -	assert(hs != NULL && output != NULL); - -	headset_close_output(hs); -	if (output && hs->output) { -		g_free(hs->output); -		hs->output = g_strdup(output); -	} - -	assert(hs->output); - -	out = open(hs->output, O_WRONLY | O_SYNC | O_CREAT); - -	if (out < 0) { -		error("open(%s): %s %d", hs->output, strerror(errno), errno); -		return FALSE; -	} - -	hs->audio_output = g_io_channel_unix_new(out); -	if (!hs->audio_output) { -		error("Allocating new channel for audio output!"); -		return FALSE; -	} - -	g_io_channel_set_close_on_unref(hs->audio_output, TRUE); - -	return TRUE; -} - -gboolean headset_close_input(struct headset *hs) -{ -	assert(hs != NULL); - -	if (hs->audio_input == NULL)  -		return FALSE; - -	g_io_channel_close(hs->audio_input); -	g_io_channel_unref(hs->audio_input); -	hs->audio_input = NULL; - -	return TRUE; -} - -gboolean headset_open_input(struct headset *hs, const char *input) +void headset_init(DBusConnection *conn)  { -	int in; - -	assert(hs != NULL); -	 -	/* we keep the input name, and NULL can be use to reopen */ -	if (input && hs->input) { -		g_free(hs->input); -		hs->input = g_strdup(input); -	} - -	assert(hs->input); - -	in = open(hs->input, O_RDONLY | O_NOCTTY); - -	if (in < 0) { -		error("open(%s): %s %d", hs->input, strerror(errno), errno); -		return FALSE; -	} - -	hs->audio_input = g_io_channel_unix_new(in); -	if (!hs->audio_input) { -		error("Allocating new channel for audio input!"); -		return FALSE; -	} - -	return TRUE; +	connection = dbus_connection_ref(conn);  } -const char *headset_get_path(struct headset *hs) +void headset_exit(void)  { -	return hs->object_path; +	dbus_connection_unref(connection); +	connection = NULL;  } diff --git a/audio/headset.h b/audio/headset.h index 13532cb7..b8582cef 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -27,31 +27,19 @@  #include <dbus/dbus.h> -struct headset; -  #define BUF_SIZE 1024 -struct headset *headset_new(DBusConnection *conn, const bdaddr_t *bda); +char *headset_add(const bdaddr_t *bda); -void headset_unref(struct headset *hs); +void headset_remove(char *path); -uint32_t headset_add_ag_record(DBusConnection *conn, uint8_t channel); +uint32_t headset_add_ag_record(uint8_t channel); -int headset_remove_ag_record(DBusConnection *conn, uint32_t rec_id); +int headset_remove_ag_record(uint32_t rec_id);  gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data); -gint headset_path_cmp(gconstpointer headset, gconstpointer path); -gint headset_bda_cmp(gconstpointer headset, gconstpointer bda); - -const char *headset_get_path(struct headset *hs); - -gboolean headset_close_output(struct headset *hs); - -gboolean headset_open_output(struct headset *hs, const char *output); - -gboolean headset_close_input(struct headset *hs); - -gboolean headset_open_input(struct headset *hs, const char *input); +void headset_init(DBusConnection *conn); +void headset_exit(void);  #endif /* __AUDIO_HEADSET_H_ */ diff --git a/audio/main.c b/audio/main.c index 6ef3b1c6..3cf609f6 100644 --- a/audio/main.c +++ b/audio/main.c @@ -73,6 +73,8 @@ int main(int argc, char *argv[])  		exit(1);  	} +	headset_init(conn); +  	audio_init(conn);  	if (argc > 1 && !strcmp(argv[1], "-s")) @@ -82,6 +84,8 @@ int main(int argc, char *argv[])  	audio_exit(); +	headset_exit(); +  	dbus_connection_unref(conn);  	g_main_loop_unref(main_loop); diff --git a/audio/manager.c b/audio/manager.c index 6c54d314..03a6fc47 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -58,7 +58,7 @@ static DBusConnection *connection = NULL;  static GIOChannel *hs_server = NULL;  static uint32_t hs_record_id; -static struct headset *default_hs; +static char *default_hs = NULL;  static GSList *headsets = NULL; @@ -200,7 +200,7 @@ static gboolean manager_create_headset_server(uint8_t chan)  		return FALSE;  	if (!hs_record_id) -		hs_record_id = headset_add_ag_record(connection, chan); +		hs_record_id = headset_add_ag_record(chan);  	if (!hs_record_id) {  		error("Unable to register service record"); @@ -215,35 +215,25 @@ static gboolean manager_create_headset_server(uint8_t chan)  	return TRUE;  } -struct headset *manager_find_headset_by_bda(bdaddr_t *bda) +void manager_add_headset(char *path)  { -	GSList *elem; - -	elem = g_slist_find_custom(headsets, bda, headset_bda_cmp); - -	return elem ? elem->data : NULL; -} - -void manager_add_headset(struct headset *hs) -{ -	assert(hs); +	if (g_slist_find_custom(headsets, path, (GCompareFunc) strcmp)) +		return; -	headsets = g_slist_append(headsets, hs); +	headsets = g_slist_append(headsets, path); -	manager_signal(connection, "HeadsetCreated", headset_get_path(hs)); +	manager_signal(connection, "HeadsetCreated", path);  	if (!default_hs) { -		default_hs = hs; -		manager_signal(connection, "DefaultHeadsetChanged", -							headset_get_path(hs)); +		default_hs = path; +		manager_signal(connection, "DefaultHeadsetChanged", path);  	}  }  static DBusHandlerResult am_create_headset(DBusMessage *msg)  { -	const char *object_path; +	char *hs_path;  	const char *address; -	struct headset *hs;  	bdaddr_t bda;  	DBusMessage *reply;  	DBusError derr; @@ -266,18 +256,15 @@ static DBusHandlerResult am_create_headset(DBusMessage *msg)  		return DBUS_HANDLER_RESULT_NEED_MEMORY;  	str2ba(address, &bda); -	hs = manager_find_headset_by_bda(&bda); -	if (!hs) { -		hs = headset_new(connection, &bda); -		if (!hs) -			return error_reply(connection, msg, -					"org.bluez.Error.Failed", -					"Unable to create new headset object"); -		manager_add_headset(hs); -	} - -	object_path = headset_get_path(hs); -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &object_path, +	/* This returns an existing path if the headset already exists */ +	hs_path = headset_add(&bda); +	if (!hs_path) +		return error_reply(connection, msg, +				"org.bluez.Error.Failed", +				"Unable to create new headset object"); +	manager_add_headset(hs_path); + +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &hs_path,  					DBUS_TYPE_INVALID);  	return send_message_and_unref(connection, reply); @@ -288,8 +275,7 @@ static DBusHandlerResult am_remove_headset(DBusMessage *msg)  	DBusError derr;  	DBusMessage *reply;  	GSList *match; -	struct headset *hs; -	const char *path; +	char *path;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr, @@ -304,7 +290,7 @@ static DBusHandlerResult am_remove_headset(DBusMessage *msg)  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	match = g_slist_find_custom(headsets, path, headset_path_cmp); +	match = g_slist_find_custom(headsets, path, (GCompareFunc) strcmp);  	if (!match)  		return error_reply(connection, msg, "org.bluez.Error.DoesNotExist",  					"The headset does not exist"); @@ -313,23 +299,23 @@ static DBusHandlerResult am_remove_headset(DBusMessage *msg)  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; -	hs = match->data; +	path = match->data; -	headsets = g_slist_remove(headsets, hs); +	headsets = g_slist_remove(headsets, path); -	if (default_hs == hs) { +	if (default_hs == path) {  		if (!headsets)  			default_hs = NULL;  		else  			default_hs = headsets->data;  		manager_signal(connection, "DefaultHeadsetChanged", -				default_hs ? headset_get_path(default_hs) : ""); +				default_hs ? default_hs : "");  	} -	manager_signal(connection, "HeadsetRemoved", headset_get_path(hs)); +	manager_signal(connection, "HeadsetRemoved", path); -	headset_unref(hs); +	headset_remove(path);  	return send_message_and_unref(connection, reply);  } @@ -350,13 +336,9 @@ static DBusHandlerResult am_list_headsets(DBusMessage *msg)  	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,  				DBUS_TYPE_STRING_AS_STRING, &array_iter); -	for (l = headsets; l != NULL; l = l->next) { -		struct headset *hs = l->data; -		const char *path = headset_get_path(hs); - +	for (l = headsets; l != NULL; l = l->next)  		dbus_message_iter_append_basic(&array_iter, -						DBUS_TYPE_STRING, &path); -	} +						DBUS_TYPE_STRING, &l->data);  	dbus_message_iter_close_container(&iter, &array_iter); @@ -366,7 +348,6 @@ static DBusHandlerResult am_list_headsets(DBusMessage *msg)  static DBusHandlerResult am_get_default_headset(DBusMessage *msg)  {  	DBusMessage *reply; -	const char *opath;  	if (!default_hs)  		return error_reply(connection, msg, "org.bluez.Error.DoesNotExist", @@ -376,9 +357,7 @@ static DBusHandlerResult am_get_default_headset(DBusMessage *msg)  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; -	opath = headset_get_path(default_hs); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &opath, +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_hs,  					DBUS_TYPE_INVALID);  	return send_message_and_unref(connection, reply); @@ -404,7 +383,7 @@ static DBusHandlerResult am_change_default_headset(DBusMessage *msg)  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	match = g_slist_find_custom(headsets, path, headset_path_cmp); +	match = g_slist_find_custom(headsets, path, (GCompareFunc) strcmp);  	if (!match)  		return error_reply(connection, msg, "org.bluez.Error.DoesNotExist",  					"The headset does not exist"); @@ -415,8 +394,7 @@ static DBusHandlerResult am_change_default_headset(DBusMessage *msg)  	default_hs = match->data; -	manager_signal(connection, "DefaultHeadsetChanged", -					headset_get_path(default_hs)); +	manager_signal(connection, "DefaultHeadsetChanged", default_hs);  	return send_message_and_unref(connection, reply);  } @@ -517,7 +495,7 @@ void audio_exit(void)  	unix_sock = -1;  	if (hs_record_id) { -		headset_remove_ag_record(connection, hs_record_id); +		headset_remove_ag_record(hs_record_id);  		hs_record_id = 0;  	} @@ -527,7 +505,7 @@ void audio_exit(void)  	}  	if (headsets) { -		g_slist_foreach(headsets, (GFunc) headset_unref, NULL); +		g_slist_foreach(headsets, (GFunc) headset_remove, NULL);  		g_slist_free(headsets);  		headsets = NULL;  	} diff --git a/audio/manager.h b/audio/manager.h index ee45f7c7..9a9948ff 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -31,7 +31,7 @@  #define HEADSET_PATH_BASE AUDIO_MANAGER_PATH "/headset" -void manager_add_headset(struct headset *hs); +void manager_add_headset(char *path);  struct headset *manager_find_headset_by_bda(bdaddr_t *bda); | 
