mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-01-08 21:33:57 +00:00
[client] audio/pw: refactor to use playback
for playback methods
This commit is contained in:
parent
fe7973ea24
commit
11acaa2957
1 changed files with 63 additions and 53 deletions
|
@ -32,13 +32,19 @@ struct PipeWire
|
||||||
{
|
{
|
||||||
struct pw_loop * loop;
|
struct pw_loop * loop;
|
||||||
struct pw_thread_loop * thread;
|
struct pw_thread_loop * thread;
|
||||||
struct pw_stream * stream;
|
|
||||||
int channels;
|
|
||||||
int sampleRate;
|
|
||||||
int stride;
|
|
||||||
|
|
||||||
RingBuffer buffer;
|
struct
|
||||||
bool active;
|
{
|
||||||
|
struct pw_stream * stream;
|
||||||
|
|
||||||
|
int channels;
|
||||||
|
int sampleRate;
|
||||||
|
int stride;
|
||||||
|
|
||||||
|
RingBuffer buffer;
|
||||||
|
bool active;
|
||||||
|
}
|
||||||
|
playback;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PipeWire pw = {0};
|
static struct PipeWire pw = {0};
|
||||||
|
@ -47,10 +53,11 @@ static void pipewire_on_process(void * userdata)
|
||||||
{
|
{
|
||||||
struct pw_buffer * pbuf;
|
struct pw_buffer * pbuf;
|
||||||
|
|
||||||
if (!ringbuffer_getCount(pw.buffer))
|
if (!ringbuffer_getCount(pw.playback.buffer))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(pbuf = pw_stream_dequeue_buffer(pw.stream))) {
|
if (!(pbuf = pw_stream_dequeue_buffer(pw.playback.stream)))
|
||||||
|
{
|
||||||
DEBUG_WARN("out of buffers");
|
DEBUG_WARN("out of buffers");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -61,15 +68,15 @@ static void pipewire_on_process(void * userdata)
|
||||||
if (!(dst = sbuf->datas[0].data))
|
if (!(dst = sbuf->datas[0].data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int frames = sbuf->datas[0].maxsize / pw.stride;
|
int frames = sbuf->datas[0].maxsize / pw.playback.stride;
|
||||||
void * values = ringbuffer_consume(pw.buffer, &frames);
|
void * values = ringbuffer_consume(pw.playback.buffer, &frames);
|
||||||
memcpy(dst, values, frames * pw.stride);
|
memcpy(dst, values, frames * pw.playback.stride);
|
||||||
|
|
||||||
sbuf->datas[0].chunk->offset = 0;
|
sbuf->datas[0].chunk->offset = 0;
|
||||||
sbuf->datas[0].chunk->stride = pw.stride;
|
sbuf->datas[0].chunk->stride = pw.playback.stride;
|
||||||
sbuf->datas[0].chunk->size = frames * pw.stride;
|
sbuf->datas[0].chunk->size = frames * pw.playback.stride;
|
||||||
|
|
||||||
pw_stream_queue_buffer(pw.stream, pbuf);
|
pw_stream_queue_buffer(pw.playback.stream, pbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pipewire_init(void)
|
static bool pipewire_init(void)
|
||||||
|
@ -92,7 +99,7 @@ static bool pipewire_init(void)
|
||||||
pw_context_destroy(context);
|
pw_context_destroy(context);
|
||||||
|
|
||||||
/* PipeWire is available so create the loop thread and start it */
|
/* PipeWire is available so create the loop thread and start it */
|
||||||
pw.thread = pw_thread_loop_new_full(pw.loop, "Playback", NULL);
|
pw.thread = pw_thread_loop_new_full(pw.loop, "PipeWire", NULL);
|
||||||
if (!pw.thread)
|
if (!pw.thread)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create the thread loop");
|
DEBUG_ERROR("Failed to create the thread loop");
|
||||||
|
@ -111,21 +118,21 @@ err:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_stop_stream(void)
|
static void pipewire_playbackStop_stream(void)
|
||||||
{
|
{
|
||||||
if (!pw.stream)
|
if (!pw.playback.stream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw_stream_flush(pw.stream, true);
|
pw_stream_flush(pw.playback.stream, true);
|
||||||
pw_stream_destroy(pw.stream);
|
pw_stream_destroy(pw.playback.stream);
|
||||||
pw.stream = NULL;
|
pw.playback.stream = NULL;
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_free(void)
|
static void pipewire_free(void)
|
||||||
{
|
{
|
||||||
pipewire_stop_stream();
|
pipewire_playbackStop_stream();
|
||||||
pw_thread_loop_stop(pw.thread);
|
pw_thread_loop_stop(pw.thread);
|
||||||
pw_thread_loop_destroy(pw.thread);
|
pw_thread_loop_destroy(pw.thread);
|
||||||
pw_loop_destroy(pw.loop);
|
pw_loop_destroy(pw.loop);
|
||||||
|
@ -133,11 +140,11 @@ static void pipewire_free(void)
|
||||||
pw.loop = NULL;
|
pw.loop = NULL;
|
||||||
pw.thread = NULL;
|
pw.thread = NULL;
|
||||||
|
|
||||||
ringbuffer_free(&pw.buffer);
|
ringbuffer_free(&pw.playback.buffer);
|
||||||
pw_deinit();
|
pw_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_start(int channels, int sampleRate)
|
static void pipewire_playbackPlaybackStart(int channels, int sampleRate)
|
||||||
{
|
{
|
||||||
const struct spa_pod * params[1];
|
const struct spa_pod * params[1];
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
|
@ -148,18 +155,20 @@ static void pipewire_start(int channels, int sampleRate)
|
||||||
.process = pipewire_on_process
|
.process = pipewire_on_process
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pw.stream && pw.channels == channels && pw.sampleRate == sampleRate)
|
if (pw.playback.stream &&
|
||||||
|
pw.playback.channels == channels &&
|
||||||
|
pw.playback.sampleRate == sampleRate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pipewire_stop_stream();
|
pipewire_playbackStop_stream();
|
||||||
|
|
||||||
pw.channels = channels;
|
pw.playback.channels = channels;
|
||||||
pw.sampleRate = sampleRate;
|
pw.playback.sampleRate = sampleRate;
|
||||||
pw.stride = sizeof(uint16_t) * channels;
|
pw.playback.stride = sizeof(uint16_t) * channels;
|
||||||
pw.buffer = ringbuffer_new(sampleRate / 10, channels * sizeof(uint16_t));
|
pw.playback.buffer = ringbuffer_new(sampleRate / 10, channels * sizeof(uint16_t));
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw.stream = pw_stream_new_simple(
|
pw.playback.stream = pw_stream_new_simple(
|
||||||
pw.loop,
|
pw.loop,
|
||||||
"Looking Glass",
|
"Looking Glass",
|
||||||
pw_properties_new(
|
pw_properties_new(
|
||||||
|
@ -173,7 +182,7 @@ static void pipewire_start(int channels, int sampleRate)
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!pw.stream)
|
if (!pw.playback.stream)
|
||||||
{
|
{
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
DEBUG_ERROR("Failed to create the stream");
|
DEBUG_ERROR("Failed to create the stream");
|
||||||
|
@ -188,7 +197,7 @@ static void pipewire_start(int channels, int sampleRate)
|
||||||
));
|
));
|
||||||
|
|
||||||
pw_stream_connect(
|
pw_stream_connect(
|
||||||
pw.stream,
|
pw.playback.stream,
|
||||||
PW_DIRECTION_OUTPUT,
|
PW_DIRECTION_OUTPUT,
|
||||||
PW_ID_ANY,
|
PW_ID_ANY,
|
||||||
PW_STREAM_FLAG_AUTOCONNECT |
|
PW_STREAM_FLAG_AUTOCONNECT |
|
||||||
|
@ -200,47 +209,47 @@ static void pipewire_start(int channels, int sampleRate)
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_play(uint8_t * data, size_t size)
|
static void pipewire_playbackPlay(uint8_t * data, size_t size)
|
||||||
{
|
{
|
||||||
if (!pw.stream)
|
if (!pw.playback.stream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if the buffer fill is higher then the average skip the update to reduce lag
|
// if the buffer fill is higher then the average skip the update to reduce lag
|
||||||
static unsigned int ttlSize = 0;
|
static unsigned int ttlSize = 0;
|
||||||
static unsigned int count = 0;
|
static unsigned int count = 0;
|
||||||
ttlSize += size;
|
ttlSize += size;
|
||||||
if (++count > 100 && ringbuffer_getCount(pw.buffer) > ttlSize / count)
|
if (++count > 100 && ringbuffer_getCount(pw.playback.buffer) > ttlSize / count)
|
||||||
{
|
{
|
||||||
count = 0;
|
count = 0;
|
||||||
ttlSize = 0;
|
ttlSize = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ringbuffer_append(pw.buffer, data, size / pw.stride);
|
ringbuffer_append(pw.playback.buffer, data, size / pw.playback.stride);
|
||||||
|
|
||||||
if (!pw.active)
|
if (!pw.playback.active)
|
||||||
{
|
{
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw_stream_set_active(pw.stream, true);
|
pw_stream_set_active(pw.playback.stream, true);
|
||||||
pw.active = true;
|
pw.playback.active = true;
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_stop(void)
|
static void pipewire_playbackStop(void)
|
||||||
{
|
{
|
||||||
if (!pw.active)
|
if (!pw.playback.active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw_stream_set_active(pw.stream, false);
|
pw_stream_set_active(pw.playback.stream, false);
|
||||||
pw.active = false;
|
pw.playback.active = false;
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_volume(int channels, const uint16_t volume[])
|
static void pipewire_playbackVolume(int channels, const uint16_t volume[])
|
||||||
{
|
{
|
||||||
if (channels != pw.channels)
|
if (channels != pw.playback.channels)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float param[channels];
|
float param[channels];
|
||||||
|
@ -248,14 +257,15 @@ static void pipewire_volume(int channels, const uint16_t volume[])
|
||||||
param[i] = 9.3234e-7 * pow(1.000211902, volume[i]) - 0.000172787;
|
param[i] = 9.3234e-7 * pow(1.000211902, volume[i]) - 0.000172787;
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw_stream_set_control(pw.stream, SPA_PROP_channelVolumes, channels, param, 0);
|
pw_stream_set_control(pw.playback.stream, SPA_PROP_channelVolumes,
|
||||||
|
channels, param, 0);
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipewire_mute(bool mute)
|
static void pipewire_playbackMute(bool mute)
|
||||||
{
|
{
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
pw_stream_set_control(pw.stream, SPA_PROP_mute, 1, (void *)&mute, 0);
|
pw_stream_set_control(pw.playback.stream, SPA_PROP_mute, 1, (void *)&mute, 0);
|
||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,10 +276,10 @@ struct LG_AudioDevOps LGAD_PipeWire =
|
||||||
.free = pipewire_free,
|
.free = pipewire_free,
|
||||||
.playback =
|
.playback =
|
||||||
{
|
{
|
||||||
.start = pipewire_start,
|
.start = pipewire_playbackPlaybackStart,
|
||||||
.play = pipewire_play,
|
.play = pipewire_playbackPlay,
|
||||||
.stop = pipewire_stop,
|
.stop = pipewire_playbackStop,
|
||||||
.volume = pipewire_volume,
|
.volume = pipewire_playbackVolume,
|
||||||
.mute = pipewire_mute
|
.mute = pipewire_playbackMute
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue