[PATCH BlueZ 3/3] AVRCP: Implement SetAbsoluteVolume

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

 



From: Vani Patel <vani.patel@xxxxxxxxxxxxxx>

Register for PropertyChanged on
MediaTransport. On "Volume" changed
send SetAbsoluteVolume
---
 audio/avctp.c |    4 ++--
 audio/avctp.h |    2 +-
 audio/avrcp.c |   37 ++++++++++++++++++++++++++++++++++++-
 audio/avrcp.h |    1 +
 audio/media.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 4 deletions(-)
 mode change 100644 => 100755 audio/avctp.c
 mode change 100644 => 100755 audio/avctp.h
 mode change 100644 => 100755 audio/avrcp.c
 mode change 100644 => 100755 audio/avrcp.h
 mode change 100644 => 100755 audio/media.c

diff --git a/audio/avctp.c b/audio/avctp.c
old mode 100644
new mode 100755
index 5161703..c5fbc1b
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -892,7 +892,7 @@ int avctp_send_passthrough(struct avctp *session, uint8_t op)
 
 int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
-				uint8_t *operands, size_t operand_count)
+				uint8_t *operands, size_t operand_count, uint8_t cr)
 {
 	uint8_t *buf;
 	struct avctp_header *avctp;
@@ -914,7 +914,7 @@ int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
 
 	avctp->transaction = transaction;
 	avctp->packet_type = AVCTP_PACKET_SINGLE;
-	avctp->cr = AVCTP_RESPONSE;
+	avctp->cr = cr;
 	avctp->pid = htons(AV_REMOTE_SVCLASS_ID);
 
 	avc->code = code;
diff --git a/audio/avctp.h b/audio/avctp.h
old mode 100644
new mode 100755
index 9727485..0b9ff37
--- a/audio/avctp.h
+++ b/audio/avctp.h
@@ -96,4 +96,4 @@ gboolean avctp_unregister_pdu_handler(unsigned int id);
 int avctp_send_passthrough(struct avctp *session, uint8_t op);
 int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
 				uint8_t code, uint8_t subunit,
-				uint8_t *operands, size_t operand_count);
+				uint8_t *operands, size_t operand_count, uint8_t cr);
diff --git a/audio/avrcp.c b/audio/avrcp.c
old mode 100644
new mode 100755
index 9ec0730..2b25253
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -84,10 +84,13 @@
 #define AVRCP_REGISTER_NOTIFICATION	0x31
 #define AVRCP_REQUEST_CONTINUING	0x40
 #define AVRCP_ABORT_CONTINUING		0x41
+#define AVRCP_SET_ABSOLUTE_VOLUME	0x50
 
 /* Capabilities for AVRCP_GET_CAPABILITIES pdu */
 #define CAP_COMPANY_ID		0x02
 #define CAP_EVENTS_SUPPORTED	0x03
+#define COMMAND		0
+#define RESPONSE		1
 
 enum battery_status {
 	BATTERY_STATUS_NORMAL =		0,
@@ -164,6 +167,7 @@ static unsigned int avctp_id = 0;
 static uint32_t company_ids[] = {
 	IEEEID_BTSIG,
 };
+static uint8_t request_transaction = 0;
 
 static sdp_record_t *avrcp_ct_record(void)
 {
@@ -395,7 +399,7 @@ int avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data)
 
 	err = avctp_send_vendordep(player->session, player->transaction_events[id],
 					AVC_CTYPE_CHANGED, AVC_SUBUNIT_PANEL,
-					buf, size + AVRCP_HEADER_LENGTH);
+					buf, size + AVRCP_HEADER_LENGTH, RESPONSE);
 	if (err < 0)
 		return err;
 
@@ -405,6 +409,37 @@ int avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data)
 	return 0;
 }
 
