[PATCH BlueZ 4/4] AVRCP: Response for VolumeChanged Notification

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Vani Patel <vani.patel@xxxxxxxxxxxxxx>

Handling of interim and changed response for
VolumeChanged notification.
---
 audio/avctp.c |   18 ++++++++----------
 audio/avrcp.c |   21 +++++++++++++++++++++
 audio/avrcp.h |    1 +
 audio/media.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/audio/avctp.c b/audio/avctp.c
index 0cbd114..5cc5e34 100755
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -403,7 +403,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 	uint8_t buf[1024], *operands, code, subunit;
 	struct avctp_header *avctp;
 	struct avc_header *avc;
-	int ret, packet_size, operand_count, sock;
+	int ret, packet_size, operand_count, sock, avrcp_packet_length=0;
 	struct avctp_pdu_handler *handler;
 
 	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
@@ -448,9 +448,6 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 			avc->code, avc->subunit_type, avc->subunit_id,
 			avc->opcode, operand_count);
 
-	if (avctp->cr == AVCTP_RESPONSE)
-		return TRUE;
-
 	packet_size = AVCTP_HEADER_LENGTH + AVC_HEADER_LENGTH;
 	avctp->cr = AVCTP_RESPONSE;
 
@@ -476,19 +473,20 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 	code = avc->code;
 	subunit = avc->subunit_type;
 
-	packet_size += handler->cb(session, avctp->transaction, &code,
+	avrcp_packet_length = handler->cb(session, avctp->transaction, &code,
 					&subunit, operands, operand_count,
 					handler->user_data);
-
+	packet_size += avrcp_packet_length;
 	avc->code = code;
 	avc->subunit_type = subunit;
 
 done:
-	ret = write(sock, buf, packet_size);
-	if (ret != packet_size)
-		goto failed;
+	if (avrcp_packet_length == 0)
+		return TRUE;
 
-	return TRUE;
+	ret = write(sock, buf, packet_size);
+	if (ret == packet_size)
+		return TRUE;
 
 failed:
 	DBG("AVCTP session %p got disconnected", session);
diff --git a/audio/avrcp.c b/audio/avrcp.c
index b11dc21..8b0d574 100755
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1031,6 +1031,18 @@ err:
 	return AVC_CTYPE_REJECTED;
 }
 
+static uint8_t avrcp_handle_volume_changed (struct avrcp_player *player,
+						struct avrcp_header *pdu,
+						uint8_t transaction)
+{
+	uint8_t abs_volume = pdu->params[1] & 0x7F;
+	abs_volume = (abs_volume * 100)/127;
+
+	if(player->cb->set_volume != NULL)
+		player->cb->set_volume(abs_volume, player->dev, player->user_data);
+
+	return 0;
+}
 
 static struct pdu_handler {
 	uint8_t pdu_id;
@@ -1089,6 +1101,13 @@ static size_t handle_vendordep_pdu(struct avctp *session, uint8_t transaction,
 	DBG("AVRCP PDU 0x%02X, company 0x%06X len 0x%04X",
 			pdu->pdu_id, company_id, pdu->params_len);
 
+	if (pdu->pdu_id == AVRCP_REGISTER_NOTIFICATION) {
+		if (pdu->params[0] == AVRCP_EVENT_VOLUME_CHANGED)
+			return avrcp_handle_volume_changed(player, pdu, transaction);
+		else 
+			return 0;
+	}
+
 	pdu->packet_type = 0;
 	pdu->rsvd = 0;
 
@@ -1183,6 +1202,8 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
 		break;
 	case AVCTP_STATE_CONNECTING:
 		player->session = avctp_connect(&dev->src, &dev->dst);
+		if (!player->dev)
+			player->dev = dev;
 
 		if (!player->handler)
 			player->handler = avctp_register_pdu_handler(
diff --git a/audio/avrcp.h b/audio/avrcp.h
index 21cbc5c..31e004e 100755
--- a/audio/avrcp.h
+++ b/audio/avrcp.h
@@ -84,6 +84,7 @@ struct avrcp_player_cb {
 	GList *(*list_metadata) (void *user_data);
 	uint8_t (*get_status) (void *user_data);
 	uint32_t (*get_position) (void *user_data);
+	void (*set_volume) (uint8_t volume, struct audio_device *dev, void *user_data);
 };
 
 int avrcp_register(DBusConnection *conn, const bdaddr_t *src, GKeyFile *config);
diff --git a/audio/media.c b/audio/media.c
index 680f5a4..ebac291 100755
--- a/audio/media.c
+++ b/audio/media.c
@@ -1343,6 +1343,56 @@ static uint32_t get_position(void *user_data)
 	return mp->position + sec * 1000 + msec;
 }
 
+static void set_volume(uint8_t volume, struct audio_device *dev, void *user_data)
+{
+	struct media_player *mp = user_data;
+	DBusMessage *msg;
+	DBusMessageIter iter, value;
+	const char *property = "Volume";
+
+	GSList *l;
+	if (mp->volume == volume)
+		return;
+
+	mp->volume = volume;
+
+	for (l = mp->adapter->endpoints; l; l = l->next) {
+
+		struct media_endpoint *endpoint;
+		struct media_transport *transport;
+
+		if (l->data == NULL)
+			continue;
+
+		endpoint = l->data;
+		transport = find_device_transport(endpoint, dev);
+		
+		if (transport == NULL)
+			continue;
+
+		const char *path = media_transport_get_path(transport);
+		msg = dbus_message_new_method_call("org.bluez",
+							path,
+							MEDIA_TRANSPORT_INTERFACE,
+							"SetProperty");
+		if (!msg) {
+			DBG ( "Unable to allocate new.PropertyChanged msg\n");
+			continue ;
+		}
+
+		dbus_message_iter_init_append(msg, &iter);
+		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
+		dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BYTE_AS_STRING, &value);
+		dbus_message_iter_append_basic(&value, DBUS_TYPE_BYTE, &volume);
+		dbus_message_iter_close_container(&iter, &value);
+		
+		if (!dbus_connection_send(media_transport_get_conn(transport),msg,NULL))
+			continue;
+	}
+
+	register_volume_notification (avrcp_get_session(mp->player));
+}
+
 static struct avrcp_player_cb player_cb = {
 	.get_setting = get_setting,
 	.set_setting = set_setting,
@@ -1350,7 +1400,8 @@ static struct avrcp_player_cb player_cb = {
 	.get_uid = get_uid,
 	.get_metadata = get_metadata,
 	.get_position = get_position,
-	.get_status = get_status
+	.get_status = get_status,
+	.set_volume = set_volume
 };
 
 static void media_player_exit(DBusConnection *connection, void *user_data)
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux