|
|
Here are some ideas for a simple API
|
|
|
|
|
|
# Device enumeration
|
|
|
|
|
|
First make a new PipeWire simple instance. This will connect behind the scene etc.
|
|
|
|
|
|
'''
|
|
|
struct pws *pws = pws_new();
|
|
|
'''
|
|
|
|
|
|
Then we can enumerate devices. You specify with flags what types of devices you want.
|
|
|
|
|
|
'''
|
|
|
struct pws_endpoint *endpoints[16];
|
|
|
enum pws_endpoint_flags flags = PWS_ENDPOINT_SOURCE | PWS_ENDPOINT_VIDEO | PWS_ENDPOINT_CAMERA;
|
|
|
|
|
|
n = pws_get_endpoints(pws, flags, endpoints, N_ELEMENTS(endpoints));
|
|
|
'''
|
|
|
|
|
|
Now we have an array of endpoints, you should be able to get more info with something like:
|
|
|
|
|
|
'''
|
|
|
const char *value = pws_endpoint_get_property(endpoint, "some.property.name");
|
|
|
'''
|
|
|
|
|
|
We should also have something to enumerate the formats. Formats are always more complicated because
|
|
|
they involve ranges and enumerations etc.
|
|
|
|
|
|
# Simple playback
|
|
|
|
|
|
Create a simple audio playback object
|
|
|
|
|
|
'''
|
|
|
struct pws_audio_playback *play;
|
|
|
struct pws_format *format;
|
|
|
|
|
|
format = pws_format_new("s16le", 44100, 2);
|
|
|
|
|
|
play = pws_audio_playback_new(pws, /* pws instance */
|
|
|
NULL, /* optional target endpoint */
|
|
|
NULL, /* optional extra properties */
|
|
|
format, /* wanted format */
|
|
|
produce_samples, /* callback that produces samples */
|
|
|
user_data); /* user data passed to callback */
|
|
|
|
|
|
'''
|
|
|
|
|
|
The samples are produced with a callback like this:
|
|
|
|
|
|
'''
|
|
|
static int produce_samples(void *user_data, void *data, uint32_t n_frames, struct timespec *time)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
int16_t *d = data;
|
|
|
for (i = 0; i < n_frames; i++)
|
|
|
d[i] = rand();
|
|
|
}
|
|
|
return n_frames;
|
|
|
}
|
|
|
'''
|
|
|
|
|
|
You are supposed to keep track of the format (and channels, rate) to produce data in the function.
|
|
|
The time argument tells you when this data will be played against the monotonic clock.
|
|
|
|
|
|
You start/stop playback with:
|
|
|
|
|
|
'''
|
|
|
pws_audio_playback_start(play);
|
|
|
pws_audio_playback_stop(play);
|
|
|
'''
|
|
|
|
|
|
# Simple audio capture
|
|
|
|
|
|
Create a simple capture object
|
|
|
|
|
|
'''
|
|
|
struct pws_audio_capture *catpure;
|
|
|
struct pws_format *format;
|
|
|
|
|
|
format = pws_format_new("s16le", 44100, 2);
|
|
|
|
|
|
play = pws_audio_capture_new(pws, /* pws instance */
|
|
|
NULL, /* optional target endpoint */
|
|
|
NULL, /* optional extra properties */
|
|
|
format, /* wanted format */
|
|
|
consume_samples, /* callback that consumes samples */
|
|
|
user_data); /* user data passed to callback */
|
|
|
|
|
|
'''
|
|
|
|
|
|
The samples are consumed with a callback like this:
|
|
|
|
|
|
'''
|
|
|
static int consume_samples(void *user_data, const void *data, uint32_t n_frames, struct timespec *time)
|
|
|
{
|
|
|
uint32_t i;
|
|
|
int16_t *s = data;
|
|
|
for (i = 0; i < n_frames; i++)
|
|
|
printf("got sample %d\n", s[i]);
|
|
|
}
|
|
|
return n_frames;
|
|
|
}
|
|
|
'''
|
|
|
|
|
|
You are supposed to keep track of the format (and channels, rate) to consume data in the function.
|
|
|
The time argument tells you when this data was captured against the monotonic clock.
|
|
|
|
|
|
You start/stop capture with:
|
|
|
|
|
|
'''
|
|
|
pws_audio_playback_start(play);
|
|
|
pws_audio_playback_stop(play);
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|