pub struct ReaperSession { /* private fields */ }
Expand description

This is the main hub for accessing medium-level API functions.

In order to use this struct, you first must obtain an instance of it by invoking new() or load(). This struct itself is limited to REAPER functions for registering/unregistering certain things. You can access all the other functions by calling reaper().

Please note that this struct will take care of unregistering everything (also audio hooks) automatically when it gets dropped (good RAII manners).

Design

Why is there a separation into ReaperSession and Reaper?

Functions for registering/unregistering things have been separated from the rest because they require more than just access to REAPER function pointers. They also need data structures to keep track of the registered things and to offer them a warm and cosy place in memory. As a result, this struct gains special importance, needs to be mutable and can’t just be cloned as desired. But there’s no reason why this restriction should also apply to all other REAPER functions. After all, being able to clone and pass things around freely can simplify things a lot.

Example

Here’s an example how things can get difficult without the ability to clone: In order to be able to use REAPER functions also from e.g. the audio hook register, we would need to wrap it in an Arc (not an Rc, because we access it from multiple threads). That’s not enough though for most real-world cases. We probably want to register/unregister things (in the main thread) not only in the beginning but also at a later time. That means we need mutable access. So we end up with Arc<Mutex<ReaperSession>>. However, why going through all that trouble and put up with possible performance issues if we can avoid it?

Implementations

Creates a new instance by getting hold of a low-level Reaper instance.

Loads all available REAPER functions from the given plug-in context.

Returns a medium-level ReaperSession instance which allows you to call these functions.

Gives access to all REAPER functions which can be safely executed in the main thread.

Example

If the REAPER functions are needed somewhere else, just clone them:

let standalone_reaper = session.reaper().clone();

Creates a new container of REAPER functions with only those unlocked that can be safely executed in the real-time audio thread.

This is the primary function for plug-ins to register things.

Things can be keyboard shortcuts, project importers etc. Typically you register things when the plug-in is loaded.

It is not recommended to use this function directly because it’s unsafe. Consider using the safe convenience functions instead. They all start with plugin_register_add_.

The meaning of the return value depends very much on the actual thing being registered. In most cases it just returns 1. In any case, if it’s not 0, reaper-rs translates this into an error.

Also see plugin_register_remove().

Errors

Returns an error if the registration failed.

Safety

REAPER can crash if you pass an invalid pointer or if it dangles during the time it is registered. So you must ensure that the registered thing lives long enough and has a stable address in memory. Additionally, mutation of the thing while it is registered can lead to subtle bugs.

Unregisters things that you have registered with plugin_register_add().

Please note that unregistering things manually just for cleaning up is unnecessary in most situations because reaper-rs takes care of automatically unregistering everything when this struct is dropped (RAII). This happens even when using the unsafe function variants.

Safety

REAPER can crash if you pass an invalid pointer.

Registers a hook command.

REAPER calls hook commands whenever an action is requested to be run.

This method doesn’t take a closure because REAPER expects a plain function pointer here. Unlike audio_reg_hardware_hook_add, REAPER doesn’t offer the possibiity to pass a context to the function. So we can’t access any context data in the hook command. You will probably have to use a kind of static variable which contains command IDs in order to make proper use of this method. The high-level API makes that much easier (it just takes an arbitrary closure). For the medium-level API this is out of scope.

Errors

Returns an error if the registration failed.

Example
use reaper_medium::{HookCommand, CommandId};

// Usually you would use a dynamic command ID that you have obtained via
// `plugin_register_add_command_id()`. Unfortunately that command ID must be exposed as
// a static variable. The high-level API provides a solution for that.
const MY_COMMAND_ID: CommandId = unsafe { CommandId::new_unchecked(42000) };

struct MyHookCommand;

impl HookCommand for MyHookCommand {
    fn call(command_id: CommandId, _flag: i32) -> bool {
        if command_id != MY_COMMAND_ID {
            return false;
        }           
        println!("Executing my command!");
        true
    }
}
session.plugin_register_add_hook_command::<MyHookCommand>();
Design

You will note that this method has a somewhat strange signature: It expects a type parameter only, not a function pointer. That allows us to lift the API to medium-level style. The alternative would have been to expect a function pointer, but then consumers would have to deal with raw types.

Unregisters a hook command.

Registers a hook command that supports MIDI CC/mousewheel actions.

See plugin_register_add_hook_command for understanding how to use this function (it has a very similar design).

Errors

Returns an error if the registration failed.

Unregisters a hook command that supports MIDI CC/mousewheel actions.

Registers a toggle action.

REAPER calls toggle actions whenever it wants to know the on/off state of an action.

