### Setup and Build on Linux Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Installs dependencies, sets up the Rust environment, and builds the project from source. ```sh # Install basic stuff sudo apt update sudo apt install curl git build-essential pkg-config libssl-dev liblzma-dev llvm-dev libclang-dev clang -y # Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # choose 1 (default) source $HOME/.cargo/env # Using nightly is not necessary if you want to build just the low-level, medium-level or high-level API! rustup default stable-x86_64-unknown-linux-gnu # Clone reaper-rs cd Downloads git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git cd reaper-rs # Build reaper-rs cargo build ``` -------------------------------- ### Install Rust on macOS Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Downloads and installs the Rust toolchain via rustup. ```sh # Install Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # choose 1 (default) source $HOME/.cargo/env ``` -------------------------------- ### Reactive Extensions Example Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Shows how to use reactive extensions (`reaper-rx`) with rxRust to subscribe to events, such as track removal notifications. ```rust rx.track_removed().subscribe(|t| println!("Track {{:?}} removed", t)); ``` -------------------------------- ### Low-Level API Example Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Demonstrates basic operations using the raw, unsafe low-level REAPER API. Use with caution as it bypasses type safety. ```rust unsafe { reaper.ShowConsoleMsg(c"Hello world from reaper-rs low-level API!"); let track = reaper.GetTrack(null_mut(), 0); reaper.DeleteTrack(track); } ``` -------------------------------- ### High-Level API Example Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Illustrates usage of the high-level API, which employs object-oriented paradigms for a safer and more intuitive experience without `unsafe` blocks. ```rust reaper.show_console_msg("Hello world from reaper-rs high-level API!"); let project = reaper.current_project(); let track = project.track_by_index(0).ok_or("no tracks")?; project.remove_track(&track); ``` -------------------------------- ### Clone and Build reaper-rs Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Clone the reaper-rs repository and build the project using Cargo. Ensure you have the stable Rust toolchain installed. ```bash rustup default stable-x86_64-apple-darwin cd Downloads git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git cd reaper-rs cargo build ``` -------------------------------- ### Implement REAPER Audio Hook Source: https://context7.com/helgoboss/reaper-rs/llms.txt Implement the `OnAudioBuffer` trait for real-time audio processing. This hook runs in the real-time audio thread, so avoid allocations, blocking, or locks. This example logs every 100 callbacks and reads MIDI input. ```rust use reaper_medium::{ ReaperSession, OnAudioBuffer, OnAudioBufferArgs, Reaper, RealTimeAudioThreadScope, MidiInputDeviceId }; struct MyAudioHook { counter: u64, reaper: Reaper, } impl OnAudioBuffer for MyAudioHook { fn call(&mut self, args: OnAudioBufferArgs) { // This runs in the real-time audio thread! // Be careful: no allocations, no blocking, no locks self.counter += 1; // Log every 100 callbacks (not recommended in production) if self.counter % 100 == 0 { // Access audio buffer info let sample_rate = args.reg.sample_rate(); let num_samples = args.reg.nch(); } // Read MIDI input from device 0 self.reaper.get_midi_input(MidiInputDeviceId::new(0), |input| -> Option<()> { let input = input?; for event in input.get_read_buf().enum_items(0) { // Process MIDI event println!("MIDI: {:?}", event); } Some(()) }); } } fn register_audio_hook(session: &mut ReaperSession) { let rt_reaper = session.create_real_time_reaper(); let hook = Box::new(MyAudioHook { counter: 0, reaper: rt_reaper, }); let handle = session.audio_reg_hardware_hook_add(hook) .expect("Failed to register audio hook"); // Store handle to unregister later } ``` -------------------------------- ### Implement REAPER Custom Command Source: https://context7.com/helgoboss/reaper-rs/llms.txt Implement the `HookCommand` trait to handle custom actions triggered by REAPER. This example defines a simple command handler that prints a message when executed. ```rust use reaper_medium::{ ReaperSession, HookCommand, CommandId, OwnedGaccelRegister, Accel, AccelMsg }; // Define command handler struct MyHookCommand; impl HookCommand for MyHookCommand { fn call(command_id: CommandId, flag: i32) -> bool { // Return true if you handled this command println!("Command {} executed with flag {}", command_id.get(), flag); true } } fn register_action(session: &mut ReaperSession) { // Register a unique command ID let command_id = session.plugin_register_add_command_id("MY_CUSTOM_ACTION") .expect("Failed to register command ID"); // Create keyboard shortcut (Ctrl+Shift+A) let accel = Accel::new( AccelMsg::new().with_control(true).with_shift(true), 65 // 'A' key ); // Register the action with description let register = OwnedGaccelRegister::new(accel, command_id, "My Custom Action"); session.plugin_register_add_gaccel(register) .expect("Failed to register action"); // Register the hook command to handle execution session.plugin_register_add_hook_command::() .expect("Failed to register hook command"); } ``` -------------------------------- ### Implement REAPER Control Surface Source: https://context7.com/helgoboss/reaper-rs/llms.txt Implement the `ControlSurface` trait to receive REAPER state changes. Callbacks are provided for track and transport events. This example shows basic logging for volume and playback state changes. ```rust use reaper_medium::{ ControlSurface, ReaperSession, SetSurfaceVolumeArgs, SetPlayStateArgs, SetTrackTitleArgs, MediaTrack }; #[derive(Debug)] struct MyControlSurface { track_count: u32, } impl ControlSurface for MyControlSurface { // Called approximately 30 times per second fn run(&mut self) { // Perform periodic tasks here } // Called when track list changes fn set_track_list_change(&self) { println!("Track list changed!"); } // Called when track volume changes fn set_surface_volume(&self, args: SetSurfaceVolumeArgs) { println!("Track volume changed to: {:?}", args.volume); } // Called when transport state changes (play/pause/record) fn set_play_state(&self, args: SetPlayStateArgs) { if args.is_playing { println!("Playback started"); } else if args.is_paused { println!("Playback paused"); } else { println!("Playback stopped"); } } // Called when track name changes fn set_track_title(&self, args: SetTrackTitleArgs) { println!("Track renamed"); } } fn register_control_surface(session: &mut ReaperSession) { let surface = Box::new(MyControlSurface { track_count: 0 }); let handle = session.plugin_register_add_csurf_inst(surface) .expect("Failed to register control surface"); // Keep handle to unregister later if needed } ``` -------------------------------- ### Medium-Level API Control Surface Registration Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Example of registering a custom control surface implementation with the REAPER session using the medium-level API. Requires implementing the `ControlSurface` trait. ```rust struct MyControlSurface; impl ControlSurface for MyControlSurface { fn set_track_list_change(&self) { println!("Tracks changed"); } } session.plugin_register_add_csurf_inst(MyControlSurface); ``` -------------------------------- ### Clone Repository and Build on Windows Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Downloads the project source and compiles it using Cargo. ```batch git clone --recurse-submodules https://github.com/helgoboss/reaper-rs.git cd reaper-rs cargo build ``` -------------------------------- ### Initialize ReaperSession and access API Source: https://context7.com/helgoboss/reaper-rs/llms.txt Demonstrates creating a session from the plugin context and accessing core REAPER functions like console messaging and project information. ```rust use reaper_medium::{ReaperSession, ProjectContext::CurrentProject}; use reaper_low::PluginContext; fn initialize_session(context: PluginContext) { // Create a new session from plug-in context let session = ReaperSession::load(context); // Access REAPER functions through the Reaper instance let reaper = session.reaper(); // Print to REAPER console reaper.show_console_msg("Session initialized!\n"); // Get track count in current project let track_count = reaper.count_tracks(CurrentProject); reaper.show_console_msg(format!("Project has {} tracks\n", track_count)); // Get app version info let version = reaper.get_app_version(); reaper.show_console_msg(format!("REAPER version: {}\n", version)); } ``` -------------------------------- ### Implement REAPER Extension Entry Point Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Basic implementation of a REAPER extension using the reaper_extension_plugin macro. ```rust use std::error::Error; use reaper_macros::reaper_extension_plugin; use reaper_low::PluginContext; use reaper_medium::ReaperSession; #[reaper_extension_plugin] fn plugin_main(context: PluginContext) -> Result<(), Box> { let session = ReaperSession::load(context); session.reaper().show_console_msg("Hello world from reaper-rs medium-level API!"); Ok(()) } ``` -------------------------------- ### Bootstrap a REAPER extension plugin Source: https://context7.com/helgoboss/reaper-rs/llms.txt Uses the reaper_extension_plugin macro to generate the required entry point and handle DLL initialization. ```rust use std::error::Error; use reaper_macros::reaper_extension_plugin; use reaper_low::PluginContext; use reaper_medium::ReaperSession; #[reaper_extension_plugin] fn plugin_main(context: PluginContext) -> Result<(), Box> { let session = ReaperSession::load(context); session.reaper().show_console_msg("Hello world from reaper-rs!"); Ok(()) } ``` -------------------------------- ### Create a REAPER-aware VST Plugin Source: https://context7.com/helgoboss/reaper-rs/llms.txt Initializes a VST plugin that attempts to access the REAPER context when loaded within the host. Requires the reaper-low and reaper-medium crates. ```rust use vst::plugin::{Info, Plugin, HostCallback}; use reaper_low::{PluginContext, reaper_vst_plugin, static_plugin_context}; use reaper_medium::ReaperSession; reaper_vst_plugin!(); #[derive(Default)] struct MyReaperVstPlugin { host: HostCallback, session: Option, } impl Plugin for MyReaperVstPlugin { fn new(host: HostCallback) -> Self { Self { host, session: None } } fn get_info(&self) -> Info { Info { name: "My REAPER VST".to_string(), unique_id: 12345, inputs: 2, outputs: 2, ..Default::default() } } fn init(&mut self) { // Try to get REAPER context (only works when loaded in REAPER) if let Ok(context) = PluginContext::from_vst_plugin(&self.host, static_plugin_context()) { let session = ReaperSession::load(context); session.reaper().show_console_msg("VST plugin loaded in REAPER!\n"); self.session = Some(session); } } } vst::plugin_main!(MyReaperVstPlugin); ``` -------------------------------- ### Perform REAPER project operations Source: https://context7.com/helgoboss/reaper-rs/llms.txt Demonstrates how to iterate through open project tabs, validate project pointers, open files, and track state changes. ```rust use reaper_medium::{Reaper, ProjectRef, ProjectContext, MainThreadScope}; fn project_operations(reaper: &Reaper) { // Enumerate all open project tabs for i in 0.. { match reaper.enum_projects(ProjectRef::Tab(i), 256) { Some(result) => { println!("Project {}: {:?}", i, result.file_path); } None => break, // No more projects } } // Get current project let current = reaper.enum_projects(ProjectRef::Current, 0) .expect("No current project"); // Check if a project pointer is still valid let is_valid = reaper.validate_ptr_2( ProjectContext::CurrentProject, current.project ); // Open a project file reaper.main_open_project( camino::Utf8Path::new("/path/to/project.rpp"), reaper_medium::OpenProjectBehavior { open_as_template: false, prompt: true, } ); // Get project state change count (useful for detecting changes) let state_count = reaper.get_project_state_change_count(ProjectContext::CurrentProject); } ``` -------------------------------- ### Build Docker Image for reaper-low Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Build a Docker image containing Rust, LLVM, and Clang, necessary for regenerating the low-level API. ```docker # Build image (official Rust image + LLVM and Clang) docker build --tag rust-for-reaper-rs . ``` -------------------------------- ### Configure Cargo.toml for REAPER Extension Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Required dependencies and crate configuration for a REAPER extension plug-in. ```toml [dependencies] reaper-medium = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } reaper-low = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } reaper-macros = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } [lib] name = "reaper_my_extension" crate-type = ["cdylib"] ``` -------------------------------- ### Set Default Rust Toolchain on Windows Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Configures the stable MSVC toolchain for Windows development. ```batch rustup default stable-x86_64-pc-windows-msvc ``` -------------------------------- ### Interact with Projects and Tracks via High-Level API Source: https://context7.com/helgoboss/reaper-rs/llms.txt Demonstrates object-oriented access to projects, tracks, FX chains, and track properties. Uses the reaper-high crate for simplified management. ```rust use reaper_high::{Reaper, Project, Track}; fn high_level_example() { let reaper = Reaper::get(); // Get current project let project = reaper.current_project(); // Iterate tracks for track in project.tracks() { if let Some(name) = track.name() { println!("Track: {}", name.to_str()); } // Get FX chain let fx_chain = track.normal_fx_chain(); for fx in fx_chain.fxs() { println!(" FX: {}", fx.name().to_str()); } } // Get track by index if let Some(track) = project.track_by_index(0) { // Set track name track.set_name("Lead Vocal"); // Set track color track.set_custom_color(Some(reaper_medium::RgbColor::new(255, 0, 0))); // Add item to track if let Ok(item) = track.add_item() { println!("Added new item to track"); } } // Get selected tracks for track in project.selected_tracks(reaper_medium::MasterTrackBehavior::ExcludeMasterTrack) { println!("Selected: {:?}", track.name()); } } ``` -------------------------------- ### Link Test Plugins on Linux Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Creates symbolic links to make compiled test plugins available to the REAPER application. ```sh mkdir -p $HOME/.config/REAPER/UserPlugins/FX ln -s $HOME/Downloads/reaper-rs/target/debug/libreaper_test_extension_plugin.so $HOME/.config/REAPER/UserPlugins/reaper_test_extension_plugin.so ln -s $HOME/Downloads/reaper-rs/target/debug/libreaper_test_vst_plugin.so $HOME/.config/REAPER/UserPlugins/FX/reaper_test_vst_plugin.so ``` -------------------------------- ### Medium-Level API Basics Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Shows fundamental usage of the medium-level API, which provides type-safe bindings to the original REAPER C++ API. This is the recommended API for general use. ```rust reaper.show_console_msg("Hello world from reaper-rs medium-level API!"); let track = reaper.get_track(CurrentProject, 0).ok_or("no tracks")?; unsafe { reaper.delete_track(track); } ``` -------------------------------- ### Regenerate reaper-low API with Docker Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Run a Docker container to build the reaper-low package with the 'generate' feature. This ensures deterministic results for API regeneration. ```docker # Build reaper-low with feature "generate" docker run --rm --user "$(id -u)":"$(id -g)" -v "$PWD":/usr/src/myapp -w /usr/src/myapp rust-for-reaper-rs cargo build --package reaper-low --features generate ``` -------------------------------- ### REAPER VST Plug-in Implementation in Rust Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md This Rust code implements a basic REAPER VST plug-in. It uses the `vst-rs` crate for the VST structure and `reaper-rs` to interact with the REAPER API, specifically showing a console message on initialization. ```rust use vst::plugin::{Info, Plugin, HostCallback}; use reaper_low::{PluginContext, reaper_vst_plugin, static_plugin_context}; use reaper_medium::ReaperSession; reaper_vst_plugin!(); #[derive(Default)] struct MyReaperVstPlugin { host: HostCallback, } impl Plugin for MyReaperVstPlugin { fn new(host: HostCallback) -> Self { Self { host } } fn get_info(&self) -> Info { Info { name: "My REAPER VST plug-in".to_string(), unique_id: 6830, ..Default::default() } } fn init(&mut self) { if let Ok(context) = PluginContext::from_vst_plugin(&self.host, static_plugin_context()) { let session = ReaperSession::load(context); session .reaper() .show_console_msg("Hello world from reaper-rs medium-level API!"); } } } vst::plugin_main!(MyReaperVstPlugin); ``` -------------------------------- ### Format Code with Cargo Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Format the project's code using Cargo's built-in formatting tool. ```bash cargo fmt ``` -------------------------------- ### Process MIDI Input and Output Source: https://context7.com/helgoboss/reaper-rs/llms.txt Accesses MIDI devices to read and write messages within the real-time audio thread. Uses RealTimeAudioThreadScope for thread safety. ```rust use reaper_medium::{ Reaper, RealTimeAudioThreadScope, MidiInputDeviceId, MidiOutputDeviceId }; fn process_midi(reaper: &Reaper) { // Read from MIDI input device reaper.get_midi_input(MidiInputDeviceId::new(0), |input| -> Option<()> { let input = input?; let read_buf = input.get_read_buf(); for event in read_buf.enum_items(0) { let msg = event.message(); // Process MIDI message // msg contains status byte, data1, data2 } Some(()) }); // Write to MIDI output reaper.get_midi_output(MidiOutputDeviceId::new(0), |output| -> Option<()> { let output = output?; // Send MIDI note on: channel 0, note 60, velocity 100 output.send_msg(&[0x90, 60, 100], -1); Some(()) }); } ``` -------------------------------- ### Regenerate Low-level API on Linux Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Triggers the generation of low-level API bindings using the specified feature flag. ```sh cd main/low cargo build --features generate cargo fmt ``` -------------------------------- ### Cargo.toml Dependencies for REAPER VST Plug-in Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Add these dependencies to your Cargo.toml file to build a REAPER VST plug-in. This includes the necessary reaper-rs crates and the vst crate. ```toml [dependencies] reaper-medium = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } reaper-low = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } vst = "0.2.0" [lib] name = "my_reaper_vst_plugin" crate-type = ["cdylib"] ``` -------------------------------- ### Subscribe to REAPER Events with Reactive Extensions Source: https://context7.com/helgoboss/reaper-rs/llms.txt Uses rxRust to handle state changes such as track modifications, volume adjustments, and transport status. Requires the reaper-rx crate. ```rust use reaper_rx::ControlSurfaceRx; use rxrust::prelude::*; fn setup_reactive_handlers(rx: &ControlSurfaceRx) { // Subscribe to track added events rx.track_added().subscribe(|track| { println!("Track added: {:?}", track.name()); }); // Subscribe to track removed events rx.track_removed().subscribe(|track| { println!("Track removed: {:?}", track.guid()); }); // Subscribe to volume changes rx.track_volume_changed().subscribe(|track| { println!("Volume changed on track"); }); // Subscribe to FX parameter changes rx.fx_parameter_value_changed().subscribe(|param| { println!("FX parameter changed"); }); // Subscribe to play state changes rx.play_state_changed().subscribe(|_| { println!("Transport state changed"); }); // Subscribe to project switches rx.project_switched().subscribe(|project| { println!("Switched to project"); }); } ``` -------------------------------- ### Manipulate tracks using medium-level API Source: https://context7.com/helgoboss/reaper-rs/llms.txt Shows how to retrieve, inspect, and modify track properties such as names, volume, and mute state, as well as inserting new tracks. ```rust use reaper_medium::{Reaper, ProjectContext::CurrentProject, MainThreadScope}; fn manipulate_tracks(reaper: &Reaper) { // Get track by index (0-based) if let Some(track) = reaper.get_track(CurrentProject, 0) { // Get track name (with closure for safe string access) reaper.get_set_media_track_info_get_name(track, |name| { println!("First track name: {}", name.to_str()); }); // Get track volume let volume = unsafe { reaper.get_media_track_info_value(track, reaper_medium::TrackAttributeKey::Vol) }; println!("Track volume: {}", volume); // Set track mute state unsafe { reaper.set_media_track_info_value( track, reaper_medium::TrackAttributeKey::Mute, 1.0 // 1.0 = muted, 0.0 = unmuted ).expect("Failed to set mute"); } } // Insert a new track at index 0 reaper.insert_track_at_index(0, reaper_medium::TrackDefaultsBehavior::OmitDefaultEnvAndFx); // Count total tracks let total = reaper.count_tracks(CurrentProject); reaper.show_console_msg(format!("Total tracks: {}\n", total)); } ``` -------------------------------- ### Add reaper-rs Dependencies to Cargo.toml Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Include these lines in your Cargo.toml file to add reaper-rs as a dependency. It is recommended to use the git repository for the latest changes. ```toml reaper-medium = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } reaper-low = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } reaper-macros = { git = "https://github.com/helgoboss/reaper-rs.git", branch = "master" } ``` -------------------------------- ### Medium-Level API Audio Hook Registration Source: https://github.com/helgoboss/reaper-rs/blob/master/README.md Demonstrates how to register a custom audio processing hook using the medium-level API. The `OnAudioBuffer` trait must be implemented for the hook. ```rust struct MyOnAudioBuffer { counter: u64 } impl OnAudioBuffer for MyOnAudioBuffer { fn call(&mut self, args: OnAudioBufferArgs) { if self.counter % 100 == 0 { println!("Audio hook callback counter: {{}}\n", self.counter); } self.counter += 1; } } session.audio_reg_hardware_hook_add(MyOnAudioBuffer { counter: 0 }); ``` -------------------------------- ### Register REAPER Custom Action Source: https://context7.com/helgoboss/reaper-rs/llms.txt Registers a custom command ID, associates it with a keyboard shortcut, and hooks the command execution. This allows custom actions to be triggered within REAPER. ```rust fn register_action(session: &mut ReaperSession) { // Register a unique command ID let command_id = session.plugin_register_add_command_id("MY_CUSTOM_ACTION") .expect("Failed to register command ID"); // Create keyboard shortcut (Ctrl+Shift+A) let accel = Accel::new( AccelMsg::new().with_control(true).with_shift(true), 65 // 'A' key ); // Register the action with description let register = OwnedGaccelRegister::new(accel, command_id, "My Custom Action"); session.plugin_register_add_gaccel(register) .expect("Failed to register action"); // Register the hook command to handle execution session.plugin_register_add_hook_command::() .expect("Failed to register hook command"); } ``` -------------------------------- ### Register REAPER Control Surface Instance Source: https://context7.com/helgoboss/reaper-rs/llms.txt Registers an instance of a custom `ControlSurface` with the REAPER session. The returned handle can be used to unregister the surface later. ```rust fn register_control_surface(session: &mut ReaperSession) { let surface = Box::new(MyControlSurface { track_count: 0 }); let handle = session.plugin_register_add_csurf_inst(surface) .expect("Failed to register control surface"); // Keep handle to unregister later if needed } ``` -------------------------------- ### Register REAPER Audio Hook Source: https://context7.com/helgoboss/reaper-rs/llms.txt Registers a custom audio hook with the REAPER session. This allows for real-time audio processing. The returned handle can be used to unregister the hook. ```rust fn register_audio_hook(session: &mut ReaperSession) { let rt_reaper = session.create_real_time_reaper(); let hook = Box::new(MyAudioHook { counter: 0, reaper: rt_reaper, }); let handle = session.audio_reg_hardware_hook_add(hook) .expect("Failed to register audio hook"); // Store handle to unregister later } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.