1use crate::message::{AudioClipData, MidiClipData};
2use crate::track::Track;
3use std::{
4 cell::UnsafeCell,
5 collections::HashMap,
6 fmt,
7 marker::PhantomData,
8 ops::{Deref, DerefMut},
9 sync::Arc,
10};
11
12pub type TrackHandle = Arc<Track>;
13pub type StateSlot = arc_swap::ArcSwap<StateSnapshot>;
14
15pub struct State {
16 inner: UnsafeCell<StateData>,
17}
18
19#[derive(Default, Debug)]
20pub struct StateData {
21 pub tracks: HashMap<String, TrackHandle>,
22 pub unused_audio_clips: Vec<AudioClipData>,
23 pub unused_midi_clips: Vec<MidiClipData>,
24}
25
26pub struct StateGuard<'a> {
27 ptr: *mut StateData,
28 _marker: PhantomData<&'a mut StateData>,
29}
30
31unsafe impl Send for StateGuard<'_> {}
32
33unsafe impl Sync for State {}
38
39impl Default for State {
40 fn default() -> Self {
41 Self {
42 inner: UnsafeCell::new(StateData::default()),
43 }
44 }
45}
46
47impl fmt::Debug for State {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.debug_struct("State")
50 .field("tracks", &self.tracks)
51 .finish()
52 }
53}
54
55impl Deref for State {
56 type Target = StateData;
57
58 fn deref(&self) -> &Self::Target {
59 unsafe { &*self.inner.get() }
60 }
61}
62
63impl DerefMut for State {
64 fn deref_mut(&mut self) -> &mut Self::Target {
65 self.inner.get_mut()
66 }
67}
68
69impl StateData {
70 pub fn snapshot(&self) -> StateSnapshot {
71 StateSnapshot {
72 tracks: self.tracks.clone(),
73 unused_audio_clips: self.unused_audio_clips.clone(),
74 unused_midi_clips: self.unused_midi_clips.clone(),
75 }
76 }
77}
78
79impl Deref for StateGuard<'_> {
80 type Target = StateData;
81
82 fn deref(&self) -> &Self::Target {
83 unsafe { &*self.ptr }
84 }
85}
86
87impl DerefMut for StateGuard<'_> {
88 fn deref_mut(&mut self) -> &mut Self::Target {
89 unsafe { &mut *self.ptr }
90 }
91}
92
93#[derive(Clone, Default, Debug)]
94pub struct StateSnapshot {
95 pub tracks: HashMap<String, TrackHandle>,
96 pub unused_audio_clips: Vec<AudioClipData>,
97 pub unused_midi_clips: Vec<MidiClipData>,
98}
99
100impl State {
101 pub fn lock(&self) -> StateGuard<'_> {
102 StateGuard {
103 ptr: self.inner.get(),
104 _marker: PhantomData,
105 }
106 }
107
108 pub fn snapshot(&self) -> StateSnapshot {
109 StateData::snapshot(self)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn state_default_creates_empty() {
119 let state = State::default();
120 assert!(state.lock().tracks.is_empty());
121 }
122
123 #[test]
124 fn state_debug_format() {
125 let state = State::default();
126 let debug_str = format!("{:?}", state);
127 assert!(debug_str.contains("State"));
128 assert!(debug_str.contains("tracks"));
129 }
130
131 #[test]
132 fn state_new_is_default() {
133 let state1 = State::default();
134 let state2 = State::default();
135 assert_eq!(state1.lock().tracks.len(), state2.lock().tracks.len());
136 }
137
138 #[test]
139 fn state_snapshot_clones_track_handles() {
140 let state = State::default();
141 let track = Arc::new(Track::new("track".to_string(), 1, 1, 0, 0, 64, 48_000.0));
142 state
143 .lock()
144 .tracks
145 .insert("track".to_string(), track.clone());
146
147 let snapshot = state.snapshot();
148
149 assert!(Arc::ptr_eq(snapshot.tracks.get("track").unwrap(), &track));
150 }
151}