[RFC : PATCH] - AVRCP 1.4 AbsoluteVolume

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

 



Hi All,

I would like to propose this patch for the implementation of Absolute Volume functionality.
When CT sends SetAbsoluteVolume request, a DBus call is made to the player to change the value of its property - volume.
This value is saved in the media_player instance so that it can be sent for Interim response for VolumeChanged Notification.
Your comments shall be appreciated.

>From 9863d379f3f39faf28105f9ad222acef65765d3d Mon Sep 17 00:00:00 2001
From: Vani Patel <vani.patel@xxxxxxxxxxxxxx>
Date: Mon, 27 Feb 2012 12:53:53 +0530
Subject: [PATCH] Absolute Volume Functions Implemented.

---
 audio/avrcp.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 audio/avrcp.h |    3 +++
 audio/media.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 108 insertions(+), 1 deletions(-)

diff --git a/audio/avrcp.c b/audio/avrcp.c
index c9ec314..70ebf8e 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -63,6 +63,8 @@
 #define E_INVALID_PARAM		0x01
 #define E_PARAM_NOT_FOUND	0x02
 #define E_INTERNAL		0x03
+#define E_NO_ERR		0x04
+#define E_NO_AVAIL_PLAYER	0x15
 
 /* Packet types */
 #define AVRCP_PACKET_TYPE_SINGLE	0x00
@@ -85,10 +87,12 @@
 #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 MAX_ABSOLUTE_VOLUME	255
 
 enum battery_status {
 	BATTERY_STATUS_NORMAL =		0,
@@ -387,6 +391,10 @@ int avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data)
 	case AVRCP_EVENT_TRACK_REACHED_START:
 		size = 1;
 		break;
+	case AVRCP_EVENT_VOLUME_CHANGED:
+ 		size = 2;
+ 		memcpy(&pdu->params[1], data, sizeof(uint8_t));
+ 		break;
 	default:
 		error("Unknown event %u", id);
 		return -EINVAL;
