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); |