mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
App audio capture: fix audio sources getting paused when closing gsr
This commit is contained in:
1
TODO
1
TODO
@@ -330,7 +330,6 @@ Set top level window argument for portal capture. Same for gpu-screen-recorder-g
|
||||
Remove unix domain socket code from kms-client/server and use socketpair directly. To make this possible always execute the kms server permission setup in flatpak, before starting recording (in gpu-screen-recorder-gtk).
|
||||
|
||||
Application audio capture isn't good enough. It creates a sink that for some automatically gets selected as the default output device and it's visible as an output device.
|
||||
When shutting down gpu screen recorder it will also cause audio applications to pause.
|
||||
Fix some of these issues by setting gsr-app-sink media class to "Stream/Input/Audio" and node.virtual=true.
|
||||
However that causes pulseaudio to be unable to record from gsr-app-sink, and it ends up being stuck in pa_sound_device_handle_reconnect in the loop with pa_mainloop_iterate.
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ typedef struct {
|
||||
struct pw_proxy **virtual_sink_proxies;
|
||||
size_t num_virtual_sink_proxies;
|
||||
size_t virtual_sink_proxies_capacity_items;
|
||||
|
||||
bool running;
|
||||
} gsr_pipewire_audio;
|
||||
|
||||
bool gsr_pipewire_audio_init(gsr_pipewire_audio *self);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.7.2', default_options : ['warning_level=2'])
|
||||
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.7.3', default_options : ['warning_level=2'])
|
||||
|
||||
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
|
||||
if get_option('buildtype') == 'debug'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "gpu-screen-recorder"
|
||||
type = "executable"
|
||||
version = "5.7.2"
|
||||
version = "5.7.3"
|
||||
platforms = ["posix"]
|
||||
|
||||
[config]
|
||||
|
||||
@@ -392,12 +392,12 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions,
|
||||
const struct spa_dict *props)
|
||||
{
|
||||
//fprintf(stderr, "add: id: %d, type: %s\n", (int)id, type);
|
||||
if(!props || !type)
|
||||
gsr_pipewire_audio *self = (gsr_pipewire_audio*)data;
|
||||
if(!props || !type || !self->running)
|
||||
return;
|
||||
|
||||
//pw_properties_new_dict(props);
|
||||
|
||||
gsr_pipewire_audio *self = (gsr_pipewire_audio*)data;
|
||||
if(strcmp(type, PW_TYPE_INTERFACE_Node) == 0) {
|
||||
const char *node_name = spa_dict_lookup(props, PW_KEY_NODE_NAME);
|
||||
const char *media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS);
|
||||
@@ -547,6 +547,7 @@ static const struct pw_registry_events registry_events = {
|
||||
|
||||
bool gsr_pipewire_audio_init(gsr_pipewire_audio *self) {
|
||||
memset(self, 0, sizeof(*self));
|
||||
self->running = true;
|
||||
|
||||
pw_init(NULL, NULL);
|
||||
|
||||
@@ -594,8 +595,49 @@ bool gsr_pipewire_audio_init(gsr_pipewire_audio *self) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static gsr_pipewire_audio_link* gsr_pipewire_audio_get_first_link_to_node(gsr_pipewire_audio *self, uint32_t node_id) {
|
||||
for(size_t i = 0; i < self->num_links; ++i) {
|
||||
if(self->links[i].input_node_id == node_id)
|
||||
return &self->links[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gsr_pipewire_audio_destroy_requested_links(gsr_pipewire_audio *self) {
|
||||
pw_thread_loop_lock(self->thread_loop);
|
||||
|
||||
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, self->server_version_sync);
|
||||
pw_thread_loop_wait(self->thread_loop);
|
||||
|
||||
for(size_t requested_link_index = 0; requested_link_index < self->num_requested_links; ++requested_link_index) {
|
||||
const gsr_pipewire_audio_node_type requested_link_node_type = self->requested_links[requested_link_index].input_type == GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_STREAM ? GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_INPUT : GSR_PIPEWIRE_AUDIO_NODE_TYPE_SINK_OR_SOURCE;
|
||||
const gsr_pipewire_audio_node *stream_input_node = gsr_pipewire_audio_get_node_by_name_case_insensitive(self, self->requested_links[requested_link_index].input_name, requested_link_node_type);
|
||||
if(!stream_input_node)
|
||||
continue;
|
||||
|
||||
for(;;) {
|
||||
gsr_pipewire_audio_link *link = gsr_pipewire_audio_get_first_link_to_node(self, stream_input_node->id);
|
||||
if(!link)
|
||||
break;
|
||||
|
||||
pw_registry_destroy(self->registry, link->id);
|
||||
|
||||
self->server_version_sync = pw_core_sync(self->core, PW_ID_CORE, self->server_version_sync);
|
||||
pw_thread_loop_wait(self->thread_loop);
|
||||
|
||||
usleep(10 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
pw_thread_loop_unlock(self->thread_loop);
|
||||
}
|
||||
|
||||
void gsr_pipewire_audio_deinit(gsr_pipewire_audio *self) {
|
||||
self->running = false;
|
||||
|
||||
if(self->thread_loop) {
|
||||
/* We need to manually destroy links first, otherwise the linked audio sources will be paused when closing the program */
|
||||
gsr_pipewire_audio_destroy_requested_links(self);
|
||||
//pw_thread_loop_wait(self->thread_loop);
|
||||
pw_thread_loop_stop(self->thread_loop);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user