nice_plug/wrapper/
standalone.rs1use clap::{CommandFactory, FromArgMatches};
5use nice_plug_core::plugin::Plugin;
6
7use self::backend::Backend;
8use self::config::WrapperConfig;
9use self::wrapper::{Wrapper, WrapperError};
10use super::util::setup_logger;
11
12mod backend;
13mod config;
14mod context;
15mod wrapper;
16
17pub fn nice_export_standalone<P: Plugin>() -> bool {
51 nice_export_standalone_with_args::<P, _>(std::env::args())
54}
55
56pub fn nice_export_standalone_with_args<P: Plugin, Args: IntoIterator<Item = String>>(
59 args: Args,
60) -> bool {
61 setup_logger();
62
63 let config = WrapperConfig::from_arg_matches(
67 &WrapperConfig::command()
68 .name(P::NAME)
69 .author(P::VENDOR)
70 .get_matches_from(args),
71 )
72 .unwrap_or_else(|err| err.exit());
73
74 match config.backend {
75 config::BackendType::Auto => {
76 let result = backend::Jack::new::<P>(config.clone()).map(|backend| {
77 crate::nice_log!("Using the JACK backend");
78 run_wrapper::<P, _>(backend, config.clone())
79 });
80
81 #[cfg(target_os = "linux")]
82 let result = result.or_else(|_| {
83 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Alsa) {
84 Ok(backend) => {
85 crate::nice_log!("Using the ALSA backend");
86 Ok(run_wrapper::<P, _>(backend, config.clone()))
87 }
88 Err(err) => {
89 use nice_plug_core::nice_error;
90
91 nice_error!(
92 "Could not initialize either the JACK or the ALSA backends, falling \
93 back to the dummy audio backend: {err:#}"
94 );
95 Err(())
96 }
97 }
98 });
99 #[cfg(target_os = "macos")]
100 let result = result.or_else(|_| {
101 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::CoreAudio) {
102 Ok(backend) => {
103 crate::nice_log!("Using the CoreAudio backend");
104 Ok(run_wrapper::<P, _>(backend, config.clone()))
105 }
106 Err(err) => {
107 crate::nice_error!(
108 "Could not initialize either the JACK or the CoreAudio backends, \
109 falling back to the dummy audio backend: {err:#}"
110 );
111 Err(())
112 }
113 }
114 });
115 #[cfg(target_os = "windows")]
116 let result = result.or_else(|_| {
117 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Wasapi) {
118 Ok(backend) => {
119 crate::nice_log!("Using the WASAPI backend");
120 Ok(run_wrapper::<P, _>(backend, config.clone()))
121 }
122 Err(err) => {
123 crate::nice_error!(
124 "Could not initialize either the JACK or the WASAPI backends, falling \
125 back to the dummy audio backend: {err:#}"
126 );
127 Err(())
128 }
129 }
130 });
131
132 result.unwrap_or_else(|_| {
133 crate::nice_error!(
134 "Falling back to the dummy audio backend, audio and MIDI will not work"
135 );
136 run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
137 })
138 }
139 config::BackendType::Jack => match backend::Jack::new::<P>(config.clone()) {
140 Ok(backend) => run_wrapper::<P, _>(backend, config),
141 Err(err) => {
142 crate::nice_error!("Could not initialize the JACK backend: {:#}", err);
143 false
144 }
145 },
146 #[cfg(target_os = "linux")]
147 config::BackendType::Alsa => {
148 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Alsa) {
149 Ok(backend) => run_wrapper::<P, _>(backend, config),
150 Err(err) => {
151 crate::nice_error!("Could not initialize the ALSA backend: {:#}", err);
152 false
153 }
154 }
155 }
156 #[cfg(target_os = "macos")]
157 config::BackendType::CoreAudio => {
158 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::CoreAudio) {
159 Ok(backend) => run_wrapper::<P, _>(backend, config),
160 Err(err) => {
161 crate::nice_error!("Could not initialize the CoreAudio backend: {:#}", err);
162 false
163 }
164 }
165 }
166 #[cfg(target_os = "windows")]
167 config::BackendType::Wasapi => {
168 match backend::CpalMidir::new::<P>(config.clone(), cpal::HostId::Wasapi) {
169 Ok(backend) => run_wrapper::<P, _>(backend, config),
170 Err(err) => {
171 crate::nice_error!("Could not initialize the WASAPI backend: {:#}", err);
172 false
173 }
174 }
175 }
176 config::BackendType::Dummy => {
177 run_wrapper::<P, _>(backend::Dummy::new::<P>(config.clone()), config)
178 }
179 }
180}
181
182fn run_wrapper<P: Plugin, B: Backend<P>>(backend: B, config: WrapperConfig) -> bool {
183 let wrapper = match Wrapper::<P, _>::new(backend, config) {
184 Ok(wrapper) => wrapper,
185 Err(err) => {
186 print_error(err);
187 return false;
188 }
189 };
190
191 match wrapper.run() {
193 Ok(()) => true,
194 Err(err) => {
195 print_error(err);
196 false
197 }
198 }
199}
200
201fn print_error(error: WrapperError) {
202 match error {
203 WrapperError::InitializationFailed => {
204 crate::nice_error!("The plugin failed to initialize");
205 }
206 }
207}