@@ -884,6 +892,7 @@ static uint8_t avrcp_handle_register_notification(struct avrcp_player *player,
 {
 	uint16_t len = ntohs(pdu->params_len);
 	uint64_t uid;
+	uint8_t volume=0;
 
 	/*
 	 * 1 byte for EventID, 4 bytes for Playback interval but the latest
@@ -909,6 +918,11 @@ static uint8_t avrcp_handle_register_notification(struct avrcp_player *player,
 	case AVRCP_EVENT_TRACK_REACHED_START:
 		len = 1;
 		break;
+ 	case AVRCP_EVENT_VOLUME_CHANGED:
+ 		len = 2;
+ 		volume = player->cb->get_volume(player->user_data);
+ 		memcpy(&pdu->params[1], &volume, sizeof(uint8_t));
+ 		break;
 	default:
 		/* All other events are not supported yet */
 		goto err;
@@ -994,6 +1008,40 @@ err:
 	return AVC_CTYPE_REJECTED;
 }
 
+static uint8_t avrcp_set_absolute_volume(struct avrcp_player *player,
+ 						struct avrcp_header *pdu,
+ 						uint8_t transaction)
+{
+ 	uint16_t len = ntohs(pdu->params_len);
+ 	uint8_t abs_volume = 0;
+ 	if (len != 1){
+ 		pdu->params[0] = E_PARAM_NOT_FOUND;
+ 		DBG("Param not Found \n");
+ 		goto err;
+ 	}
+ /*	if (NULL == addressed_player) {
+ 		status = E_NO_AVAIL_PLAYER;
+ 		goto err;
+ 	}
+ */  /*This shall be addressed once AddressedPlayer is implemented */
+ 
+ 	abs_volume = pdu->params[0];
+ 	if (abs_volume > MAX_ABSOLUTE_VOLUME){
+ 		pdu->params[0] = E_INVALID_PARAM;
+ 		goto err;
+ 	}
+ 
+ 	player->cb->set_volume(abs_volume, player->user_data);
+ 	pdu->params[0] = abs_volume;
+ 	pdu->params_len = htons(len);
+ 	return AVC_CTYPE_ACCEPTED;
+ 
+ 	err:
+ 	pdu->params_len = htons(1);
+ 	return AVC_CTYPE_REJECTED;
+ 
+}
 
 static struct pdu_handler {
 	uint8_t pdu_id;
@@ -1030,6 +1078,8 @@ static struct pdu_handler {
 					avrcp_handle_request_continuing },
 		{ AVRCP_ABORT_CONTINUING, AVC_CTYPE_CONTROL,
 					avrcp_handle_abort_continuing },
+		{ AVRCP_SET_ABSOLUTE_VOLUME, AVC_CTYPE_CONTROL,
+ 					avrcp_set_absolute_volume },
 		{ },
 };
 
diff --git a/audio/avrcp.h b/audio/avrcp.h
index fb64f3b..1df6103 100644
--- a/audio/avrcp.h
+++ b/audio/avrcp.h
@@ -73,6 +73,7 @@
 #define AVRCP_EVENT_TRACK_CHANGED	0x02
 #define AVRCP_EVENT_TRACK_REACHED_END	0x03
 #define AVRCP_EVENT_TRACK_REACHED_START	0x04
+#define AVRCP_EVENT_VOLUME_CHANGED	0x0d
 #define AVRCP_EVENT_LAST		AVRCP_EVENT_TRACK_REACHED_START
 
 struct avrcp_player_cb {
@@ -83,6 +84,8 @@ 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, void *user_data);
+ 	uint8_t (*get_volume)(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 c0fd0c3..738adbf 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -102,6 +102,7 @@ struct media_player {
 	guint			track_watch;
 	uint8_t			status;
 	uint32_t		position;
+	uint8_t         	volume;
 	GTimer			*timer;
 };
 
@@ -1255,6 +1256,36 @@ static uint32_t get_position(void *user_data)
 	return mp->position + sec * 1000 + msec;
 }
 
+static uint8_t get_volume(void *user_data)
+{
+ 	struct media_player *mp = user_data;
+ 	return mp->volume;
+}
+
+static void set_volume(uint16_t volume, void *user_data)
+{
+ 	struct media_player *mp = user_data;
+ 	DBusMessage *msg; 
+ 	DBusMessageIter iter, var;
+ 	const char *property = "InputGain";
+ 	msg = dbus_message_new_method_call(mp->sender, mp->path,
+ 						MEDIA_PLAYER_INTERFACE,
+ 						"SetProperty");
+ 	if (msg == NULL) {
+ 		DBG("Couldn't allocate D-Bus message");
+ 		return ;
+ 	}
+ 	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,
+ 						&var);
+ 	dbus_message_iter_append_basic(&var, DBUS_TYPE_BYTE, &volume);
+ 	dbus_message_iter_close_container(&iter, &var);
+ 	g_dbus_send_message(mp->adapter->conn, msg);
+ 	return ;	
+}
+
 static struct avrcp_player_cb player_cb = {
 	.get_setting = get_setting,
 	.set_setting = set_setting,
@@ -1262,7 +1293,9 @@ 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,
+ 	.get_volume = get_volume
 };
 
 static void media_player_exit(DBusConnection *connection, void *user_data)
@@ -1338,6 +1371,24 @@ static gboolean set_position(struct media_player *mp, DBusMessageIter *iter)
 	return TRUE;
 }
 
+static gboolean set_media_volume(struct media_player *mp, DBusMessageIter *iter)
+{
+ 	uint8_t *value;
+ 	int val;
+ 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BYTE)
+ 		return FALSE;
+ 
+ 	dbus_message_iter_get_basic(iter, &value);
+ 
+ 	if (mp->volume == *value)
+ 		return TRUE;
+ 
+ 	mp->volume = *value;
+ 	avrcp_player_event(mp->player, AVRCP_EVENT_VOLUME_CHANGED, value);
+ 
+ 	return TRUE;
+}
+
 static gboolean set_property(struct media_player *mp, const char *key,
 							DBusMessageIter *entry)
 {
@@ -1355,6 +1406,9 @@ static gboolean set_property(struct media_player *mp, const char *key,
 
 	if (strcasecmp(key, "Position") == 0)
 		return set_position(mp, &var);
+	
+	if (strcasecmp(key, "Volume") == 0)
+ 		return set_media_volume(mp, &var);
 
 	attr = attr_to_val(key);
 	if (attr < 0)
-- 
1.7.5.4

Vani
--
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