+int avrcp_player_set_volume(struct avrcp_player *player, void *data)
+{
+	uint8_t buf[AVRCP_HEADER_LENGTH + 9];
+	struct avrcp_header *pdu = (void *) buf;
+	uint16_t size = 1;
+	int err;
+	uint8_t volume = 0;
+
+	if (player->session == NULL)
+		return -ENOTCONN;
+
+	memset(buf, 0, sizeof(buf));
+
+	set_company_id(pdu->company_id, IEEEID_BTSIG);
+
+	volume = *((uint8_t *)data);
+	volume = 1.27 * volume;
+
+	pdu->pdu_id = AVRCP_SET_ABSOLUTE_VOLUME;
+	pdu->params_len = htons(size);
+	pdu->params[0] = volume;
+
+	err = avctp_send_vendordep(player->session, request_transaction++,
+					AVC_CTYPE_CONTROL, AVC_SUBUNIT_PANEL,
+					buf, size + AVRCP_HEADER_LENGTH, COMMAND);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
 static uint16_t player_write_media_attribute(struct avrcp_player *player,
 						uint32_t id, uint8_t *buf,
 						uint16_t *pos,
diff --git a/audio/avrcp.h b/audio/avrcp.h
old mode 100644
new mode 100755
index 8a09546..58d555f
--- a/audio/avrcp.h
+++ b/audio/avrcp.h
@@ -98,5 +98,6 @@ struct avrcp_player *avrcp_register_player(const bdaddr_t *src,
 void avrcp_unregister_player(struct avrcp_player *player);
 
 int avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data);
+int avrcp_player_set_volume(struct avrcp_player *player, void *data);
 
 size_t avrcp_handle_vendor_reject(uint8_t *code, uint8_t *operands);
diff --git a/audio/media.c b/audio/media.c
old mode 100644
new mode 100755
index 61ec153..680f5a4
--- a/audio/media.c
+++ b/audio/media.c
@@ -55,6 +55,7 @@
 #define MEDIA_INTERFACE "org.bluez.Media"
 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint"
 #define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer"
+#define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport"
 
 #define REQUEST_TIMEOUT (3 * 1000)		/* 3 seconds */
 
@@ -101,8 +102,10 @@ struct media_player {
 	guint			watch;
 	guint			property_watch;
 	guint			track_watch;
+	guint                   volume_watch;
 	uint8_t			status;
 	uint32_t		position;
+	uint8_t			volume;
 	GTimer			*timer;
 };
 
@@ -1642,6 +1645,43 @@ static gboolean track_changed(DBusConnection *connection, DBusMessage *msg,
 	return TRUE;
 }
 
+static gboolean volume_changed(DBusConnection *connection, DBusMessage *msg,
+							void *user_data)
+{
+	struct media_player *mp = user_data;
+	DBusMessageIter iter, value;
+	uint8_t volume;
+	const char *property;
+
+	dbus_message_iter_init(msg, &iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
+		error("Unexpected signature in %s.%s signal",
+					dbus_message_get_interface(msg),
+					dbus_message_get_member(msg));
+		return FALSE;
+	}
+
+	dbus_message_iter_get_basic(&iter, &property);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+		return FALSE;
+
+	dbus_message_iter_recurse(&iter, &value);
+
+	if (g_strcmp0(property, "Volume") != 0)
+		return FALSE;
+
+	if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_BYTE)
+		return FALSE;
+
+	dbus_message_iter_get_basic(&value, &volume);
+	mp->volume = volume;
+	avrcp_player_set_volume(mp->player, &volume);
+
+	return TRUE;
+}
 static struct media_player *media_player_create(struct media_adapter *adapter,
 						const char *sender,
 						const char *path,
@@ -1668,6 +1708,11 @@ static struct media_player *media_player_create(struct media_adapter *adapter,
 						"TrackChanged",
 						track_changed,
 						mp, NULL);
+	mp->volume_watch = g_dbus_add_signal_watch(adapter->conn, sender,
+						path, MEDIA_TRANSPORT_INTERFACE,
+						"PropertyChanged",
+						volume_changed,
+						mp, NULL);
 	mp->player = avrcp_register_player(&adapter->src, &player_cb, mp,
 						media_player_free);
 	if (!mp->player) {
-- 
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