See plugin_register_add_hook_command() for an example.

Errors

Returns an error if the registration failed.

Unregisters a toggle action.

source

pub fn plugin_register_add_hook_post_command<T: HookPostCommand>(
    &mut self
) -> Result<(), ReaperFunctionError>

Registers a hook post command.

REAPER calls hook post commands whenever a normal action of the main section has been performed.

See plugin_register_add_hook_command() for an example.

Errors

Returns an error if the registration failed.

source

pub fn plugin_register_remove_hook_post_command<T: HookPostCommand>(&mut self)

Unregisters a hook post command.

source

pub fn plugin_register_add_hook_post_command_2<T: HookPostCommand2>(
    &mut self
) -> Result<(), ReaperFunctionError>

Registers a hook post command 2.

REAPER calls hook post commands 2 whenever a MIDI CC/mousewheel action has been performed.

See plugin_register_add_hook_command() for an example.

Errors

Returns an error if the registration failed.

source

pub fn plugin_register_remove_hook_post_command_2<T: HookPostCommand2>(
    &mut self
)

Unregisters a hook post command 2.

Registers a timer.

The given function will be called regularly until removal. Roughly 30 times per second, just like the run() method of a control surface.

Errors

Returns an error if the registration failed.

Unregisters a timer.

Registers a command ID for the given command name.

The given command name must be a unique identifier with only A-Z and 0-9.

Returns the assigned command ID, an ID which is guaranteed to be unique within the current REAPER session. If the command name is already in use, it just seems to return the ID which has been assigned before.

Errors

Returns an error if the registration failed (e.g. because not supported or out of actions).

Unstable!!!

Safety

You must ensure that the given function pointer is valid.

Registers a an action into the main section.

This consists of a command ID, a description and a default binding for it. It doesn’t include the actual code to be executed when the action runs (use plugin_register_add_hook_command() for that).

This function returns a handle which you can use to unregister the action at any time via plugin_register_remove_gaccel().

Errors

Returns an error if the registration failed.

Design

This function takes ownership of the passed struct in order to take complete care of it. Compared to the alternative of taking a reference or pointer, that releases the API consumer from the responsibilities to guarantee a long enough lifetime and to maintain a stable address in memory. Giving up ownership also means that the consumer doesn’t have access to the struct anymore - which is a good thing, because REAPER should be the new rightful owner of this struct. Thanks to this we don’t need to mark this function as unsafe!

Plays a preview register.

Errors

Returns an error if not successful.

Safety

REAPER can crash if you pass an invalid preview pointer, if the pointer gets stale while still playing, if you don’t properly handle synchronization via mutex or critical section when modifying the register while playing. Use play_preview_ex() if you want to be released from that burden.

Stops a preview that you have played with play_preview_ex_unchecked().

Please note that stopping preview registers manually just for cleaning up is unnecessary in most situations because reaper-rs takes care of automatically unregistering everything when this struct is dropped (RAII). This happens even when using the unsafe function variants.

Errors

Returns an error if not successful.

Safety

REAPER can crash if you pass an invalid pointer.

Plays a preview register on a specific track.

Errors

Returns an error if not successful.

Safety

REAPER can crash if you pass an invalid project or preview pointer, if the pointer gets stale while still playing, if you don’t properly handle synchronization via mutex or critical section when modifying the register while playing. Use play_track_preview_2_ex() if you want to be released from that burden.

Stops a preview that you have played with play_track_preview_2_ex_unchecked().

Please note that stopping preview registers manually just for cleaning up is unnecessary in most situations because reaper-rs takes care of automatically unregistering everything when this struct is dropped (RAII). This happens even when using the unsafe function variants.

Errors

Returns an error if not successful.

Safety

REAPER can crash if you pass an invalid register pointer.

Plays a preview register.

It asks for a shared mutex-protected register because it assumes you want to keep controlling the playback. With the mutex you can safely modify the register on-the-fly while it’s being played by REAPER.

Returns a handle which is necessary to stop the preview at a later time.

Errors

Returns an error if not successful.

Stops a preview that you have played with play_preview_ex().

Errors

Returns an error if not successful (e.g. was not playing).

Plays a preview register on a specific track.

It asks for a shared mutex-protected register because it assumes you want to keep controlling the playback. With the mutex you can safely modify the register on-the-fly while it’s being played by REAPER.

Returns a handle which is necessary to stop the preview at a later time.

Errors

Returns an error if not successful.

Stops a preview that you have played with play_track_preview_2_ex().

Errors

Returns an error if not successful (e.g. was not playing).

Unregisters an action.

