Diff between ea42bc7391ae5ea10fddb05f97c4c6cd698f340e and 177d7aea76385263fe8c57fa32f73bc6263d9d31

Changed Files

File Additions Deletions Status
audio/control.c +71 -0 modified

Full Patch

diff --git a/audio/control.c b/audio/control.c
index feb6930..187c3f1 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -121,6 +121,7 @@
 #define AVRCP_GET_PLAYER_VALUE_TEXT	0x16
 #define AVRCP_DISPLAYABLE_CHARSET	0x17
 #define AVRCP_CT_BATTERY_STATUS		0x18
+#define AVRCP_GET_PLAY_STATUS		0x30
 
 /* Capabilities for AVRCP_GET_CAPABILITIES pdu */
 #define CAP_COMPANY_ID		0x02
@@ -694,6 +695,30 @@ static const char *battery_status_to_str(enum battery_status status)
 	return NULL;
 }
 
+static void mp_get_playback_status(struct media_player *mp, uint8_t *status,
+					uint32_t *elapsed, uint32_t *track_len)
+{
+	if (status)
+		*status = mp->status;
+	if (track_len)
+		*track_len = mp->mi.track_len;
+
+	if (!elapsed)
+		return;
+
+	*elapsed = mp->mi.elapsed;
+
+	if (mp->status == PLAY_STATUS_PLAYING) {
+		double timedelta = g_timer_elapsed(mp->timer, NULL);
+		uint32_t sec, msec;
+
+		sec = (uint32_t) timedelta;
+		msec = (uint32_t)((timedelta - sec) * 1000);
+
+		*elapsed += sec * 1000 + msec;
+	}
+}
+
 static void mp_set_playback_status(struct control *control, uint8_t status,
 							uint32_t elapsed)
 {
@@ -989,6 +1014,39 @@ err:
 	return -EINVAL;
 }
 
+static int avrcp_handle_get_play_status(struct control *control,
+						struct avrcp_spec_avc_pdu *pdu)
+{
+	uint16_t len = ntohs(pdu->params_len);
+	uint32_t elapsed;
+	uint32_t track_len;
+	uint8_t status;
+
+	if (len != 0) {
+		pdu->params[0] = E_INVALID_PARAM;
+		return -EINVAL;
+	}
+
+	if (control->mp) {
+		mp_get_playback_status(control->mp, &status,
+							&elapsed, &track_len);
+		track_len = htonl(track_len);
+		elapsed = htonl(elapsed);
+	} else {
+		track_len = 0xFFFFFFFF;
+		elapsed = 0xFFFFFFFF;
+		status = PLAY_STATUS_ERROR;
+	}
+
+	memcpy(&pdu->params[0], &track_len, 4);
+	memcpy(&pdu->params[4], &elapsed, 4);
+	pdu->params[8] = status;
+
+	pdu->params_len = htons(9);
+
+	return 9;
+}
+
 /* handle vendordep pdu inside an avctp packet */
 static int handle_vendordep_pdu(struct control *control,
 					struct avrcp_header *avrcp,
@@ -1129,6 +1187,19 @@ static int handle_vendordep_pdu(struct control *control,
 		avrcp->code = CTYPE_STABLE;
 
 		break;
+	case AVRCP_GET_PLAY_STATUS:
+		if (avrcp->code != CTYPE_STATUS) {
+			pdu->params[0] = E_INVALID_COMMAND;
+			goto err_metadata;
+		}
+
+		len = avrcp_handle_get_play_status(control, pdu);
+		if (len < 0)
+			goto err_metadata;
+
+		avrcp->code = CTYPE_STABLE;
+
+		break;
 	default:
 		/* Invalid pdu_id */
 		pdu->params[0] = E_INVALID_COMMAND;