use super::*;
use crate::clap::extensions::params::PARAM_INPUT_GAIN;
use crate::clap::plugin::make_test_shared;
use clack_host::prelude::EventBuffer;
use clack_plugin::events::event_types::{
ParamGestureBeginEvent, ParamGestureEndEvent, ParamValueEvent,
};
use clack_plugin::prelude::InputEvents;
use std::sync::atomic::Ordering;
#[test]
fn test_gui_gestures_and_parameter_flow() {
let shared = make_test_shared();
let input_idx = PARAM_INPUT_GAIN as usize;
const BITS_PER_PARAM: u32 = 3;
const CHANGED_SHIFT: u32 = 0;
const BEGIN_SHIFT: u32 = 1;
const END_SHIFT: u32 = 2;
let offset = input_idx as u32 * BITS_PER_PARAM;
shared
.ui_to_rt
.gesture_flags
.fetch_or(1 << (offset + BEGIN_SHIFT), Ordering::Relaxed);
shared
.ui_to_rt
.gesture_flags
.fetch_or(1 << (offset + CHANGED_SHIFT), Ordering::Relaxed);
shared
.ui_to_rt
.param_input_gain
.store(1.5f32.to_bits(), Ordering::Relaxed);
shared
.ui_to_rt
.gesture_flags
.fetch_or(1 << (offset + END_SHIFT), Ordering::Relaxed);
let mut output_events_buffer = EventBuffer::new();
{
let mut output_events = OutputEvents::from_buffer(&mut output_events_buffer);
shared.write_gui_events(&mut output_events);
}
let input_view = InputEvents::from_buffer(&output_events_buffer);
let mut begin_received = false;
let mut value_received = false;
let mut end_received = false;
for event in &input_view {
if let Some(begin) = event.as_event::<ParamGestureBeginEvent>()
&& begin.param_id().unwrap().get() == PARAM_INPUT_GAIN
{
begin_received = true;
} else if let Some(val_ev) = event.as_event::<ParamValueEvent>() {
if val_ev.param_id().unwrap().get() == PARAM_INPUT_GAIN {
assert_eq!(val_ev.value(), 1.5);
value_received = true;
}
} else if let Some(end) = event.as_event::<ParamGestureEndEvent>()
&& end.param_id().unwrap().get() == PARAM_INPUT_GAIN
{
end_received = true;
}
}
assert!(begin_received, "Should receive ParamGestureBeginEvent");
assert!(value_received, "Should receive ParamValueEvent");
assert!(end_received, "Should receive ParamGestureEndEvent");
let flags = shared.ui_to_rt.gesture_flags.load(Ordering::Relaxed);
assert_eq!(
flags & (1 << (offset + BEGIN_SHIFT)),
0,
"begin flag should be cleared"
);
assert_eq!(
flags & (1 << (offset + CHANGED_SHIFT)),
0,
"changed flag should be cleared"
);
assert_eq!(
flags & (1 << (offset + END_SHIFT)),
0,
"end flag should be cleared"
);
}
#[test]
fn test_file_picker_alive_fence_and_timeout() {
let shared = Arc::new(make_test_shared());
{
shared.cold.ui_loading.store(true, Ordering::Relaxed);
let alive_fence = Arc::clone(&shared.cold.alive_fence);
let shared_addr = &*shared as *const NamClapShared as usize;
let (tx, rx) = std::sync::mpsc::channel();
tx.send(Some(std::path::PathBuf::from("/tmp/model.nam")))
.unwrap();
match rx.recv_timeout(std::time::Duration::from_millis(50)) {
Ok(path_opt) => {
if alive_fence.load(Ordering::Relaxed) {
let shared_ref = unsafe { &*(shared_addr as *const NamClapShared) };
if let Some(path) = path_opt
&& let Ok(mut pending_guard) = shared_ref.cold.ui_pending_model.lock()
{
*pending_guard = Some(path);
}
}
}
Err(_) => panic!("Should have received the path"),
}
assert_eq!(
*shared.cold.ui_pending_model.lock().unwrap(),
Some(std::path::PathBuf::from("/tmp/model.nam"))
);
}
*shared.cold.ui_pending_model.lock().unwrap() = None;
{
shared.cold.ui_loading.store(true, Ordering::Relaxed);
let alive_fence = Arc::clone(&shared.cold.alive_fence);
let shared_addr = &*shared as *const NamClapShared as usize;
alive_fence.store(false, Ordering::Relaxed);
let (tx, rx) = std::sync::mpsc::channel();
tx.send(Some(std::path::PathBuf::from("/tmp/model2.nam")))
.unwrap();
match rx.recv_timeout(std::time::Duration::from_millis(50)) {
Ok(path_opt) => {
if alive_fence.load(Ordering::Relaxed) {
let shared_ref = unsafe { &*(shared_addr as *const NamClapShared) };
if let Some(path) = path_opt
&& let Ok(mut pending_guard) = shared_ref.cold.ui_pending_model.lock()
{
*pending_guard = Some(path);
}
}
}
Err(_) => panic!("Should have received the path"),
}
assert_eq!(*shared.cold.ui_pending_model.lock().unwrap(), None);
}
{
shared.cold.alive_fence.store(true, Ordering::Relaxed);
shared.cold.ui_loading.store(true, Ordering::Relaxed);
let alive_fence = Arc::clone(&shared.cold.alive_fence);
let shared_addr = &*shared as *const NamClapShared as usize;
let (_tx, rx) = std::sync::mpsc::channel::<Option<std::path::PathBuf>>();
match rx.recv_timeout(std::time::Duration::from_millis(10)) {
Ok(_) => panic!("Should not have received anything"),
Err(_) => {
if alive_fence.load(Ordering::Relaxed) {
let shared_ref = unsafe { &*(shared_addr as *const NamClapShared) };
shared_ref.cold.ui_loading.store(false, Ordering::Relaxed);
}
}
}
assert!(!shared.cold.ui_loading.load(Ordering::Relaxed));
}
}