Registers a hidden control surface.

This is very useful for being notified by REAPER about all kinds of events in the main thread.

This function returns a handle which you can use to unregister the control surface at any time via plugin_register_remove_csurf_inst().

Errors

Returns an error if the registration failed.

Example
use reaper_medium::ControlSurface;

#[derive(Debug)]
struct MyControlSurface;

impl ControlSurface for MyControlSurface {
    fn set_track_list_change(&self) {
        println!("Tracks changed");
    }
}
session.plugin_register_add_csurf_inst(Box::new(MyControlSurface));

Unregisters a hidden control surface and hands ownership back to you.

If the control surface is not registered, this function just returns None.

This only needs to be called if you explicitly want the control surface to “stop” while your plug-in is still running. You don’t need to call this for cleaning up because this struct takes care of unregistering everything safely when it gets dropped.

Safety

As soon as the returned control surface goes out of scope, it is removed from memory. If you don’t intend to keep the return value around longer, you should be absolutely sure that your control surface is not currently executing any function. Because both this function and any control surface function can only be called by the main thread, this effectively means you must make sure that this removal function is not called by a control surface method itself. That would be like pulling the rug out from under your feet!

This scenario is not hypothetical: The control surface run() method is very suitable for processing arbitrary tasks which it receives via a channel. Let’s say one of these arbitrary tasks calls this removal function. It’s guaranteed that REAPER will not call the run() function anymore after that, yes. But, the run() function itself might not be finished yet and pull another task from the receiver … oops. The receiver is not there anymore because it was owned by the control surface and therefore removed from memory as well. This will lead to a crash.

Ideally, REAPER would really own this control surface, including managing its lifetime. Then REAPER would remove it as soon as the run() function returns. But this is not how the REAPER API works. We must manage the control surface lifetime for REAPER.

Like audio_reg_hardware_hook_add but doesn’t manage memory for you.

Also see audio_reg_hardware_hook_remove_unchecked().

Errors

Returns an error if the registration failed.

Safety

REAPER can crash if you pass an invalid pointer or if it dangles during the time it is registered. So you must ensure that the audio hook register lives long enough and has a stable address in memory. Additionally, incorrectly accessing the audio hook register while it is registered can lead to horrible race conditions and other undefined behavior.

Unregisters the audio hook register that you have registered with audio_reg_hardware_hook_add_unchecked().

Please note that unregistering audio hook registers manually just for cleaning up is unnecessary in most situations because reaper-rs takes care of automatically unregistering everything when this struct is dropped (RAII). This happens even when using the unsafe function variants.

Safety

REAPER can crash if you pass an invalid pointer.

Registers an audio hook register.

This allows you to get called back in the real-time audio thread before and after REAPER’s processing. You should be careful with this because you are entering real-time world.

This function returns a handle which you can use to unregister the audio hook register at any time via audio_reg_hardware_hook_remove() (from the main thread).

Errors

Returns an error if the registration failed.

Example
use reaper_medium::{
    ControlSurface, OnAudioBuffer, OnAudioBufferArgs,
    Reaper, RealTimeAudioThreadScope, MidiInputDeviceId
};

struct MyOnAudioBuffer {
    counter: u64,
    reaper: Reaper<RealTimeAudioThreadScope>,
}

impl OnAudioBuffer for MyOnAudioBuffer {
    fn call(&mut self, args: OnAudioBufferArgs) {
        // Mutate some own state (safe because we are the owner)
        if self.counter % 100 == 0 {
            println!("Audio hook callback counter: {}\n", self.counter);
        }
        self.counter += 1;
        // Read some MIDI events
        self.reaper.get_midi_input(MidiInputDeviceId::new(0), |input| -> Option<()> {
            for event in input?.get_read_buf().enum_items(0) {
                println!("Received MIDI event {:?}", event);
            }
            Some(())
        });
    }
}

session.audio_reg_hardware_hook_add(Box::new(MyOnAudioBuffer {
    counter: 0,
    reaper: session.create_real_time_reaper()
}));

Unregisters an audio hook register and hands ownership back to you.

If the audio hook register is not registered, this function just returns None.

This only needs to be called if you explicitly want the audio hook to “stop” while your plug-in is still running. You don’t need to call this for cleaning up because this struct takes care of unregistering everything safely when it gets dropped.

REAPER guarantees via proper synchronization that after this method returns, the callback is not in the process of being called and also will not be called anymore. However, it is not guaranteed that the last callback invocation has is_post == true.

Trait Implementations

Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Executes the destructor for this type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait. Read more
Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait. Read more
Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s. Read more
Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.