Skip to content

Commit

Permalink
#778 #770 Multiple changes
Browse files Browse the repository at this point in the history
- Let users pick parameters again, even if FX is unstable
- Let users pick parameter of last focused FX if FX is set to "Focused"
- Add warning message when doing that
- Improve picking of last focused FX instance when linking FX to presets
  in context menu
  • Loading branch information
helgoboss committed Nov 24, 2022
1 parent 3a39861 commit 12ccc07
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion main/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "realearn"
version = "2.14.0-pre.11"
version = "2.14.0"
authors = ["Benjamin Klum <[email protected]>"]
edition = "2021"
build = "build.rs"
Expand Down
27 changes: 19 additions & 8 deletions main/src/infrastructure/plugin/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub struct App {
server: SharedRealearnServer,
config: RefCell<AppConfig>,
changed_subject: RefCell<LocalSubject<'static, (), ()>>,
list_of_recently_focused_fx: Rc<RefCell<ListOfRecentlyFocusedFx>>,
recently_focused_fx_container: Rc<RefCell<RecentlyFocusedFxContainer>>,
party_is_over_subject: LocalSubject<'static, (), ()>,
control_surface_main_task_sender: RealearnControlSurfaceMainTaskSender,
clip_matrix_event_sender: SenderToNormalThread<QualifiedClipMatrixEvent>,
Expand Down Expand Up @@ -178,15 +178,26 @@ impl Default for App {
}

#[derive(Debug, Default)]
struct ListOfRecentlyFocusedFx {
struct RecentlyFocusedFxContainer {
previous: Option<Fx>,
current: Option<Fx>,
}

impl ListOfRecentlyFocusedFx {
fn feed(&mut self, currently_focused_fx: Option<Fx>) {
impl RecentlyFocusedFxContainer {
fn feed(&mut self, new_fx: Option<Fx>) {
// Never clear any memorized FX.
let Some(new_fx) = new_fx else {
return;
};
// Don't rotate if current FX has not changed.
if let Some(current) = self.current.as_ref() {
if &new_fx == current {
return;
}
}
// Rotate
self.previous = self.current.take();
self.current = currently_focused_fx;
self.current = Some(new_fx);
}
}

Expand Down Expand Up @@ -279,7 +290,7 @@ impl App {
))),
config: RefCell::new(config),
changed_subject: Default::default(),
list_of_recently_focused_fx: Default::default(),
recently_focused_fx_container: Default::default(),
party_is_over_subject: Default::default(),
control_surface_main_task_sender: main_sender,
clip_matrix_event_sender,
Expand Down Expand Up @@ -344,7 +355,7 @@ impl App {
server::http::keep_informing_clients_about_sessions();
debug_util::register_resolve_symbols_action();
crate::infrastructure::test::register_test_action();
let list_of_recently_focused_fx = self.list_of_recently_focused_fx.clone();
let list_of_recently_focused_fx = self.recently_focused_fx_container.clone();
self.osc_device_manager
.borrow()
.changed()
Expand Down Expand Up @@ -699,7 +710,7 @@ impl App {
/// last focused one. That's important because when queried from ReaLearn UI, the current one
/// is mostly ReaLearn itself - which is in most cases not what we want.
pub fn previously_focused_fx(&self) -> Option<Fx> {
self.list_of_recently_focused_fx.borrow().previous.clone()
self.recently_focused_fx_container.borrow().previous.clone()
}

// TODO-medium Return a reference to a SharedControllerManager! Clients might just want to turn
Expand Down
89 changes: 55 additions & 34 deletions main/src/infrastructure/ui/mapping_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,21 +1116,25 @@ impl MappingPanel {
"Target control error"
};
let body = format!("{} ({})", event.log_entry, event.log_context);
self.view
.require_control(root::ID_MAPPING_HELP_APPLICABLE_TO_LABEL)
.hide();
self.view
.require_control(root::ID_MAPPING_HELP_APPLICABLE_TO_COMBO_BOX)
.hide();
self.view
.require_control(root::ID_MAPPING_HELP_SUBJECT_LABEL)
.set_text(title);
self.view
.require_control(root::ID_MAPPING_HELP_CONTENT_LABEL)
.set_text(body);
self.set_simple_help_text(title, &body);
});
}

fn set_simple_help_text(&self, title: &str, body: &str) {
self.view
.require_control(root::ID_MAPPING_HELP_APPLICABLE_TO_LABEL)
.hide();
self.view
.require_control(root::ID_MAPPING_HELP_APPLICABLE_TO_COMBO_BOX)
.hide();
self.view
.require_control(root::ID_MAPPING_HELP_SUBJECT_LABEL)
.set_text(title);
self.view
.require_control(root::ID_MAPPING_HELP_CONTENT_LABEL)
.set_text(body);
}

pub fn handle_changed_target_value(
self: SharedView<Self>,
targets: &[CompoundMappingTarget],
Expand Down Expand Up @@ -3011,7 +3015,8 @@ impl<'a> MutableMappingPanel<'a> {
));
}
t if t.supports_fx_parameter() => {
if let Ok(fx) = self.target_with_context().first_fx() {
let fx = get_relevant_target_fx(self.mapping, self.session);
if let Some(fx) = fx {
let i = combo.selected_combo_box_item_index();
let param = fx.parameter_by_index(i as _);
self.change_mapping(MappingCommand::ChangeTarget(
Expand All @@ -3023,6 +3028,12 @@ impl<'a> MutableMappingPanel<'a> {
self.change_mapping(MappingCommand::ChangeTarget(
TargetCommand::SetParamName(param_name),
));
if self.mapping.target_model.fx_type() == VirtualFxType::Focused {
self.panel.set_simple_help_text(
"Target warning",
r#"ATTENTION: You just picked a parameter for the last focused FX. This is okay but you should know that as soon as you focus another type of FX, the parameter list will change and your mapping will control a completely different parameter! You probably want to use this in combination with the "Auto-load" feature, which lets you link FX types to mapping presets. See https://github.com/helgoboss/realearn/blob/master/doc/user-guide.adoc#using-auto-load-to-control-whatever-plug-in-is-currently-in-focus."#
);
}
}
}
t if t.supports_track_exclusivity() => {
Expand Down Expand Up @@ -5180,28 +5191,18 @@ impl<'a> ImmutableMappingPanel<'a> {
&& self.target.param_type() == VirtualFxParameterType::ById =>
{
combo.show();
if self.target.fx_type().is_sticky() {
let context = self.session.extended_context();
if let Ok(fx) = self
.target
.with_context(context, self.mapping.compartment())
.first_fx()
{
combo.fill_combo_box_indexed(fx_parameter_combo_box_entries(&fx));
let param_index = self.target.param_index();
combo
.select_combo_box_item_by_index(param_index as _)
.unwrap_or_else(|_| {
let label = get_fx_param_label(None, param_index);
combo.select_new_combo_box_item(label.into_owned());
});
} else {
combo.select_only_combo_box_item("<Requires FX>");
}
let fx = get_relevant_target_fx(self.mapping, self.session);
if let Some(fx) = fx {
combo.fill_combo_box_indexed(fx_parameter_combo_box_entries(&fx));
let param_index = self.target.param_index();
combo
.select_combo_box_item_by_index(param_index as _)
.unwrap_or_else(|_| {
let label = get_fx_param_label(None, param_index);
combo.select_new_combo_box_item(label.into_owned());
});
} else {
combo.select_only_combo_box_item(
"Use 'Particular' only if FX is particular as well!",
)
combo.select_only_combo_box_item("<Requires FX>");
}
}
t if t.supports_track_exclusivity() => {
Expand Down Expand Up @@ -5673,6 +5674,7 @@ impl<'a> ImmutableMappingPanel<'a> {
.set_text(step_label);
}

#[allow(clippy::needless_bool)]
fn invalidate_mode_control_visibilities(&self) {
let relevant_source_characters = self.mapping.source_model.possible_detailed_characters();
let base_input = self.mapping.base_mode_applicability_check_input();
Expand Down Expand Up @@ -7534,3 +7536,22 @@ fn extract_first_line(text: &str) -> &str {
fn has_multiple_lines(text: &str) -> bool {
text.lines().count() > 1
}

fn get_relevant_target_fx(mapping: &MappingModel, session: &Session) -> Option<Fx> {
if mapping.target_model.fx_type() == VirtualFxType::Focused {
// This is a special case. Since ReaLearn 2.14.0-pre.10, an FX is not
// considered as focused anymore when clicking somewhere else. So we would
// never obtain an FX instance here because user clicks into the mapping
// panel, which is not an FX, not even ReaLearn FX as far as REAPER is
// concerned! So we need to choose the last focused FX.
// See https://github.com/helgoboss/realearn/issues/778.
Reaper::get().focused_fx().map(|res| res.fx)
} else {
// Choose whatever FX the selector currently resolves to
mapping
.target_model
.with_context(session.extended_context(), mapping.compartment())
.first_fx()
.ok()
}
}

0 comments on commit 12ccc07

Please sign in to comment.