PC Music Generator - a Virtual Modular Synthesizer
1use std::{
2 collections::{
3 BTreeMap,
4 VecDeque,
5 },
6 fs,
7 path::Path,
8 sync::Arc,
9};
10
11use devices::description::DeviceKind;
12use egui::{
13 Context,
14 DragValue,
15 Pos2,
16 Ui,
17 Vec2,
18 Window,
19};
20use serde::{
21 Deserialize,
22 Deserializer,
23 Serialize,
24 Serializer,
25};
26use uuid::Uuid;
27use visuals::templates::WidgetTemplate;
28
29pub mod container;
30pub mod devices;
31pub mod graph;
32pub mod module_description;
33pub mod visuals;
34pub mod widgets;
35
36pub fn widget_prefabs(
37 path: impl AsRef<Path>,
38) -> Result<BTreeMap<Uuid, WidgetTemplate>, Box<dyn std::error::Error>> {
39 fs::read_to_string(path).map_err(Into::into).and_then(|s| {
40 let prefabs = serde_yaml::from_str(&s)?;
41 Ok(prefabs)
42 })
43}
44
45pub fn widget_name(uuid: Option<Uuid>, widgets: &BTreeMap<Uuid, WidgetTemplate>) -> String {
46 if let Some(uuid) = uuid {
47 format!("{}: {}", uuid, widgets[&uuid].name)
48 } else {
49 "None".into()
50 }
51}
52
53pub fn pos_drag_value(ui: &mut Ui, label: impl AsRef<str>, pos: &mut Pos2) {
54 two_drag_value(ui, label.as_ref(), "X", "Y", &mut pos.x, &mut pos.y)
55}
56
57pub fn vec_drag_value(ui: &mut Ui, label: impl AsRef<str>, vec: &mut Vec2) {
58 two_drag_value(ui, label.as_ref(), "X", "Y", &mut vec.x, &mut vec.y)
59}
60
61pub fn two_drag_value(
62 ui: &mut Ui,
63 label: impl AsRef<str>,
64 l1: impl AsRef<str>,
65 l2: impl AsRef<str>,
66 v1: &mut f32,
67 v2: &mut f32,
68) {
69 ui.horizontal(|ui| {
70 ui.label(label.as_ref());
71 ui.label(l1.as_ref());
72 ui.add(DragValue::new(v1));
73 ui.label(l2.as_ref());
74 ui.add(DragValue::new(v2));
75 });
76}
77
78pub fn error_window(error: &mut Option<Box<dyn std::error::Error>>, ctx: &Context) {
79 Window::new("Error").resizable(false).show(ctx, |ui| {
80 ui.vertical_centered(|ui| {
81 ui.label(error.as_ref().unwrap().to_string());
82 if ui.button("Ok").clicked() {
83 error.take();
84 }
85 })
86 });
87}
88
89fn ser_btree_as_vec<S, T>(map: &BTreeMap<usize, T>, ser: S) -> Result<S::Ok, S::Error>
90where
91 S: Serializer,
92 T: Serialize,
93{
94 map.values().collect::<Vec<_>>().serialize(ser)
95}
96
97fn de_vec_as_btree<'de, D, T>(de: D) -> Result<BTreeMap<usize, T>, D::Error>
98where
99 D: Deserializer<'de>,
100 T: Deserialize<'de>,
101{
102 let vec: Vec<T> = Vec::deserialize(de)?;
103 Ok(vec.into_iter().enumerate().collect())
104}
105
106pub fn ser_device_description<S>(dd: &usize, ser: S) -> Result<S::Ok, S::Error>
107where
108 S: Serializer,
109{
110 DeviceKind::Audio(*dd).name().serialize(ser)
111}
112
113pub fn de_device_description<'de, D>(de: D) -> Result<usize, D::Error>
114where
115 D: Deserializer<'de>,
116 D::Error: serde::de::Error,
117{
118 let s = String::deserialize(de)?;
119
120 devices::DEVICES
121 .iter()
122 .enumerate()
123 .find_map(|(id, dd)| if dd.name == s { Some(id) } else { None })
124 .ok_or(serde::de::Error::custom(format!(
125 "{s} is not a known device name, I only know these devices: {:?}",
126 DeviceKind::all()
127 .iter()
128 .map(DeviceKind::name)
129 .collect::<Vec<_>>()
130 )))
131}
132pub struct STQueue<T> {
133 inner: Arc<eframe::epaint::mutex::Mutex<VecDeque<T>>>,
134}
135
136impl<T> Clone for STQueue<T> {
137 fn clone(&self) -> Self {
138 Self {
139 inner: Arc::clone(&self.inner),
140 }
141 }
142}
143
144impl<T> STQueue<T> {
145 pub fn new() -> Self {
146 Self {
147 inner: Default::default(),
148 }
149 }
150
151 pub fn put(&self, msg: T) {
152 self.inner.lock().push_front(msg)
153 }
154
155 pub fn get(&self) -> Option<T> {
156 self.inner.lock().pop_back()
157 }
158}
159
160impl<T> Default for STQueue<T> {
161 fn default() -> Self {
162 Self::new()
163 }
164}
165
166pub trait Uuidentified {
167 fn uuid(&self) -> Uuid;
168}
169
170pub trait Tooltipable {
171 fn tooltip(&self) -> String;
172}