Reorganize top-level directories with clearer naming convention

app -> app-desktop-macos, presets -> app-presets, server -> remote-server,
daw-config-reaper -> osc-config-daw, plugin-reaper-realearn -> plugin-reaper-relearn.
Updated run.py and presets.py path references accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Paul Lipscomb
2026-07-15 17:51:05 -04:00
parent e58f06d9fa
commit 7ecc718f5d
2256 changed files with 11 additions and 5 deletions
@@ -0,0 +1,92 @@
use anyhow::{ensure, Context};
use camino::Utf8Path;
use reaper_high::Reaper;
use reaper_low::raw;
use reaper_medium::{
FlexibleOwnedPcmSource, Handle, MeasureAlignment, MidiImportBehavior, OwnedPreviewRegister,
PositionInSeconds, ReaperMutex, ReaperMutexGuard, ReaperVolumeValue,
};
use std::cell::Cell;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct SoundPlayer {
preview_register: Arc<ReaperMutex<OwnedPreviewRegister>>,
play_handle: Cell<Option<Handle<raw::preview_register_t>>>,
}
unsafe impl Send for SoundPlayer {}
impl Default for SoundPlayer {
fn default() -> Self {
Self::new()
}
}
impl SoundPlayer {
pub fn new() -> Self {
let mut register = OwnedPreviewRegister::new();
register.set_volume(ReaperVolumeValue::ZERO_DB);
let preview_register = Arc::new(ReaperMutex::new(register));
Self {
preview_register,
play_handle: Cell::new(None),
}
}
pub fn load_file(&mut self, path_to_file: &Utf8Path) -> anyhow::Result<()> {
ensure!(path_to_file.exists(), "sound file doesn't exist");
let source = Reaper::get()
.medium_reaper()
.pcm_source_create_from_file_ex(path_to_file, MidiImportBehavior::UsePreference)?;
self.load_pcm_source(FlexibleOwnedPcmSource::Reaper(source))
}
pub fn load_pcm_source(&mut self, source: FlexibleOwnedPcmSource) -> anyhow::Result<()> {
let mut preview_register = self.lock_preview_register()?;
preview_register.set_src(Some(source));
Ok(())
}
pub fn volume(&self) -> anyhow::Result<ReaperVolumeValue> {
let preview_register = self.lock_preview_register()?;
Ok(preview_register.volume())
}
pub fn set_volume(&self, volume: ReaperVolumeValue) -> anyhow::Result<()> {
let mut preview_register = self.lock_preview_register()?;
preview_register.set_volume(volume);
Ok(())
}
pub fn play(&self) -> anyhow::Result<()> {
if self.play_handle.get().is_some() {
// Is playing already. Simply rewind.
let mut preview_register = self.lock_preview_register()?;
preview_register.set_cur_pos(PositionInSeconds::ZERO);
} else {
// Is not yet playing. Start playing.
let handle = Reaper::get().medium_session().play_preview_ex(
self.preview_register.clone(),
Default::default(),
MeasureAlignment::PlayImmediately,
)?;
self.play_handle.set(Some(handle));
}
Ok(())
}
pub fn stop(&self) -> anyhow::Result<()> {
let play_handle = self.play_handle.take().context("not playing")?;
Reaper::get().medium_session().stop_preview(play_handle)?;
self.lock_preview_register()?
.set_cur_pos(PositionInSeconds::ZERO);
Ok(())
}
fn lock_preview_register(&self) -> anyhow::Result<ReaperMutexGuard<OwnedPreviewRegister>> {
self.preview_register
.lock()
.context("couldn't acquire preview register lock in sound player")
}
}