summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/audio-api.txt8
-rw-r--r--audio/headset.c145
-rw-r--r--audio/headset.h4
-rw-r--r--audio/main.c2
-rw-r--r--audio/manager.c321
-rw-r--r--audio/manager.h2
-rw-r--r--audio/unix.c60
-rw-r--r--audio/unix.h3
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);