diff options
| -rw-r--r-- | audio/headset.c | 124 | ||||
| -rw-r--r-- | audio/pcm_bluetooth.c | 20 | ||||
| -rw-r--r-- | audio/unix.c | 54 | 
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;  	} | 
