summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2007-06-29 23:19:36 +0000
committerLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2007-06-29 23:19:36 +0000
commitdf235d1f395b10654024979180c778777bd50c71 (patch)
treed12a132c9921e5e50a661a73b752b01f71034b28
parentb57f22a505f7c46662bfd5900df38dd68099df2c (diff)
Handle state machine in a better way and add disconnect code for plugin.
-rw-r--r--audio/headset.c124
-rw-r--r--audio/pcm_bluetooth.c20
-rw-r--r--audio/unix.c54
3 files changed, 114 insertions, 84 deletions
diff --git a/audio/headset.c b/audio/headset.c
index 28f6ac1d..ca24e93b 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -181,11 +181,6 @@ static void close_sco(struct device *device)
g_io_channel_close(hs->sco);
g_io_channel_unref(hs->sco);
hs->sco = NULL;
- hs->state = HEADSET_STATE_CONNECTED;
- dbus_connection_emit_signal(device->conn, device->path,
- AUDIO_HEADSET_INTERFACE,
- "Stopped",
- DBUS_TYPE_INVALID);
}
}
@@ -286,8 +281,7 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
return TRUE;
failed:
- close_sco(device);
- headset_close_rfcomm(device);
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
return FALSE;
}
@@ -304,7 +298,7 @@ static gboolean sco_cb(GIOChannel *chan, GIOCondition cond,
error("Audio connection got disconnected");
- close_sco(device);
+ headset_set_state(device, HEADSET_STATE_CONNECTED);
return FALSE;
}
@@ -359,9 +353,8 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
{
struct headset *hs;
struct pending_connect *c;
- int ret, sk, err, flags;
+ int ret, sk, err;
socklen_t len;
- char str[13];
if (cond & G_IO_NVAL)
return FALSE;
@@ -390,29 +383,12 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
hs->sco = chan;
c->io = NULL;
- flags = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-
- g_io_add_watch(hs->sco, flags, (GIOFunc) sco_cb, device);
-
g_slist_foreach(hs->pending, (GFunc)pending_connect_ok, device);
g_slist_free(hs->pending);
hs->pending = NULL;
fcntl(sk, F_SETFL, 0);
- hs->state = HEADSET_STATE_PLAYING;
- dbus_connection_emit_signal(device->conn, device->path,
- AUDIO_HEADSET_INTERFACE,
- "Playing", DBUS_TYPE_INVALID);
-
- if (hs->sp_gain >= 0) {
- snprintf(str, sizeof(str) - 1, "\r\n+VGS=%u\r\n", hs->sp_gain);
- headset_send(device->headset, str);
- }
-
- if (hs->mic_gain >= 0) {
- snprintf(str, sizeof(str) - 1, "\r\n+VGM=%u\r\n", hs->sp_gain);
- headset_send(device->headset, str);
- }
+ headset_set_state(device, HEADSET_STATE_PLAYING);
return FALSE;
@@ -420,7 +396,7 @@ failed:
g_slist_foreach(hs->pending, (GFunc)pending_connect_failed, device);
g_slist_free(hs->pending);
hs->pending = NULL;
- hs->state = HEADSET_STATE_CONNECTED;
+ headset_set_state(device, HEADSET_STATE_CONNECTED);
return FALSE;
}
@@ -486,7 +462,7 @@ static int sco_connect(struct device *device, struct pending_connect *c)
do_callback = TRUE;
}
- hs->state = HEADSET_STATE_PLAY_IN_PROGRESS;
+ headset_set_state(device, HEADSET_STATE_PLAY_IN_PROGRESS);
if (!g_slist_find(hs->pending, c))
hs->pending = g_slist_append(hs->pending, c);
@@ -530,12 +506,8 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
hs->rfcomm = chan;
c->io = NULL;
- hs->state = HEADSET_STATE_CONNECTED;
- dbus_connection_emit_signal(device->conn, device->path,
- AUDIO_HEADSET_INTERFACE,
- "Connected", DBUS_TYPE_INVALID);
+ headset_set_state(device, HEADSET_STATE_CONNECTED);
- device_store(device, FALSE);
debug("Connected to %s", hs_address);
g_io_add_watch(chan, G_IO_IN | G_IO_ERR | G_IO_HUP| G_IO_NVAL,
@@ -558,9 +530,9 @@ failed:
g_slist_free(hs->pending);
hs->pending = NULL;
if (hs->rfcomm)
- hs->state = HEADSET_STATE_CONNECTED;
+ headset_set_state(device, HEADSET_STATE_CONNECTED);
else
- hs->state = HEADSET_STATE_DISCONNECTED;
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
return FALSE;
}
@@ -676,7 +648,7 @@ failed:
g_slist_foreach(hs->pending, (GFunc)pending_connect_failed, device);
g_slist_free(hs->pending);
hs->pending = NULL;
- hs->state = HEADSET_STATE_DISCONNECTED;
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
device_finish_sdp_transaction(device);
}
@@ -778,7 +750,7 @@ failed:
g_slist_foreach(hs->pending, (GFunc)pending_connect_failed, device);
g_slist_free(hs->pending);
hs->pending = NULL;
- hs->state = HEADSET_STATE_DISCONNECTED;
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
}
static int get_handles(struct device *device)
@@ -809,7 +781,7 @@ static int get_handles(struct device *device)
DBUS_TYPE_STRING, &hs_svc,
DBUS_TYPE_INVALID);
- hs->state = HEADSET_STATE_CONNECT_IN_PROGRESS;
+ headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS);
if (!dbus_connection_send_with_reply(device->conn, msg, &pending, -1)) {
error("Sending GetRemoteServiceHandles failed");
dbus_message_unref(msg);
@@ -919,18 +891,10 @@ static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- switch(hs->state) {
- case HEADSET_STATE_PLAYING:
- case HEADSET_STATE_PLAY_IN_PROGRESS:
- close_sco(device);
- break;
- case HEADSET_STATE_CONNECTED:
- case HEADSET_STATE_CONNECT_IN_PROGRESS:
- case HEADSET_STATE_DISCONNECTED:
+ if (hs->state < HEADSET_STATE_PLAY_IN_PROGRESS)
return err_not_connected(conn, msg);
- break;
- }
+ headset_set_state(device, HEADSET_STATE_CONNECTED);
send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
@@ -970,19 +934,10 @@ static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- switch(hs->state) {
- case HEADSET_STATE_PLAYING:
- case HEADSET_STATE_PLAY_IN_PROGRESS:
- close_sco(device);
- case HEADSET_STATE_CONNECTED:
- case HEADSET_STATE_CONNECT_IN_PROGRESS:
- headset_close_rfcomm(device);
- break;
- case HEADSET_STATE_DISCONNECTED:
+ if (hs->state == HEADSET_STATE_DISCONNECTED)
return err_not_connected(conn, msg);
- break;
- }
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
ba2str(&device->dst, hs_address);
info("Disconnected from %s, %s", hs_address, device->path);
@@ -1500,11 +1455,6 @@ int headset_close_rfcomm(void *device)
g_io_channel_close(hs->rfcomm);
g_io_channel_unref(hs->rfcomm);
hs->rfcomm = NULL;
- hs->state = HEADSET_STATE_DISCONNECTED;
- dbus_connection_emit_signal(dev->conn, dev->path,
- AUDIO_HEADSET_INTERFACE,
- "Disconnected",
- DBUS_TYPE_INVALID);
}
hs->data_start = 0;
@@ -1517,32 +1467,64 @@ void headset_set_state(void *device, headset_state_t state)
{
struct device *dev = (struct device *) device;
struct headset *hs = dev->headset;
+ char str[13];
+
+ if (hs->state == state)
+ return;
switch(state) {
case HEADSET_STATE_DISCONNECTED:
+ close_sco(device);
+ headset_close_rfcomm(device);
+ dbus_connection_emit_signal(dev->conn, dev->path,
+ AUDIO_HEADSET_INTERFACE,
+ "Disconnected",
+ DBUS_TYPE_INVALID);
+ break;
case HEADSET_STATE_CONNECT_IN_PROGRESS:
break;
case HEADSET_STATE_CONNECTED:
- if (hs->rfcomm) {
- char hs_address[18];
-
+ if (hs->state < state) {
g_io_add_watch(hs->rfcomm,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
(GIOFunc) rfcomm_io_cb, device);
- ba2str(&((struct device *) device)->dst, hs_address);
-
dbus_connection_emit_signal(dev->conn, dev->path,
AUDIO_HEADSET_INTERFACE,
"Connected",
DBUS_TYPE_INVALID);
}
+ else {
+ close_sco(device);
+ dbus_connection_emit_signal(dev->conn, dev->path,
+ AUDIO_HEADSET_INTERFACE,
+ "Stopped",
+ DBUS_TYPE_INVALID);
+ }
break;
case HEADSET_STATE_PLAY_IN_PROGRESS:
+ break;
case HEADSET_STATE_PLAYING:
+ g_io_add_watch(hs->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) sco_cb, device);
+
+ dbus_connection_emit_signal(dev->conn, dev->path,
+ AUDIO_HEADSET_INTERFACE,
+ "Playing", DBUS_TYPE_INVALID);
+
+ if (hs->sp_gain >= 0) {
+ snprintf(str, sizeof(str) - 1, "\r\n+VGS=%u\r\n", hs->sp_gain);
+ headset_send(hs, str);
+ }
+
+ if (hs->mic_gain >= 0) {
+ snprintf(str, sizeof(str) - 1, "\r\n+VGM=%u\r\n", hs->sp_gain);
+ headset_send(hs, str);
+ }
break;
}
+ debug("State changed %s: %d -> %d", dev->path, hs->state, state);
hs->state = state;
}
diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c
index f95dcc9c..71daab4f 100644
--- a/audio/pcm_bluetooth.c
+++ b/audio/pcm_bluetooth.c
@@ -86,6 +86,26 @@ static snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
static void bluetooth_exit(struct bluetooth_data *data)
{
+ int ret, len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_status);
+ struct ipc_packet *pkt;
+ struct ipc_data_status *status;
+
+ DBG("Sending PKT_TYPE_STATUS_REQ...");
+
+ if ((pkt = malloc(len)) == 0)
+ goto done;
+
+ memset(pkt, 0, len);
+ pkt->type = PKT_TYPE_STATUS_REQ;
+ pkt->role = PKT_ROLE_NONE;
+ pkt->error = PKT_ERROR_NONE;
+
+ status = (struct ipc_data_status *) pkt->data;
+ status->status = STATUS_DISCONNECTED;
+
+ if ((ret = send(data->sock, pkt, len, 0)) < 0)
+ DBG("OK");
+done:
if (data == NULL)
return;
diff --git a/audio/unix.c b/audio/unix.c
index a4b8f2c4..0f6c53aa 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -75,13 +75,49 @@ static int unix_sendmsg_fd(int sock, int fd, struct ipc_packet *pkt)
return sendmsg(sock, &msgh, MSG_NOSIGNAL);
}
-static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data)
+static void cfg_event(int clisk, struct ipc_packet *pkt)
+{
+ struct ipc_data_cfg *cfg = (struct ipc_data_cfg *) pkt->data;
+ struct device *device;
+
+ memset(cfg, 0, sizeof(struct ipc_data_cfg));
+
+ if ((device = manager_default_device())) {
+ if (device->headset)
+ headset_get_config(device, clisk, pkt);
+ }
+ else
+ cfg->fd = -1;
+
+ if (cfg->fd != 0)
+ unix_send_cfg(clisk, pkt);
+}
+
+static void ctl_event(int clisk, struct ipc_packet *pkt)
+{
+}
+
+static void status_event(int clisk, struct ipc_packet *pkt)
{
+ struct ipc_data_status *status = (struct ipc_data_status *) pkt->data;
struct device *device;
+
+ if (status->status == STATUS_DISCONNECTED) {
+ if (!(device = manager_default_device()))
+ return;
+
+ if (device->headset)
+ headset_set_state(device, HEADSET_STATE_DISCONNECTED);
+ }
+
+ g_free(pkt);
+}
+
+static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
struct sockaddr_un addr;
socklen_t addrlen;
struct ipc_packet *pkt;
- struct ipc_data_cfg *cfg;
int sk, clisk, len;
debug("chan %p cond %td data %p", chan, cond, data);
@@ -114,23 +150,15 @@ static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data)
switch (pkt->type) {
case PKT_TYPE_CFG_REQ:
info("Package PKT_TYPE_CFG_REQ:%u", pkt->role);
-
- cfg = (struct ipc_data_cfg *) pkt->data;
-
- memset(cfg, 0, sizeof(struct ipc_data_cfg));
- if ((device = manager_default_device())) {
- if (device->headset)
- headset_get_config(device, clisk, pkt);
- }
-
- if (cfg->fd != 0)
- unix_send_cfg(clisk, pkt);
+ cfg_event(clisk, pkt);
break;
case PKT_TYPE_STATUS_REQ:
info("Package PKT_TYPE_STATUS_REQ");
+ status_event(clisk, pkt);
break;
case PKT_TYPE_CTL_REQ:
info("Package PKT_TYPE_CTL_REQ");
+ ctl_event(clisk, pkt);
break;
}