Skip to content

Commit

Permalink
App: Move REAPER arrangement transport stuff to main scope
Browse files Browse the repository at this point in the history
- it's independent from Playtime after all
- better for event handling
  • Loading branch information
helgoboss committed Mar 7, 2024
1 parent 4a5e69c commit 171154b
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 163 deletions.
4 changes: 4 additions & 0 deletions main/src/domain/control_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ pub trait ControlSurfaceEventHandler: Debug {
diff: &DeviceDiff<MidiOutputDeviceId>,
device_config_changed: bool,
);

fn process_reaper_change_events(&self, change_events: &[ChangeEvent]);
}

pub enum RealearnControlSurfaceMainTask<EH: DomainEventHandler> {
Expand Down Expand Up @@ -394,6 +396,8 @@ impl<EH: DomainEventHandler> RealearnControlSurfaceMiddleware<EH> {
if normal_events.is_empty() && monitoring_fx_events.is_empty() {
return;
}
self.event_handler
.process_reaper_change_events(&normal_events);
for i in self.instances() {
i.borrow_mut()
.process_control_surface_change_events(&normal_events);
Expand Down
10 changes: 9 additions & 1 deletion main/src/infrastructure/plugin/backbone_shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ use realearn_api::persistence::{
TrackDescriptor, TrackFxChain,
};
use realearn_api::runtime::{AutoAddedControllerEvent, InfoEvent};
use reaper_high::{CrashInfo, Fx, Guid, MiddlewareControlSurface, Project, Reaper, Track};
use reaper_high::{
ChangeEvent, CrashInfo, Fx, Guid, MiddlewareControlSurface, Project, Reaper, Track,
};
use reaper_low::{PluginContext, Swell};
use reaper_macros::reaper_extension_plugin;
use reaper_medium::{
Expand Down Expand Up @@ -2531,6 +2533,12 @@ impl ControlSurfaceEventHandler for BackboneControlSurfaceEventHandler {
Ok(())
});
}

fn process_reaper_change_events(&self, change_events: &[ChangeEvent]) {
BackboneShell::get()
.proto_hub
.send_global_events_caused_by_reaper_change_events(change_events);
}
}

#[derive(Debug)]
Expand Down
10 changes: 7 additions & 3 deletions main/src/infrastructure/proto/ext.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use helgoboss_license_api::persistence::LicenseData;
use helgoboss_license_api::runtime::License;
use reaper_high::Reaper;
use reaper_medium::ReaperString;
use reaper_medium::{PlayState, ReaperString};
use std::iter;

use crate::infrastructure::data::{
Expand All @@ -13,8 +13,8 @@ use crate::application::UnitModel;
use crate::domain::CompartmentKind;
use crate::infrastructure::proto::{
event_reply, occasional_global_update, occasional_instance_update,
qualified_occasional_unit_update, AudioInputChannel, AudioInputChannels, Compartment,
ContinuousColumnUpdate, ContinuousMatrixUpdate, GetContinuousColumnUpdatesReply,
qualified_occasional_unit_update, ArrangementPlayState, AudioInputChannel, AudioInputChannels,
Compartment, ContinuousColumnUpdate, ContinuousMatrixUpdate, GetContinuousColumnUpdatesReply,
GetContinuousMatrixUpdatesReply, GetContinuousSlotUpdatesReply, GetOccasionalClipUpdatesReply,
GetOccasionalColumnUpdatesReply, GetOccasionalGlobalUpdatesReply,
GetOccasionalInstanceUpdatesReply, GetOccasionalMatrixUpdatesReply,
Expand Down Expand Up @@ -62,6 +62,10 @@ impl qualified_occasional_unit_update::Update {
}

impl occasional_global_update::Update {
pub fn arrangement_play_state(play_state: PlayState) -> Self {
Self::ArrangementPlayState(ArrangementPlayState::from_engine(play_state).into())
}

pub fn info_event(event: realearn_api::runtime::InfoEvent) -> Self {
let json =
serde_json::to_string(&event).expect("couldn't represent main info event as JSON");
Expand Down
165 changes: 122 additions & 43 deletions main/src/infrastructure/proto/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub mod reply {
pub struct CommandRequest {
#[prost(
oneof = "command_request::Value",
tags = "1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 37, 40, 25, 26, 27, 34, 28, 29, 31, 32, 33, 35, 36, 38, 39, 41, 42, 43, 44, 45"
tags = "1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 37, 40, 25, 26, 27, 34, 28, 29, 31, 32, 33, 35, 36, 38, 39, 41, 42, 43, 44, 45, 46"
)]
pub value: ::core::option::Option<command_request::Value>,
}
Expand Down Expand Up @@ -145,6 +145,8 @@ pub mod command_request {
SaveCustomCompartmentData(super::SaveCustomCompartmentDataRequest),
#[prost(message, tag = "45")]
GetOccasionalUnitUpdates(super::GetOccasionalUnitUpdatesRequest),
#[prost(message, tag = "46")]
TriggerGlobal(super::TriggerGlobalRequest),
}
}
/// Envelope for queries.
Expand Down Expand Up @@ -465,6 +467,12 @@ pub struct DeleteControllerRequest {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TriggerGlobalRequest {
#[prost(enumeration = "TriggerGlobalAction", tag = "1")]
pub action: i32,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TriggerMatrixRequest {
#[prost(string, tag = "1")]
pub matrix_id: ::prost::alloc::string::String,
Expand Down Expand Up @@ -1049,7 +1057,7 @@ pub struct QualifiedOccasionalTrackUpdate {
pub struct OccasionalGlobalUpdate {
#[prost(
oneof = "occasional_global_update::Update",
tags = "1, 2, 3, 4, 5, 6, 7, 8, 9"
tags = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
)]
pub update: ::core::option::Option<occasional_global_update::Update>,
}
Expand Down Expand Up @@ -1085,6 +1093,9 @@ pub mod occasional_global_update {
/// Contains the license state of Playtime.
#[prost(message, tag = "9")]
PlaytimeLicenseState(super::LicenseState),
/// Arrangement play state (= REAPER transport play state)
#[prost(enumeration = "super::ArrangementPlayState", tag = "10")]
ArrangementPlayState(i32),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
Expand All @@ -1099,7 +1110,7 @@ pub struct LicenseState {
pub struct OccasionalMatrixUpdate {
#[prost(
oneof = "occasional_matrix_update::Update",
tags = "1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26"
tags = "1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26"
)]
pub update: ::core::option::Option<occasional_matrix_update::Update>,
}
Expand All @@ -1117,9 +1128,6 @@ pub mod occasional_matrix_update {
/// Matrix tempo (= REAPER master tempo)
#[prost(double, tag = "3")]
Tempo(f64),
/// Arrangement play state (= REAPER transport play state)
#[prost(enumeration = "super::ArrangementPlayState", tag = "4")]
ArrangementPlayState(i32),
/// Complete persistent data of the matrix has changed, including topology and other settings!
/// This contains the complete persistent matrix as JSON.
///
Expand Down Expand Up @@ -1481,13 +1489,7 @@ impl MatrixVolumeKind {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum TriggerMatrixAction {
ArrangementTogglePlayStop = 0,
StopAllClips = 1,
ArrangementPlay = 2,
ArrangementStop = 3,
ArrangementPause = 4,
ArrangementStartRecording = 5,
ArrangementStopRecording = 6,
StopAllClips = 0,
Undo = 7,
Redo = 8,
ToggleClick = 9,
Expand Down Expand Up @@ -1515,25 +1517,7 @@ impl TriggerMatrixAction {
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
TriggerMatrixAction::ArrangementTogglePlayStop => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_TOGGLE_PLAY_STOP"
}
TriggerMatrixAction::StopAllClips => "TRIGGER_MATRIX_ACTION_STOP_ALL_CLIPS",
TriggerMatrixAction::ArrangementPlay => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_PLAY"
}
TriggerMatrixAction::ArrangementStop => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_STOP"
}
TriggerMatrixAction::ArrangementPause => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_PAUSE"
}
TriggerMatrixAction::ArrangementStartRecording => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_START_RECORDING"
}
TriggerMatrixAction::ArrangementStopRecording => {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_STOP_RECORDING"
}
TriggerMatrixAction::Undo => "TRIGGER_MATRIX_ACTION_UNDO",
TriggerMatrixAction::Redo => "TRIGGER_MATRIX_ACTION_REDO",
TriggerMatrixAction::ToggleClick => "TRIGGER_MATRIX_ACTION_TOGGLE_CLICK",
Expand Down Expand Up @@ -1576,19 +1560,7 @@ impl TriggerMatrixAction {
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_TOGGLE_PLAY_STOP" => {
Some(Self::ArrangementTogglePlayStop)
}
"TRIGGER_MATRIX_ACTION_STOP_ALL_CLIPS" => Some(Self::StopAllClips),
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_PLAY" => Some(Self::ArrangementPlay),
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_STOP" => Some(Self::ArrangementStop),
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_PAUSE" => Some(Self::ArrangementPause),
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_START_RECORDING" => {
Some(Self::ArrangementStartRecording)
}
"TRIGGER_MATRIX_ACTION_ARRANGEMENT_STOP_RECORDING" => {
Some(Self::ArrangementStopRecording)
}
"TRIGGER_MATRIX_ACTION_UNDO" => Some(Self::Undo),
"TRIGGER_MATRIX_ACTION_REDO" => Some(Self::Redo),
"TRIGGER_MATRIX_ACTION_TOGGLE_CLICK" => Some(Self::ToggleClick),
Expand Down Expand Up @@ -1626,6 +1598,62 @@ impl TriggerMatrixAction {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum TriggerGlobalAction {
ArrangementTogglePlayStop = 0,
ArrangementPlay = 2,
ArrangementStop = 3,
ArrangementPause = 4,
ArrangementStartRecording = 5,
ArrangementStopRecording = 6,
}
impl TriggerGlobalAction {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
TriggerGlobalAction::ArrangementTogglePlayStop => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_TOGGLE_PLAY_STOP"
}
TriggerGlobalAction::ArrangementPlay => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_PLAY"
}
TriggerGlobalAction::ArrangementStop => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_STOP"
}
TriggerGlobalAction::ArrangementPause => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_PAUSE"
}
TriggerGlobalAction::ArrangementStartRecording => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_START_RECORDING"
}
TriggerGlobalAction::ArrangementStopRecording => {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_STOP_RECORDING"
}
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_TOGGLE_PLAY_STOP" => {
Some(Self::ArrangementTogglePlayStop)
}
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_PLAY" => Some(Self::ArrangementPlay),
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_STOP" => Some(Self::ArrangementStop),
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_PAUSE" => Some(Self::ArrangementPause),
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_START_RECORDING" => {
Some(Self::ArrangementStartRecording)
}
"TRIGGER_GLOBAL_ACTION_ARRANGEMENT_STOP_RECORDING" => {
Some(Self::ArrangementStopRecording)
}
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum Compartment {
Controller = 0,
Main = 1,
Expand Down Expand Up @@ -2327,6 +2355,10 @@ pub mod helgobox_service_server {
tonic::Status,
>;
/// General global commands
async fn trigger_global(
&self,
request: tonic::Request<super::TriggerGlobalRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status>;
async fn set_app_settings(
&self,
request: tonic::Request<super::SetAppSettingsRequest>,
Expand Down Expand Up @@ -3090,6 +3122,53 @@ pub mod helgobox_service_server {
};
Box::pin(fut)
}
"/generated.HelgoboxService/TriggerGlobal" => {
#[allow(non_camel_case_types)]
struct TriggerGlobalSvc<T: HelgoboxService>(pub Arc<T>);
impl<
T: HelgoboxService,
> tonic::server::UnaryService<super::TriggerGlobalRequest>
for TriggerGlobalSvc<T> {
type Response = super::Empty;
type Future = BoxFuture<
tonic::Response<Self::Response>,
tonic::Status,
>;
fn call(
&mut self,
request: tonic::Request<super::TriggerGlobalRequest>,
) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut = async move {
<T as HelgoboxService>::trigger_global(&inner, request)
.await
};
Box::pin(fut)
}
}
let accept_compression_encodings = self.accept_compression_encodings;
let send_compression_encodings = self.send_compression_encodings;
let max_decoding_message_size = self.max_decoding_message_size;
let max_encoding_message_size = self.max_encoding_message_size;
let inner = self.inner.clone();
let fut = async move {
let inner = inner.0;
let method = TriggerGlobalSvc(inner);
let codec = tonic::codec::ProstCodec::default();
let mut grpc = tonic::server::Grpc::new(codec)
.apply_compression_config(
accept_compression_encodings,
send_compression_encodings,
)
.apply_max_message_size_config(
max_decoding_message_size,
max_encoding_message_size,
);
let res = grpc.unary(method, req).await;
Ok(res)
};
Box::pin(fut)
}
"/generated.HelgoboxService/SetAppSettings" => {
#[allow(non_camel_case_types)]
struct SetAppSettingsSvc<T: HelgoboxService>(pub Arc<T>);
Expand Down
24 changes: 16 additions & 8 deletions main/src/infrastructure/proto/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use crate::infrastructure::data::{
use crate::infrastructure::plugin::InstanceShell;
use crate::infrastructure::proto::helgobox_service_server::HelgoboxServiceServer;
use crate::infrastructure::proto::{
occasional_global_update, occasional_instance_update, qualified_occasional_unit_update,
HelgoboxServiceImpl, OccasionalGlobalUpdate, OccasionalInstanceUpdate,
OccasionalInstanceUpdateBatch, OccasionalUnitUpdateBatch, ProtoRequestHandler, ProtoSenders,
QualifiedOccasionalUnitUpdate,
occasional_global_update, occasional_instance_update, occasional_matrix_update,
qualified_occasional_unit_update, HelgoboxServiceImpl, OccasionalGlobalUpdate,
OccasionalInstanceUpdate, OccasionalInstanceUpdateBatch, OccasionalUnitUpdateBatch,
ProtoRequestHandler, ProtoSenders, QualifiedOccasionalUnitUpdate,
};
use helgoboss_license_api::runtime::License;
use realearn_api::runtime::InfoEvent;
use reaper_high::ChangeEvent;

#[derive(Debug)]
pub struct ProtoHub {
Expand Down Expand Up @@ -109,6 +109,17 @@ impl ProtoHub {
});
}

pub fn send_global_events_caused_by_reaper_change_events(&self, change_events: &[ChangeEvent]) {
self.send_occasional_global_updates(|| {
change_events.iter().filter_map(|event| match event {
ChangeEvent::PlayStateChanged(e) => Some(
occasional_global_update::Update::arrangement_play_state(e.new_value),
),
_ => None,
})
})
}

fn send_occasional_global_updates<F, I>(&self, create_updates: F)
where
F: FnOnce() -> I,
Expand Down Expand Up @@ -674,9 +685,6 @@ mod playtime_impl {
ChangeEvent::TrackSelectedChanged(e) => {
column_track_update(matrix, &e.track, || Update::selected(e.new_value))
}
ChangeEvent::PlayStateChanged(e) => Some(R::Matrix(
occasional_matrix_update::Update::arrangement_play_state(e.new_value),
)),
ChangeEvent::MasterTempoChanged(e) => Some(R::Matrix(
occasional_matrix_update::Update::tempo(e.new_value),
)),
Expand Down
2 changes: 2 additions & 0 deletions main/src/infrastructure/proto/initial_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::infrastructure::proto::{
OccasionalGlobalUpdate, OccasionalInstanceUpdate, QualifiedOccasionalUnitUpdate,
};
use crate::infrastructure::server::data::get_controller_routing;
use reaper_high::Reaper;

pub fn create_initial_global_updates() -> Vec<OccasionalGlobalUpdate> {
use occasional_global_update::Update;
Expand All @@ -16,6 +17,7 @@ pub fn create_initial_global_updates() -> Vec<OccasionalGlobalUpdate> {
let global_updates = [
Update::midi_input_devices(),
Update::midi_output_devices(),
Update::arrangement_play_state(Reaper::get().current_project().play_state()),
// TODO-high-ms3 Update when changed
Update::audio_input_channels(),
Update::controller_presets(&BackboneShell::get().controller_preset_manager().borrow()),
Expand Down
Loading

0 comments on commit 171154b

Please sign in to comment.