diff options
-rw-r--r-- | audio/audio-api.txt | 8 | ||||
-rw-r--r-- | audio/headset.c | 145 | ||||
-rw-r--r-- | audio/headset.h | 4 | ||||
-rw-r--r-- | audio/main.c | 2 | ||||
-rw-r--r-- | audio/manager.c | 321 | ||||
-rw-r--r-- | audio/manager.h | 2 | ||||
-rw-r--r-- | audio/unix.c | 60 | ||||
-rw-r--r-- | audio/unix.h | 3 |
8 files changed, 289 insertions, 256 deletions
diff --git a/audio/audio-api.txt b/audio/audio-api.txt index 17baedc1..cd736802 100644 --- a/audio/audio-api.txt +++ b/audio/audio-api.txt @@ -35,6 +35,14 @@ Methods of available devices which implement as a minimum the interfaces given through the parameter. + string DefaultDevice() + + Returns the object path for the default device. + + void ChangeDefaultDevice(string path) + + Changes the default device. + array{string} ListHeadsets() Returns list of headset objects that are configured. diff --git a/audio/headset.c b/audio/headset.c index 5c087312..723bc1ab 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -89,6 +89,8 @@ struct pending_connect { DBusMessage *msg; GIOChannel *io; guint io_id; + int sock; + struct ipc_data_cfg *cfg; }; struct headset { @@ -325,7 +327,7 @@ static void send_cancel_auth(audio_device_t *device) DBusMessage *cancel; char addr[18], *address = addr; const char *uuid; - + if (device->headset->type == SVC_HEADSET) uuid = HSP_AG_UUID; else @@ -475,9 +477,11 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond, g_io_add_watch(hs->sco, flags, (GIOFunc) sco_cb, device); - reply = dbus_message_new_method_return(hs->pending_connect->msg); - if (reply) - send_message_and_unref(connection, reply); + if (hs->pending_connect->msg) { + reply = dbus_message_new_method_return(hs->pending_connect->msg); + if (reply) + send_message_and_unref(connection, reply); + } pending_connect_free(hs->pending_connect); hs->pending_connect = NULL; @@ -514,6 +518,70 @@ failed: return FALSE; } +static int sco_connect(audio_device_t *device, struct pending_connect *c) +{ + struct headset *hs = device->headset; + struct sockaddr_sco addr; + gboolean do_callback = FALSE; + int sk, err; + + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); + if (sk < 0) { + err = errno; + error("socket(BTPROTO_SCO): %s (%d)", strerror(err), err); + return -err; + } + + c->io = g_io_channel_unix_new(sk); + if (!c->io) { + close(sk); + return -EINVAL; + } + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, BDADDR_ANY); + + if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + err = errno; + error("socket(BTPROTO_SCO): %s (%d)", strerror(err), err); + return -err; + } + + if (set_nonblocking(sk) < 0) { + err = errno; + return -err; + } + + memset(&addr, 0, sizeof(addr)); + addr.sco_family = AF_BLUETOOTH; + bacpy(&addr.sco_bdaddr, &device->bda); + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (!(errno == EAGAIN || errno == EINPROGRESS)) { + err = errno; + error("connect: %s (%d)", strerror(errno), errno); + return -err; + } + + debug("SCO connect in progress"); + c->io_id = g_io_add_watch(c->io, + G_IO_OUT | G_IO_NVAL | G_IO_ERR | G_IO_HUP, + (GIOFunc) sco_connect_cb, device); + } else { + debug("SCO connect succeeded with first try"); + do_callback = TRUE; + } + + hs->state = HEADSET_STATE_PLAY_IN_PROGRESS; + hs->pending_connect = c; + + if (do_callback) + sco_connect_cb(c->io, G_IO_OUT, device); + + return 0; +} + static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, audio_device_t *device) { @@ -521,14 +589,14 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, char hs_address[18]; int sk, ret, err; socklen_t len; - + if (cond & G_IO_NVAL) return FALSE; hs = device->headset; assert(hs != NULL); - assert(hs->pending_connect != NULL); + assert(hs->pending_connect != NULL); assert(hs->rfcomm == NULL); assert(hs->state == HEADSET_STATE_CONNECT_IN_PROGRESS); @@ -1406,10 +1474,7 @@ static DBusHandlerResult hs_play(DBusConnection *conn, DBusMessage *msg, { audio_device_t *device = data; struct headset *hs = device->headset; - struct sockaddr_sco addr; struct pending_connect *c; - gboolean do_callback = FALSE; - int sk, err; if (hs->state < HEADSET_STATE_CONNECTED) return err_not_connected(connection, msg); @@ -1426,66 +1491,10 @@ static DBusHandlerResult hs_play(DBusConnection *conn, DBusMessage *msg, 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); - goto failed; - } - - c->io = g_io_channel_unix_new(sk); - if (!c->io) { - close(sk); - pending_connect_free(c); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - - memset(&addr, 0, sizeof(addr)); - addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, BDADDR_ANY); - - 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); + if (sco_connect(device, c) < 0) goto failed; - } - - if (set_nonblocking(sk) < 0) { - err = errno; - err_connect_failed(connection, msg, err); - goto failed; - } - - memset(&addr, 0, sizeof(addr)); - addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, &device->bda); - - if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - if (!(errno == EAGAIN || errno == EINPROGRESS)) { - err = errno; - error("connect: %s (%d)", strerror(errno), errno); - goto failed; - } - - debug("SCO connect in progress"); - c->io_id = g_io_add_watch(c->io, - G_IO_OUT | G_IO_NVAL | G_IO_ERR | G_IO_HUP, - (GIOFunc) sco_connect_cb, device); - } else { - debug("SCO connect succeeded with first try"); - do_callback = TRUE; - } - - hs->state = HEADSET_STATE_PLAY_IN_PROGRESS; - hs->pending_connect = c; - - if (do_callback) - sco_connect_cb(c->io, G_IO_OUT, device); return 0; - failed: if (c) pending_connect_free(c); @@ -1772,7 +1781,7 @@ register_iface: } void headset_free(const char *object_path) -{ +{ audio_device_t *device; if (!dbus_connection_get_object_user_data(connection, object_path, @@ -2028,7 +2037,7 @@ void headset_exit(void) connection = NULL; } -int headset_get_config(headset_t *headset, struct ipc_data_cfg *cfg) +int headset_get_config(headset_t *headset, int sock, struct ipc_data_cfg *cfg) { if (!sco_over_hci) return -1; diff --git a/audio/headset.h b/audio/headset.h index 6780e7a9..b420860e 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -29,7 +29,7 @@ #include <dbus/dbus.h> -#include "ipc.h" +#include "unix.h" #define AUDIO_HEADSET_INTERFACE "org.bluez.audio.Headset" @@ -49,6 +49,6 @@ int headset_server_init(DBusConnection *conn, gboolean disable_hfp, void headset_exit(void); -int headset_get_config(headset_t *headset, struct ipc_data_cfg *cfg); +int headset_get_config(headset_t *headset, int sock, struct ipc_data_cfg *cfg); #endif /* __AUDIO_HEADSET_H_ */ diff --git a/audio/main.c b/audio/main.c index 3a170b1a..0ca8ce87 100644 --- a/audio/main.c +++ b/audio/main.c @@ -36,9 +36,7 @@ #include "dbus.h" #include "logging.h" -#include "unix.h" #include "manager.h" -#include "headset.h" /* Configuration settings */ static gboolean disable_hfp = TRUE; diff --git a/audio/manager.c b/audio/manager.c index e166fdca..7faa0490 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -79,7 +79,7 @@ struct audio_sdp_data { static DBusConnection *connection = NULL; -static audio_device_t *default_hs = NULL; +static audio_device_t *default_dev = NULL; static GSList *devices = NULL; @@ -275,6 +275,10 @@ static gboolean add_device(audio_device_t *device) return FALSE; } + /* First device became default */ + if (g_slist_length(devices) == 0) + default_dev = device; + devices = g_slist_append(devices, device); return TRUE; @@ -370,6 +374,11 @@ static void handle_record(sdp_record_t *record, audio_device_t *device) break; case HANDSFREE_SVCLASS_ID: debug("Found Hansfree record"); + if (device->headset) + headset_update(device->headset, record, uuid16); + else + device->headset = headset_init(device->object_path, + record, uuid16); break; case HANDSFREE_AGW_SVCLASS_ID: debug("Found Handsfree AG record"); @@ -429,6 +438,7 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success) char **required; int required_len, i; DBusMessage *reply = NULL; + DBusError derr; debug("Audio service discovery completed with %s", success ? "success" : "failure"); @@ -441,13 +451,43 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success) if (!data->msg) goto update; - if (!dbus_message_get_args(data->msg, NULL, + dbus_error_init(&derr); + if (dbus_message_is_method_call(data->msg, AUDIO_MANAGER_INTERFACE, + "CreateHeadset")) { + dbus_message_get_args(data->msg, &derr, + DBUS_TYPE_STRING, &addr, + DBUS_TYPE_INVALID); + required = dbus_new0(char *, 2); + if (required == NULL) { + success = FALSE; + err_failed(connection, data->msg, "Out of memory"); + goto done; + } + + required[0] = dbus_new0(char, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + if (required[0] == NULL) { + success = FALSE; + err_failed(connection, data->msg, "Out of memory"); + goto done; + } + + memcpy(required[0], AUDIO_HEADSET_INTERFACE, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + required[1] = NULL; + required_len = 1; + } + else + dbus_message_get_args(data->msg, &derr, DBUS_TYPE_STRING, &addr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &required, &required_len, - DBUS_TYPE_INVALID)) { + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&derr)) { error("Unable to get message args"); success = FALSE; + dbus_error_free(&derr); goto done; } @@ -494,13 +534,20 @@ update: "DeviceCreated", DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); - + if (data->device->headset) + dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH, + AUDIO_MANAGER_INTERFACE, + "HeadsetCreated", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); send_message_and_unref(connection, reply); } done: + if (required) + dbus_free_string_array(required); if (!success) free_device(data->device); if (data->msg) @@ -651,7 +698,6 @@ static void get_handles_reply(DBusPendingCall *call, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &array, &array_len, DBUS_TYPE_INVALID)) { - err_failed(connection, data->msg, "Unable to get args from reply"); goto failed; @@ -679,7 +725,7 @@ static void get_handles_reply(DBusPendingCall *call, get_next_record(data); else finish_sdp(data, TRUE); - } + } dbus_message_unref(reply); @@ -789,8 +835,8 @@ audio_device_t *manager_headset_connected(bdaddr_t *bda) DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); - if (!default_hs) { - default_hs = device; + if (!default_dev) { + default_dev = device; dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH, AUDIO_MANAGER_INTERFACE, "DefaultHeadsetChanged", @@ -805,13 +851,13 @@ static gboolean device_supports_interface(audio_device_t *device, const char *iface) { if (strcmp(iface, AUDIO_HEADSET_INTERFACE) == 0) - return device->headset ? TRUE : FALSE; + return device->headset ? TRUE : FALSE; if (strcmp(iface, AUDIO_GATEWAY_INTERFACE) == 0) return device->gateway ? TRUE : FALSE; if (strcmp(iface, AUDIO_SOURCE_INTERFACE) == 0) - return device->gateway ? TRUE : FALSE; + return device->source ? TRUE : FALSE; if (strcmp(iface, AUDIO_SINK_INTERFACE) == 0) return device->sink ? TRUE : FALSE; @@ -854,11 +900,34 @@ static DBusHandlerResult am_create_device(DBusConnection *conn, DBusError derr; dbus_error_init(&derr); - dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &required, &required_len, - DBUS_TYPE_INVALID); + if (dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE, + "CreateHeadset")) { + dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + required = dbus_new0(char *, 2); + if (required == NULL) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + required[0] = dbus_new0(char, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + if (required[0] == NULL) { + dbus_free(required); + return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + + memcpy(required[0], AUDIO_HEADSET_INTERFACE, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + required[1] = NULL; + required_len = 1; + } + else + dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &required, &required_len, + DBUS_TYPE_INVALID); + if (dbus_error_is_set(&derr)) { err_invalid_args(connection, msg, derr.message); dbus_error_free(&derr); @@ -905,10 +974,31 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn, int required_len; dbus_error_init(&derr); - dbus_message_get_args(msg, &derr, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &required, &required_len, - DBUS_TYPE_INVALID); + + if (dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE, + "ListHeadsets")) { + required = dbus_new0(char *, 2); + if (required == NULL) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + required[0] = dbus_new0(char, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + if (required[0] == NULL) { + dbus_free(required); + return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + + memcpy(required[0], AUDIO_HEADSET_INTERFACE, + strlen(AUDIO_HEADSET_INTERFACE) + 1); + required[1] = NULL; + required_len = 1; + } + else + dbus_message_get_args(msg, &derr, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &required, &required_len, + DBUS_TYPE_INVALID); + if (dbus_error_is_set(&derr)) { err_invalid_args(connection, msg, derr.message); dbus_error_free(&derr); @@ -944,72 +1034,6 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn, return send_message_and_unref(connection, reply); } -static DBusHandlerResult am_create_headset(DBusConnection *conn, DBusMessage *msg, - void *data) -{ - const char *path, *address; - bdaddr_t bda; - DBusMessage *reply; - DBusError derr; - audio_device_t *device; - gboolean created = FALSE; - - dbus_error_init(&derr); - dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); - if (dbus_error_is_set(&derr)) { - err_invalid_args(connection, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } - - str2ba(address, &bda); - - device = find_device(&bda); - if (device) - goto done; - - device = create_device(&bda); - if (!add_device(device)) { - free_device(device); - return error_reply(connection, msg, - "org.bluez.audio.Error.Failed", - "Unable to create new audio device"); - } - - if (!device->headset) { - device->headset = headset_init(device->object_path, NULL, 0); - created = TRUE; - } - - if (!device->headset) { - remove_device(device); - return error_reply(connection, msg, - "org.bluez.audio.Error.Failed", - "Unable to init Headset interface"); - } - -done: - path = device->object_path; - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - if (created) - dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH, - AUDIO_MANAGER_INTERFACE, - "HeadsetCreated", - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - return send_message_and_unref(connection, reply); -} - static gint device_path_cmp(gconstpointer a, gconstpointer b) { const audio_device_t *device = a; @@ -1045,7 +1069,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn, if (!match) return error_reply(connection, msg, "org.bluez.audio.Error.DoesNotExist", - "The headset does not exist"); + "The device does not exist"); reply = dbus_message_new_method_return(msg); if (!reply) @@ -1055,20 +1079,20 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn, remove_device(device); - if (default_hs == device) { + if (default_dev == device) { const char *param; GSList *l; - default_hs = NULL; + default_dev = NULL; for (l = devices; l != NULL; l = l->next) { device = l->data; if (device->headset) - default_hs = device; + default_dev = device; } - param = default_hs ? default_hs->object_path : ""; + param = default_dev ? default_dev->object_path : ""; dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH, AUDIO_MANAGER_INTERFACE, @@ -1092,49 +1116,6 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn, return send_message_and_unref(connection, reply); } -static DBusHandlerResult am_remove_headset(DBusConnection *conn, - DBusMessage *msg, - void *data) -{ - return am_remove_device(conn, msg, data); -} - -static DBusHandlerResult am_list_headsets(DBusConnection *conn, - DBusMessage *msg, - void *data) -{ - DBusMessageIter iter; - DBusMessageIter array_iter; - DBusMessage *reply; - GSList *l; - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &array_iter); - - for (l = devices; l != NULL; l = l->next) { - audio_device_t *device = l->data; - const char *path; - - if (!device->headset) - continue; - - path = device->object_path; - - dbus_message_iter_append_basic(&array_iter, - DBUS_TYPE_STRING, &path); - } - - dbus_message_iter_close_container(&iter, &array_iter); - - return send_message_and_unref(connection, reply); -} - static DBusHandlerResult am_find_by_addr(DBusConnection *conn, DBusMessage *msg, void *data) @@ -1174,14 +1155,21 @@ static DBusHandlerResult am_find_by_addr(DBusConnection *conn, return send_message_and_unref(conn, reply); } -static DBusHandlerResult am_get_default_headset(DBusConnection *conn, +static DBusHandlerResult am_default_device(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; const char *path; - if (!default_hs) + if (!default_dev) + return error_reply(connection, msg, + "org.bluez.audio.Error.DoesNotExist", + "There is no default device"); + + if (default_dev->headset == NULL && + dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE, + "DefaultHeadset")) return error_reply(connection, msg, "org.bluez.audio.Error.DoesNotExist", "There is no default headset"); @@ -1190,7 +1178,7 @@ static DBusHandlerResult am_get_default_headset(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - path = default_hs->object_path; + path = default_dev->object_path; dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); @@ -1198,7 +1186,7 @@ static DBusHandlerResult am_get_default_headset(DBusConnection *conn, return send_message_and_unref(connection, reply); } -static DBusHandlerResult am_change_default_headset(DBusConnection *conn, +static DBusHandlerResult am_change_default_device(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1206,6 +1194,7 @@ static DBusHandlerResult am_change_default_headset(DBusConnection *conn, DBusMessage *reply; GSList *match; const char *path; + audio_device_t *device; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1224,22 +1213,35 @@ static DBusHandlerResult am_change_default_headset(DBusConnection *conn, if (!match) return error_reply(connection, msg, "org.bluez.audio.Error.DoesNotExist", - "The headset does not exist"); + "The device does not exist"); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - default_hs = match->data; + device = match->data; - path = default_hs->object_path; + path = device->object_path; - dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH, - AUDIO_MANAGER_INTERFACE, - "DefaultHeadsetChanged", - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); + if (!dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE, + "ChangeDefaultHeadset")) + dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH, + AUDIO_MANAGER_INTERFACE, + "DefaultDeviceChanged", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + else if (device->headset) + dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH, + AUDIO_MANAGER_INTERFACE, + "DefaultHeadsetChanged", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + else + return error_reply(connection, msg, + "org.bluez.audio.Error.DoesNotExist", + "The headset does not exist"); + default_dev = device; return send_message_and_unref(connection, reply); } @@ -1249,19 +1251,23 @@ static DBusMethodVTable manager_methods[] = { { "RemoveDevice", am_remove_device, "s", "" }, { "ListDevices", am_list_devices, - "as", "as" }, - { "CreateHeadset", am_create_headset, + "as", "as" }, + { "DefaultDevice", am_default_device, + "", "s" }, + { "ChangeDefaultDevice", am_change_default_device, + "s", "" }, + { "CreateHeadset", am_create_device, "s", "s" }, - { "RemoveHeadset", am_remove_headset, + { "RemoveHeadset", am_remove_device, "s", "" }, - { "ListHeadsets", am_list_headsets, + { "ListHeadsets", am_list_devices, "", "as" }, { "FindDeviceByAddress", am_find_by_addr, "s", "s" }, - { "DefaultHeadset", am_get_default_headset, + { "DefaultHeadset", am_default_device, "", "s" }, - { "ChangeDefaultHeadset", am_change_default_headset, - "s", "" }, + { "ChangeDefaultHeadset", am_change_default_device, + "s", "" }, { NULL, NULL, NULL, NULL }, }; @@ -1270,6 +1276,7 @@ static DBusSignalVTable manager_signals[] = { { "DeviceRemoved", "s" }, { "HeadsetCreated", "s" }, { "HeadsetRemoved", "s" }, + { "DefaultDeviceChanged", "s" }, { "DefaultHeadsetChanged", "s" }, { NULL, NULL } }; @@ -1309,19 +1316,19 @@ void audio_exit(void) connection = NULL; } -int manager_get_device(uint8_t role, struct ipc_data_cfg *cfg) +int manager_get_device(int sock, uint8_t role, struct ipc_data_cfg *cfg) { GSList *l; - if (default_hs && default_hs->headset && - headset_is_connected(default_hs->headset)) - return headset_get_config(default_hs->headset, cfg); + if (default_dev && default_dev->headset && + headset_is_connected(default_dev->headset)) + return headset_get_config(default_dev->headset, sock, cfg); for (l = devices; l != NULL; l = l->next) { audio_device_t *dev = l->data; if (dev->headset && headset_is_connected(dev->headset)) - return headset_get_config(dev->headset, cfg); + return headset_get_config(dev->headset, sock, cfg); } return -1; diff --git a/audio/manager.h b/audio/manager.h index 1ec5247b..5cdf2b23 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -95,4 +95,4 @@ DBusHandlerResult err_not_available(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, const char *dsc); -int manager_get_device(uint8_t role, struct ipc_data_cfg *cfg); +int manager_get_device(int sock, uint8_t role, struct ipc_data_cfg *cfg); diff --git a/audio/unix.c b/audio/unix.c index 163f4f98..2dad00df 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -39,7 +39,6 @@ #include "logging.h" #include "dbus.h" -#include "unix.h" #include "manager.h" static int unix_sock = -1; @@ -119,29 +118,8 @@ static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data) cfg = (struct ipc_data_cfg *) pkt->data; memset(cfg, 0, sizeof(struct ipc_data_cfg)); - if (manager_get_device(pkt->role, cfg) < 0) - cfg->fd = -1; - - info("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u, sample_size=%u," - "rate=%u", cfg->fd, cfg->fd_opt, cfg->channels, - cfg->pkt_len, cfg->sample_size, cfg->rate); - - pkt->type = PKT_TYPE_CFG_RSP; - pkt->length = sizeof(struct ipc_data_cfg); - pkt->error = PKT_ERROR_NONE; - - len = send(clisk, pkt, len, 0); - if (len < 0) - info("Error %s(%d)", strerror(errno), errno); - - info("%d bytes sent", len); - - if (cfg->fd != -1) { - len = unix_sendmsg_fd(clisk, cfg->fd, pkt); - if (len < 0) - info("Error %s(%d)", strerror(errno), errno); - info("%d bytes sent", len); - } + if (manager_get_device(clisk, pkt->role, cfg) == 0) + unix_send_cfg(clisk, pkt); break; case PKT_TYPE_STATUS_REQ: @@ -152,8 +130,6 @@ static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data) break; } - g_free(pkt); - close(clisk); return TRUE; } @@ -202,3 +178,35 @@ void unix_exit(void) close(unix_sock); unix_sock = -1; } + +int unix_send_cfg(int sock, struct ipc_packet *pkt) +{ + struct ipc_data_cfg *cfg = (struct ipc_data_cfg *) pkt->data; + int len; + + info("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u, sample_size=%u," + "rate=%u", cfg->fd, cfg->fd_opt, cfg->channels, + cfg->pkt_len, cfg->sample_size, cfg->rate); + + pkt->type = PKT_TYPE_CFG_RSP; + pkt->length = sizeof(struct ipc_data_cfg); + pkt->error = PKT_ERROR_NONE; + + len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_cfg); + len = send(sock, pkt, len, 0); + if (len < 0) + info("Error %s(%d)", strerror(errno), errno); + + info("%d bytes sent", len); + + if (cfg->fd != -1) { + len = unix_sendmsg_fd(sock, cfg->fd, pkt); + if (len < 0) + info("Error %s(%d)", strerror(errno), errno); + info("%d bytes sent", len); + } + + g_free(pkt); + close(sock); + return 0; +} diff --git a/audio/unix.h b/audio/unix.h index 4f3fc994..15da23ab 100644 --- a/audio/unix.h +++ b/audio/unix.h @@ -21,6 +21,9 @@ * */ +#include "ipc.h" + int unix_init(void); void unix_exit(void); +int unix_send_cfg(int sock, struct ipc_packet *pkt); |