|
@@ -13,7 +13,8 @@ use crate::serde::ser::SerializeMap;
|
|
|
use std::sync::MutexGuard;
|
|
|
// pub fn collect
|
|
|
use log::*;
|
|
|
-
|
|
|
+use std::collections::hash_map::DefaultHasher;
|
|
|
+use std::hash::{Hash, Hasher};
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
|
|
pub struct Sound {
|
|
@@ -36,6 +37,22 @@ pub struct Sound {
|
|
|
pub reverse: bool
|
|
|
}
|
|
|
|
|
|
+impl PartialEq for Sound {
|
|
|
+ fn eq(&self, other: &Self) -> bool {
|
|
|
+ self.name == other.name
|
|
|
+ && self.volume == other.volume
|
|
|
+ && self.roll == other.roll
|
|
|
+ && self.speed == other.speed
|
|
|
+ && self.trim == other.trim
|
|
|
+ }
|
|
|
+}
|
|
|
+// impl Hash for Sound {
|
|
|
+// fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
+// self.name.hash(state);
|
|
|
+// self.volume.hash(state);
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
impl AsRef<[u8]> for Sound {
|
|
|
fn as_ref(&self) -> &[u8] {
|
|
|
&self.data
|
|
@@ -66,6 +83,13 @@ impl Sound {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ pub fn extended_display(&self) -> String {
|
|
|
+ format!(
|
|
|
+ "{} V{} S{} R{} T{}", self.name.replace(".wav", ""), self.volume, self.speed, self.roll, self.trim
|
|
|
+ )
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
pub fn duration(&self) -> Option<Duration> {
|
|
|
|
|
|
// let file = File::open(&self.location).unwrap();
|
|
@@ -89,16 +113,6 @@ impl Sound {
|
|
|
}
|
|
|
|
|
|
pub fn cloned(&self) -> Sound {
|
|
|
- // let mut s = Sound::default();
|
|
|
- // s.data = self.data.clone();
|
|
|
- // s.name = self.name.clone();
|
|
|
- // s.location = self.location.clone();
|
|
|
- // s.roll = self.roll;
|
|
|
- // s.rollrate = self.rollrate;
|
|
|
- // s.speed = self.speed;
|
|
|
- // s.volume = self.volume;
|
|
|
- // s.trim = self.trim;
|
|
|
-
|
|
|
let mut clone = self.clone();
|
|
|
clone.active = Arc::from(Mutex::from(false));
|
|
|
clone
|
|
@@ -282,10 +296,10 @@ pub struct Pattern {
|
|
|
pub resolution: i32,
|
|
|
pub xsize: usize,
|
|
|
pub ysize: usize,
|
|
|
- #[serde(serialize_with="ser_sounds", deserialize_with="de_sounds")]
|
|
|
- pub sounds: HashMap<(usize, usize), Sound>,
|
|
|
+ // #[serde(serialize_with="ser_sounds", deserialize_with="de_sounds")]
|
|
|
+ // pub sounds: HashMap<(usize, usize), Sound>,
|
|
|
#[serde(serialize_with="ser_snds", deserialize_with="de_snds")]
|
|
|
- pub snds: Arc<Mutex<HashMap<(usize, usize), Sound>>>
|
|
|
+ pub sounds: Arc<Mutex<HashMap<(usize, usize), Sound>>>
|
|
|
}
|
|
|
|
|
|
/// Some basic defaults for a pattern.
|
|
@@ -297,8 +311,8 @@ impl Default for Pattern {
|
|
|
resolution: 8,
|
|
|
xsize: 8,
|
|
|
ysize: 1,
|
|
|
- sounds: HashMap::new(),
|
|
|
- snds: Arc::new(Mutex::new(HashMap::new()))
|
|
|
+ // sounds: HashMap::new(),
|
|
|
+ sounds: Arc::new(Mutex::new(HashMap::new()))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -349,7 +363,7 @@ impl Pattern {
|
|
|
let device = device.clone();
|
|
|
let delay = self.get_sample_spacing(bpm);
|
|
|
|
|
|
- let snds = self.snds.clone();
|
|
|
+ let snds = self.sounds.clone();
|
|
|
thread::spawn(move || {
|
|
|
|
|
|
// loop for repeats
|
|
@@ -397,11 +411,11 @@ impl Pattern {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// Replace all souds in a row by a new sound.
|
|
|
+ /// Replace all sounds in a row by a new sound.
|
|
|
/// This only replaces the source, leaving other settings intact.
|
|
|
pub fn replace_sound_sources(&mut self, new_sound: &Sound, row: usize) {
|
|
|
for x in 0..self.xsize {
|
|
|
- if let Some(snd) = self.snds.lock().unwrap().get_mut(&(x, row)) {
|
|
|
+ if let Some(snd) = self.sounds.lock().unwrap().get_mut(&(x, row)) {
|
|
|
info!("replacing {} with {}", snd.name, new_sound.name);
|
|
|
snd.location = new_sound.location.clone();
|
|
|
snd.data = new_sound.data.clone();
|
|
@@ -412,37 +426,51 @@ impl Pattern {
|
|
|
|
|
|
/// Insert a sound
|
|
|
pub fn insert_sound(&mut self, pos: &(usize, usize), snd: &Sound) {
|
|
|
- self.snds.lock().unwrap().insert(*pos, snd.clone());
|
|
|
+ self.sounds.lock().unwrap().insert(*pos, snd.clone());
|
|
|
}
|
|
|
|
|
|
/// Remove a sound
|
|
|
pub fn remove_sound(&mut self, pos: &(usize, usize)) {
|
|
|
- self.snds.lock().unwrap().remove(pos);
|
|
|
+ self.sounds.lock().unwrap().remove(pos);
|
|
|
}
|
|
|
|
|
|
/// Check if a pattern contains a sound
|
|
|
pub fn contains_sound(&self, pos: &(usize, usize)) -> bool {
|
|
|
- self.snds.lock().unwrap().contains_key(pos)
|
|
|
+ self.sounds.lock().unwrap().contains_key(pos)
|
|
|
}
|
|
|
|
|
|
- /// Return a MutexGuard to the sounds
|
|
|
- pub fn sounds(&self) -> MutexGuard<HashMap<(usize, usize), Sound>> {
|
|
|
- self.snds.lock().unwrap()
|
|
|
- }
|
|
|
|
|
|
/// Get a sound from a pattern
|
|
|
pub fn get_sound(&self, pos: &(usize, usize)) -> Option<Sound> {
|
|
|
- self.snds.lock().unwrap()
|
|
|
+ self.sounds.lock().unwrap()
|
|
|
.get(pos)
|
|
|
.map(|s| s.clone())
|
|
|
}
|
|
|
|
|
|
|
|
|
+ pub fn get_all_sounds(&self) -> Vec<Sound> {
|
|
|
+ let mut sounds = vec![];
|
|
|
+
|
|
|
+ for x in 0..self.xsize {
|
|
|
+ for y in 0..self.ysize {
|
|
|
+
|
|
|
+ if let Some(snd) = self.sounds.lock().unwrap().get_mut(&(x, y)) {
|
|
|
+ if !sounds.contains(snd) {
|
|
|
+
|
|
|
+ sounds.push(snd.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sounds
|
|
|
+ }
|
|
|
+
|
|
|
/// Replace all souds in a row by a new sound.
|
|
|
/// This only replaces the source, leaving other settings intact.
|
|
|
pub fn replace_sounds(&mut self, new_sound: &Sound, row: usize) {
|
|
|
for x in 0..self.xsize {
|
|
|
- if let Some(snd) = self.sounds.get_mut(&(x, row)) {
|
|
|
+ if let Some(snd) = self.sounds.lock().unwrap().get_mut(&(x, row)) {
|
|
|
*snd = new_sound.clone();
|
|
|
}
|
|
|
|
|
@@ -454,7 +482,7 @@ impl Pattern {
|
|
|
let mut names: HashMap<String, usize> = HashMap::new();
|
|
|
|
|
|
for x in 0..self.xsize {
|
|
|
- if let Some(snd) = self.snds.lock().unwrap().get(&(x, row)) {
|
|
|
+ if let Some(snd) = self.sounds.lock().unwrap().get(&(x, row)) {
|
|
|
match names.get_mut(&snd.name) {
|
|
|
Some(v) => *v += 1,
|
|
|
None => {names.insert(snd.name.clone(), 1);},
|
|
@@ -485,14 +513,14 @@ impl Pattern {
|
|
|
|
|
|
/// Clear all sounds in a pattern.
|
|
|
pub fn clear_all(&mut self) {
|
|
|
- self.snds.lock().unwrap().clear();
|
|
|
+ self.sounds.lock().unwrap().clear();
|
|
|
}
|
|
|
|
|
|
/// Reload all sounds in a pattern
|
|
|
pub fn reload_sounds(&mut self) -> Pattern {
|
|
|
for x in 0..self.xsize {
|
|
|
for y in 0..self.ysize {
|
|
|
- if let Some(snd) = self.sounds.get_mut(&(x,y)) {
|
|
|
+ if let Some(snd) = self.sounds.lock().unwrap().get_mut(&(x,y)) {
|
|
|
// println!("RELOAD {:?}", &snd.name);
|
|
|
match snd.updated_from_source() {
|
|
|
Ok(newdata) => snd.data = newdata.data,
|
|
@@ -501,7 +529,8 @@ impl Pattern {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- self.snds = Arc::new(Mutex::new(self.sounds.clone()));
|
|
|
+ // TODO: is this line needed?
|
|
|
+ // self.sounds = Arc::new(Mutex::new(self.sounds.clone()));
|
|
|
self.clone()
|
|
|
}
|
|
|
|