mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-01-26 06:07:53 +00:00
stream: Make capability device IDs an JSON object
Also change the encoding of the byte array to use hexadecimal encoding, i.e. the byte array [100, 200] in becomes "64c8".
This commit is contained in:
parent
8600721de0
commit
f2c4452e8d
@ -365,10 +365,13 @@ with. This can be used to reduce the amount of devices that are queried for form
|
||||
metadata, which can be a time consuming task, if devices needs to be woken up.
|
||||
|
||||
To achieve this, the consumer adds another \ref SPA_PARAM_PeerCapability item with the key
|
||||
\ref PW_CAPABILITY_DEVICE_IDS set to a string of base 64 encoded `dev_t` device IDs.
|
||||
\ref PW_CAPABILITY_DEVICE_IDS set to a JSON object describing what device IDs are supported.
|
||||
|
||||
This JSON object as of version 1 contains a single key "available-devices" that contain
|
||||
a list of hexadecimal encoded `dev_t` device IDs.
|
||||
|
||||
```
|
||||
char *device_ids = ...; /* Base 64 encoding of a dev_t. */.
|
||||
char *device_ids = "{\"available-devices\": [\"6464000000000000\",\"c8c8000000000000\"]}";
|
||||
&SPA_DICT_ITEMS(
|
||||
SPA_DICT_ITEM(PW_CAPABILITY_DEVICE_ID_NEGOTIATION, "1"),
|
||||
SPA_DICT_ITEM(PW_CAPABILITY_DEVICE_IDS, device_ids)));
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
/* PipeWire */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
static inline void base64_encode(const uint8_t *data, size_t len, char *enc, char pad)
|
||||
{
|
||||
static const char tab[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
size_t i;
|
||||
for (i = 0; i < len; i += 3) {
|
||||
uint32_t v;
|
||||
v = data[i+0] << 16;
|
||||
v |= (i+1 < len ? data[i+1] : 0) << 8;
|
||||
v |= (i+2 < len ? data[i+2] : 0);
|
||||
*enc++ = tab[(v >> (3*6)) & 0x3f];
|
||||
*enc++ = tab[(v >> (2*6)) & 0x3f];
|
||||
*enc++ = i+1 < len ? tab[(v >> (1*6)) & 0x3f] : pad;
|
||||
*enc++ = i+2 < len ? tab[(v >> (0*6)) & 0x3f] : pad;
|
||||
}
|
||||
*enc = '\0';
|
||||
}
|
||||
|
||||
static inline size_t base64_decode(const char *data, size_t len, uint8_t *dec)
|
||||
{
|
||||
uint8_t tab[] = {
|
||||
62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
|
||||
-1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
|
||||
-1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < len; i += 4) {
|
||||
uint32_t v;
|
||||
v = tab[data[i+0]-43] << (3*6);
|
||||
v |= tab[data[i+1]-43] << (2*6);
|
||||
v |= (data[i+2] == '=' ? 0 : tab[data[i+2]-43]) << (1*6);
|
||||
v |= (data[i+3] == '=' ? 0 : tab[data[i+3]-43]);
|
||||
dec[j++] = (v >> 16) & 0xff;
|
||||
if (data[i+2] != '=') dec[j++] = (v >> 8) & 0xff;
|
||||
if (data[i+3] != '=') dec[j++] = v & 0xff;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
60
src/examples/utils.h
Normal file
60
src/examples/utils.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* PipeWire */
|
||||
/* SPDX-FileCopyrightText: Copyright © 2026 Red Hat */
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
static inline char *
|
||||
encode_hex(const uint8_t *data, size_t size)
|
||||
{
|
||||
FILE *ms;
|
||||
char *encoded = NULL;
|
||||
size_t encoded_size = 0;
|
||||
size_t i;
|
||||
|
||||
ms = open_memstream(&encoded, &encoded_size);
|
||||
for (i = 0; i < size; i++) {
|
||||
fprintf(ms, "%02x", data[i]);
|
||||
}
|
||||
fclose(ms);
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
static inline int8_t
|
||||
ascii_hex_to_hex(uint8_t ascii_hex)
|
||||
{
|
||||
if (ascii_hex >= '0' && ascii_hex <= '9')
|
||||
return ascii_hex - '0';
|
||||
else if (ascii_hex >= 'a' && ascii_hex <= 'f')
|
||||
return ascii_hex - 'a' + 10;
|
||||
else if (ascii_hex >= 'A' && ascii_hex <= 'F')
|
||||
return ascii_hex - 'A' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
decode_hex(const char *encoded, uint8_t *data, size_t size)
|
||||
{
|
||||
size_t length;
|
||||
size_t i;
|
||||
|
||||
length = strlen(encoded);
|
||||
|
||||
if (size < (length / 2) * sizeof(uint8_t))
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
while (i < length) {
|
||||
int8_t top = ascii_hex_to_hex(encoded[i]);
|
||||
int8_t bottom = ascii_hex_to_hex(encoded[i + 1]);
|
||||
|
||||
if (top == -1 || bottom == -1)
|
||||
return -1;
|
||||
|
||||
uint8_t el = top << 4 | bottom;
|
||||
data[i / 2] = el;
|
||||
i += 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -29,7 +29,7 @@
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/capabilities.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* Comment out to test device ID negotation backward compatibility. */
|
||||
#define SUPPORT_DEVICE_ID_NEGOTIATION 1
|
||||
@ -372,46 +372,56 @@ collect_device_ids(struct data *data, const char *json)
|
||||
int len;
|
||||
const char *value;
|
||||
struct spa_json sub;
|
||||
char key[1024];
|
||||
|
||||
if ((len = spa_json_begin(&it, json, strlen(json), &value)) <= 0) {
|
||||
fprintf(stderr, "invalid device IDs value\n");
|
||||
return;
|
||||
}
|
||||
if (!spa_json_is_array(value, len)) {
|
||||
fprintf(stderr, "device IDs not array\n");
|
||||
if (!spa_json_is_object(value, len)) {
|
||||
fprintf(stderr, "device IDs not object\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spa_json_enter(&it, &sub);
|
||||
while ((len = spa_json_next(&sub, &value)) > 0) {
|
||||
char *string;
|
||||
union {
|
||||
dev_t device_id;
|
||||
uint8_t buffer[1024];
|
||||
} dec;
|
||||
while ((len = spa_json_object_next(&sub, key, sizeof(key), &value)) > 0) {
|
||||
struct spa_json devices_sub;
|
||||
|
||||
string = alloca(len + 1);
|
||||
|
||||
if (!spa_json_is_string(value, len)) {
|
||||
fprintf(stderr, "device ID not string\n");
|
||||
if (!spa_json_is_array(value, len)) {
|
||||
fprintf(stderr, "available-devices not array\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (spa_json_parse_string(value, len, string) <= 0) {
|
||||
fprintf(stderr, "invalid device ID string\n");
|
||||
return;
|
||||
spa_json_enter(&sub, &devices_sub);
|
||||
while ((len = spa_json_next(&devices_sub, &value)) > 0) {
|
||||
char *string;
|
||||
union {
|
||||
dev_t device_id;
|
||||
uint8_t buffer[1024];
|
||||
} dec;
|
||||
|
||||
string = alloca(len + 1);
|
||||
|
||||
if (!spa_json_is_string(value, len)) {
|
||||
fprintf(stderr, "device ID not string\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (spa_json_parse_string(value, len, string) <= 0) {
|
||||
fprintf(stderr, "invalid device ID string\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (decode_hex(string, dec.buffer, sizeof (dec.buffer)) < 0) {
|
||||
fprintf(stderr, "invalid device ID string\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "discovered device ID %u:%u\n",
|
||||
major(dec.device_id), minor(dec.device_id));
|
||||
|
||||
data->device_ids[data->n_device_ids++] = dec.device_id;
|
||||
}
|
||||
|
||||
if (base64_decode(string, strlen(string),
|
||||
(uint8_t *)&dec.device_id) < sizeof(dev_t)) {
|
||||
fprintf(stderr, "invalid device ID\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "discovered device ID %u:%u\n",
|
||||
major(dec.device_id), minor(dec.device_id));
|
||||
|
||||
data->device_ids[data->n_device_ids++] = dec.device_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <pipewire/capabilities.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* Comment out to test device ID negotation backward compatibility. */
|
||||
#define SUPPORT_DEVICE_ID_NEGOTIATION 1
|
||||
@ -784,17 +784,20 @@ int main(int argc, char *argv[])
|
||||
size_t i;
|
||||
|
||||
ms = open_memstream(&device_ids, &device_ids_size);
|
||||
fprintf(ms, "[");
|
||||
fprintf(ms, "{\"available-devices\": [");
|
||||
for (i = 0; i < SPA_N_ELEMENTS(devices); i++) {
|
||||
dev_t device_id = makedev(devices[i].major, devices[i].minor);
|
||||
char device_id_encoded[256];
|
||||
char *device_id_encoded;
|
||||
|
||||
device_id_encoded = encode_hex((const uint8_t *) &device_id, sizeof (device_id));
|
||||
|
||||
base64_encode((const uint8_t *) &device_id, sizeof (device_id), device_id_encoded, '\0');
|
||||
if (i > 0)
|
||||
fprintf(ms, ",");
|
||||
fprintf(ms, "\"%s\"", device_id_encoded);
|
||||
|
||||
free(device_id_encoded);
|
||||
}
|
||||
fprintf(ms, "]");
|
||||
fprintf(ms, "]}");
|
||||
fclose(ms);
|
||||
#endif /* SUPPORT_DEVICE_IDS_LIST */
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user