From 8078049464385db1f2c7667a02a2ea104c717c17 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 1 Apr 2024 17:36:22 +0200 Subject: [PATCH 01/11] wip: AudioObject --- src/audio/audio_structures.rs | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 56c49f4..4e092df 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -27,6 +27,17 @@ pub struct Volume { value: u32, } +pub trait AudioObject { + fn alias(&self) -> String; + fn name(&self) -> String; + fn volume(&self) -> Vec; + fn index(&self) -> u32; + fn channels(&self) -> u16; + fn muted(&self) -> bool; + fn toggle_muted(&mut self); + fn active(&self) -> i32; +} + impl Volume { pub fn from_i32(value: i32) -> Option { match value { @@ -170,6 +181,40 @@ impl From<&SourceInfo<'_>> for Source { } } +impl AudioObject for Source { + fn alias(&self) -> String { + self.alias.clone() + } + + fn name(&self) -> String { + self.name.clone() + } + + fn volume(&self) -> Vec { + self.volume + } + + fn index(&self) -> u32 { + self.index + } + + fn channels(&self) -> u16 { + self.channels + } + + fn muted(&self) -> bool { + self.muted + } + + fn toggle_muted(&mut self) { + self.muted = !self.muted; + } + + fn active(&self) -> i32 { + self.active + } +} + #[derive(Debug, Clone, Default)] pub struct Sink { pub index: u32, From 8034bef41566d418d5a6d896dd7623bf7899d0c7 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 1 Apr 2024 17:38:55 +0200 Subject: [PATCH 02/11] fix: clone on vec --- src/audio/audio_structures.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 4e092df..3319989 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -191,7 +191,7 @@ impl AudioObject for Source { } fn volume(&self) -> Vec { - self.volume + self.volume.clone() } fn index(&self) -> u32 { From b6320927fc44b0578dfd2b408b7b034203ac54c4 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 1 Apr 2024 17:39:41 +0200 Subject: [PATCH 03/11] chore: Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b99f3a0..c5deace 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "re_set-lib" -version = "3.1.7" +version = "3.1.8" edition = "2021" description = "Data structure library for ReSet" repository = "https://github.com/Xetibo/ReSet-Lib" From 1b9e1cdb3acdc0d2841dd5207852deb6274a001b Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 1 Apr 2024 18:18:01 +0200 Subject: [PATCH 04/11] wip: AudioObject for Sink --- Cargo.toml | 2 +- src/audio/audio_structures.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c5deace..f1b0694 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "re_set-lib" -version = "3.1.8" +version = "3.1.9" edition = "2021" description = "Data structure library for ReSet" repository = "https://github.com/Xetibo/ReSet-Lib" diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 3319989..8c5c395 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -295,6 +295,40 @@ impl From<&SinkInfo<'_>> for Sink { } } +impl AudioObject for Sink { + fn alias(&self) -> String { + self.alias.clone() + } + + fn name(&self) -> String { + self.name.clone() + } + + fn volume(&self) -> Vec { + self.volume.clone() + } + + fn index(&self) -> u32 { + self.index + } + + fn channels(&self) -> u16 { + self.channels + } + + fn muted(&self) -> bool { + self.muted + } + + fn toggle_muted(&mut self) { + self.muted = !self.muted; + } + + fn active(&self) -> i32 { + self.active + } +} + #[derive(Debug, Clone, Default)] pub struct InputStream { pub index: u32, From bf709a9f9ad54b69d97c065ee0b50dde78d073ca Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 1 Apr 2024 23:31:58 +0200 Subject: [PATCH 05/11] wip: Add TAudioStreamObject --- Cargo.toml | 2 +- src/audio/audio_structures.rs | 85 +++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f1b0694..2db728a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "re_set-lib" -version = "3.1.9" +version = "3.1.10" edition = "2021" description = "Data structure library for ReSet" repository = "https://github.com/Xetibo/ReSet-Lib" diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 8c5c395..2544b04 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -27,7 +27,7 @@ pub struct Volume { value: u32, } -pub trait AudioObject { +pub trait TAudioObject { fn alias(&self) -> String; fn name(&self) -> String; fn volume(&self) -> Vec; @@ -38,6 +38,17 @@ pub trait AudioObject { fn active(&self) -> i32; } +pub trait TAudioStreamObject { + fn index(&self) -> u32; + fn name(&self) -> String; + fn application_name(&self) -> String; + fn audio_object_index(&self) -> u32; + fn channels(&self) -> u16; + fn volume(&self) -> Vec; + fn muted(&self) -> bool; + fn corked(&self) -> bool; +} + impl Volume { pub fn from_i32(value: i32) -> Option { match value { @@ -181,7 +192,7 @@ impl From<&SourceInfo<'_>> for Source { } } -impl AudioObject for Source { +impl TAudioObject for Source { fn alias(&self) -> String { self.alias.clone() } @@ -295,7 +306,7 @@ impl From<&SinkInfo<'_>> for Sink { } } -impl AudioObject for Sink { +impl TAudioObject for Sink { fn alias(&self) -> String { self.alias.clone() } @@ -409,6 +420,40 @@ impl From<&SinkInputInfo<'_>> for InputStream { } } +impl TAudioStreamObject for InputStream { + fn index(&self) -> u32 { + self.index + } + + fn name(&self) -> String { + self.name.clone() + } + + fn application_name(&self) -> String { + self.application_name.clone() + } + + fn audio_object_index(&self) -> u32 { + self.index + } + + fn channels(&self) -> u16 { + self.channels + } + + fn volume(&self) -> Vec { + self.volume.clone() + } + + fn muted(&self) -> bool { + self.muted + } + + fn corked(&self) -> bool { + self.corked + } +} + #[derive(Debug, Clone, Default)] pub struct OutputStream { pub index: u32, @@ -489,6 +534,40 @@ impl From<&SourceOutputInfo<'_>> for OutputStream { } } +impl TAudioStreamObject for OutputStream { + fn index(&self) -> u32 { + self.index + } + + fn name(&self) -> String { + self.name.clone() + } + + fn application_name(&self) -> String { + self.application_name.clone() + } + + fn audio_object_index(&self) -> u32 { + self.index + } + + fn channels(&self) -> u16 { + self.channels + } + + fn volume(&self) -> Vec { + self.volume.clone() + } + + fn muted(&self) -> bool { + self.muted + } + + fn corked(&self) -> bool { + self.corked + } +} + #[derive(Debug, Clone, Default)] pub struct Card { pub index: u32, From 57febba5bbdbc7426233c008bb58084d083e4cda Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Tue, 2 Apr 2024 11:21:40 +0200 Subject: [PATCH 06/11] wip: Add setmute to stream --- Cargo.toml | 2 +- src/audio/audio_structures.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2db728a..55fb73d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "re_set-lib" -version = "3.1.10" +version = "3.1.11" edition = "2021" description = "Data structure library for ReSet" repository = "https://github.com/Xetibo/ReSet-Lib" diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 2544b04..2c6805d 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -46,6 +46,7 @@ pub trait TAudioStreamObject { fn channels(&self) -> u16; fn volume(&self) -> Vec; fn muted(&self) -> bool; + fn toggle_muted(&mut self); fn corked(&self) -> bool; } @@ -449,6 +450,10 @@ impl TAudioStreamObject for InputStream { self.muted } + fn toggle_muted(&mut self) { + self.muted = !self.muted; + } + fn corked(&self) -> bool { self.corked } @@ -563,6 +568,10 @@ impl TAudioStreamObject for OutputStream { self.muted } + fn toggle_muted(&mut self) { + self.muted = !self.muted; + } + fn corked(&self) -> bool { self.corked } From 8b4735e65eff480ff9819fac1423dd299036c6f3 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Wed, 3 Apr 2024 17:35:36 +0200 Subject: [PATCH 07/11] wip: Add generic audio events --- src/audio/audio_structures.rs | 4 +- src/signals.rs | 156 +++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index 2c6805d..b48bb8b 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -27,7 +27,7 @@ pub struct Volume { value: u32, } -pub trait TAudioObject { +pub trait TAudioObject: Arg + for<'z> Get<'z> + 'static { fn alias(&self) -> String; fn name(&self) -> String; fn volume(&self) -> Vec; @@ -38,7 +38,7 @@ pub trait TAudioObject { fn active(&self) -> i32; } -pub trait TAudioStreamObject { +pub trait TAudioStreamObject: Arg + for<'z> Get<'z> + 'static { fn index(&self) -> u32; fn name(&self) -> String; fn application_name(&self) -> String; diff --git a/src/signals.rs b/src/signals.rs index 842d519..7749653 100644 --- a/src/signals.rs +++ b/src/signals.rs @@ -4,7 +4,9 @@ use dbus::{ }; use crate::{ - audio::audio_structures::{InputStream, OutputStream, Sink, Source}, + audio::audio_structures::{ + InputStream, OutputStream, Sink, Source, TAudioObject, TAudioStreamObject, + }, bluetooth::bluetooth_structures::BluetoothDevice, network::network_structures::{AccessPoint, WifiDevice}, utils::dbus_utils::{AUDIO, BLUETOOTH, WIRELESS}, @@ -290,6 +292,22 @@ impl dbus::message::SignalArgs for WifiDeviceReset { const INTERFACE: &'static str = WIRELESS; } +pub trait TAudioObjectEvent { + fn object(&self) -> AudioObject; + fn object_move(self) -> AudioObject; + fn object_ref(&self) -> &AudioObject; +} + +pub trait TAudioStreamEvent { + fn stream(&self) -> AudioStreamObject; + fn stream_move(self) -> AudioStreamObject; + fn stream_ref(&self) -> &AudioStreamObject; +} + +pub trait TAudioEventRemoved { + fn index(&self) -> u32; +} + #[derive(Debug)] pub struct SinkAdded { pub sink: Sink, @@ -318,6 +336,20 @@ impl GetVal<(Sink,)> for SinkAdded { } } +impl TAudioObjectEvent for SinkAdded { + fn object(&self) -> Sink { + self.sink.clone() + } + + fn object_move(self) -> Sink { + self.sink + } + + fn object_ref(&self) -> &Sink { + &self.sink + } +} + #[derive(Debug)] pub struct SinkChanged { pub sink: Sink, @@ -346,6 +378,20 @@ impl GetVal<(Sink,)> for SinkChanged { } } +impl TAudioObjectEvent for SinkChanged { + fn object(&self) -> Sink { + self.sink.clone() + } + + fn object_move(self) -> Sink { + self.sink + } + + fn object_ref(&self) -> &Sink { + &self.sink + } +} + #[derive(Debug)] pub struct SinkRemoved { pub index: u32, @@ -374,6 +420,12 @@ impl GetVal<(u32,)> for SinkRemoved { } } +impl TAudioEventRemoved for SinkRemoved { + fn index(&self) -> u32 { + self.index + } +} + #[derive(Debug)] pub struct InputStreamAdded { pub stream: InputStream, @@ -402,6 +454,20 @@ impl GetVal<(InputStream,)> for InputStreamAdded { } } +impl TAudioStreamEvent for InputStreamAdded { + fn stream(&self) -> InputStream { + self.stream.clone() + } + + fn stream_move(self) -> InputStream { + self.stream + } + + fn stream_ref(&self) -> &InputStream { + &self.stream + } +} + #[derive(Debug)] pub struct InputStreamChanged { pub stream: InputStream, @@ -424,6 +490,20 @@ impl dbus::message::SignalArgs for InputStreamChanged { const INTERFACE: &'static str = AUDIO; } +impl TAudioStreamEvent for InputStreamChanged { + fn stream(&self) -> InputStream { + self.stream.clone() + } + + fn stream_move(self) -> InputStream { + self.stream + } + + fn stream_ref(&self) -> &InputStream { + &self.stream + } +} + #[derive(Debug)] pub struct InputStreamRemoved { pub index: u32, @@ -452,6 +532,12 @@ impl GetVal<(u32,)> for InputStreamRemoved { } } +impl TAudioEventRemoved for InputStreamRemoved { + fn index(&self) -> u32 { + self.index + } +} + #[derive(Debug)] pub struct SourceAdded { pub source: Source, @@ -480,6 +566,20 @@ impl GetVal<(Source,)> for SourceAdded { } } +impl TAudioObjectEvent for SourceAdded { + fn object(&self) -> Source { + self.source.clone() + } + + fn object_move(self) -> Source { + self.source + } + + fn object_ref(&self) -> &Source { + &self.source + } +} + #[derive(Debug)] pub struct SourceChanged { pub source: Source, @@ -508,6 +608,20 @@ impl GetVal<(Source,)> for SourceChanged { } } +impl TAudioObjectEvent for SourceChanged { + fn object(&self) -> Source { + self.source.clone() + } + + fn object_move(self) -> Source { + self.source + } + + fn object_ref(&self) -> &Source { + &self.source + } +} + #[derive(Debug)] pub struct SourceRemoved { pub index: u32, @@ -536,6 +650,12 @@ impl GetVal<(u32,)> for SourceRemoved { } } +impl TAudioEventRemoved for SourceRemoved { + fn index(&self) -> u32 { + self.index + } +} + #[derive(Debug)] pub struct OutputStreamAdded { pub stream: OutputStream, @@ -564,6 +684,20 @@ impl GetVal<(OutputStream,)> for OutputStreamAdded { } } +impl TAudioStreamEvent for OutputStreamAdded { + fn stream(&self) -> OutputStream { + self.stream.clone() + } + + fn stream_move(self) -> OutputStream { + self.stream + } + + fn stream_ref(&self) -> &OutputStream { + &self.stream + } +} + #[derive(Debug)] pub struct OutputStreamChanged { pub stream: OutputStream, @@ -586,6 +720,20 @@ impl dbus::message::SignalArgs for OutputStreamChanged { const INTERFACE: &'static str = AUDIO; } +impl TAudioStreamEvent for OutputStreamChanged { + fn stream(&self) -> OutputStream { + self.stream.clone() + } + + fn stream_move(self) -> OutputStream { + self.stream + } + + fn stream_ref(&self) -> &OutputStream { + &self.stream + } +} + #[derive(Debug)] pub struct OutputStreamRemoved { pub index: u32, @@ -614,6 +762,12 @@ impl GetVal<(u32,)> for OutputStreamRemoved { } } +impl TAudioEventRemoved for OutputStreamRemoved { + fn index(&self) -> u32 { + self.index + } +} + #[derive(Debug)] pub struct PropertiesChanged { pub interface: String, From 8c1be9a00842f13ded20a891c603c15de3fd13ce Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Wed, 3 Apr 2024 17:39:16 +0200 Subject: [PATCH 08/11] wip: Add Send + Sync to traits --- src/audio/audio_structures.rs | 4 ++-- src/signals.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/audio/audio_structures.rs b/src/audio/audio_structures.rs index b48bb8b..791634e 100644 --- a/src/audio/audio_structures.rs +++ b/src/audio/audio_structures.rs @@ -27,7 +27,7 @@ pub struct Volume { value: u32, } -pub trait TAudioObject: Arg + for<'z> Get<'z> + 'static { +pub trait TAudioObject: Arg + for<'z> Get<'z> + Send + Sync + 'static { fn alias(&self) -> String; fn name(&self) -> String; fn volume(&self) -> Vec; @@ -38,7 +38,7 @@ pub trait TAudioObject: Arg + for<'z> Get<'z> + 'static { fn active(&self) -> i32; } -pub trait TAudioStreamObject: Arg + for<'z> Get<'z> + 'static { +pub trait TAudioStreamObject: Arg + for<'z> Get<'z> + Send + Sync + 'static { fn index(&self) -> u32; fn name(&self) -> String; fn application_name(&self) -> String; diff --git a/src/signals.rs b/src/signals.rs index 7749653..6d9fd11 100644 --- a/src/signals.rs +++ b/src/signals.rs @@ -292,19 +292,19 @@ impl dbus::message::SignalArgs for WifiDeviceReset { const INTERFACE: &'static str = WIRELESS; } -pub trait TAudioObjectEvent { +pub trait TAudioObjectEvent: Send + Sync + 'static { fn object(&self) -> AudioObject; fn object_move(self) -> AudioObject; fn object_ref(&self) -> &AudioObject; } -pub trait TAudioStreamEvent { +pub trait TAudioStreamEvent: Send + Sync + 'static { fn stream(&self) -> AudioStreamObject; fn stream_move(self) -> AudioStreamObject; fn stream_ref(&self) -> &AudioStreamObject; } -pub trait TAudioEventRemoved { +pub trait TAudioEventRemoved: Send + Sync + 'static { fn index(&self) -> u32; } From 707cdde8e27d9613281e8cdde849b2c01c8d406c Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Tue, 9 Apr 2024 21:33:31 +0200 Subject: [PATCH 09/11] feat: Add requires_backend check to capabilities --- src/utils/plugin.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/utils/plugin.rs b/src/utils/plugin.rs index 3280cb2..431c5a9 100644 --- a/src/utils/plugin.rs +++ b/src/utils/plugin.rs @@ -15,18 +15,22 @@ pub enum PluginImplementation { } #[repr(C)] -pub struct PluginCapabilities(Vec<&'static str>, PluginImplementation); +pub struct PluginCapabilities(Vec<&'static str>, bool, PluginImplementation); impl PluginCapabilities { - pub fn get_capabilities(&self) -> Vec<&'static str> { - self.0.clone() + pub fn get_capabilities(&self) -> (Vec<&'static str>, bool) { + (self.0.clone(), self.1) } pub fn get_implementation(&self) -> &PluginImplementation { - &self.1 + &self.2 } - pub fn new(capabilities: Vec<&'static str>, implementation: PluginImplementation) -> Self { - Self(capabilities, implementation) + pub fn new( + capabilities: Vec<&'static str>, + requires_backend: bool, + implementation: PluginImplementation, + ) -> Self { + Self(capabilities, requires_backend, implementation) } } From 31fffca8bee799f8492c7eecc0fa4a7bb3fee272 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Tue, 9 Apr 2024 21:37:58 +0200 Subject: [PATCH 10/11] fix: Use proper types for capabilities --- src/utils/plugin_setup.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/plugin_setup.rs b/src/utils/plugin_setup.rs index 200875c..a5752ab 100644 --- a/src/utils/plugin_setup.rs +++ b/src/utils/plugin_setup.rs @@ -195,7 +195,7 @@ fn get_plugin_capabilities(lib: &Library) -> Option { #[allow(improper_ctypes_definitions)] pub struct BackendPluginFunctions { - pub capabilities: Vec<&'static str>, + pub capabilities: (Vec<&'static str>, bool), pub startup: libloading::Symbol<'static, unsafe extern "C" fn()>, pub shutdown: libloading::Symbol<'static, unsafe extern "C" fn()>, pub name: libloading::Symbol<'static, unsafe extern "C" fn() -> String>, @@ -206,7 +206,7 @@ pub struct BackendPluginFunctions { #[allow(improper_ctypes_definitions)] impl BackendPluginFunctions { pub fn new( - capabilities: Vec<&'static str>, + capabilities: (Vec<&'static str>, bool), backend_startup: libloading::Symbol<'static, unsafe extern "C" fn()>, shutdown: libloading::Symbol<'static, unsafe extern "C" fn()>, name: libloading::Symbol<'static, unsafe extern "C" fn() -> String>, From 6da871ec1fa7c52277b70065ccbcfbe6d12073a6 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Tue, 9 Apr 2024 21:40:11 +0200 Subject: [PATCH 11/11] fix: differentiate between backend and frontend --- src/utils/plugin_setup.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/plugin_setup.rs b/src/utils/plugin_setup.rs index a5752ab..69000ea 100644 --- a/src/utils/plugin_setup.rs +++ b/src/utils/plugin_setup.rs @@ -195,7 +195,7 @@ fn get_plugin_capabilities(lib: &Library) -> Option { #[allow(improper_ctypes_definitions)] pub struct BackendPluginFunctions { - pub capabilities: (Vec<&'static str>, bool), + pub capabilities: Vec<&'static str>, pub startup: libloading::Symbol<'static, unsafe extern "C" fn()>, pub shutdown: libloading::Symbol<'static, unsafe extern "C" fn()>, pub name: libloading::Symbol<'static, unsafe extern "C" fn() -> String>, @@ -214,7 +214,7 @@ impl BackendPluginFunctions { tests: libloading::Symbol<'static, unsafe extern "C" fn() -> Vec>, ) -> Self { Self { - capabilities, + capabilities: capabilities.0, startup: backend_startup, shutdown, name, @@ -230,7 +230,7 @@ unsafe impl Sync for BackendPluginFunctions {} #[allow(improper_ctypes_definitions)] pub struct FrontendPluginFunctions { - pub capabilities: Vec<&'static str>, + pub capabilities: (Vec<&'static str>, bool), pub frontend_startup: libloading::Symbol<'static, unsafe extern "C" fn()>, pub frontend_shutdown: libloading::Symbol<'static, unsafe extern "C" fn()>, pub frontend_data: @@ -241,7 +241,7 @@ pub struct FrontendPluginFunctions { #[allow(improper_ctypes_definitions)] impl FrontendPluginFunctions { pub fn new( - capabilities: Vec<&'static str>, + capabilities: (Vec<&'static str>, bool), frontend_startup: libloading::Symbol<'static, unsafe extern "C" fn()>, frontend_shutdown: libloading::Symbol<'static, unsafe extern "C" fn()>, frontend_data: libloading::Symbol<