Skip to content

Commit

Permalink
Medium-level: Add get_set_project_info_string
Browse files Browse the repository at this point in the history
It has some problems, which are not present in other languages implementations. See tests.
verbolize category string
  • Loading branch information
Levitanus committed Nov 15, 2022
1 parent ef26a59 commit d226787
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 5 deletions.
17 changes: 15 additions & 2 deletions main/medium/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,25 @@ pub enum SetTrackUiFlags {
}

/// Defines nudge mode in `apply_nudge`
///
///
/// if not SetToValue — will nudge by value.
#[enumflags2::bitflags]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[repr(u32)]
pub enum ApplyNudgeFlag {
SetToValue = 1,
Snap = 2,
}
}

/// Defines how project is saved in `Reaper::save_project_ex()`
#[enumflags2::bitflags]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[repr(u32)]
pub enum SaveProjectFlags {
/// Save as RTrackTemplate.
AsTrackTemplate = 1,
/// Include media in track template.
WithMedia = 2,
/// Include envelopes in track template.
WithEnvelopes = 4,
}
94 changes: 94 additions & 0 deletions main/medium/src/misc_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1714,3 +1714,97 @@ impl NudgeUnits {
}
}
}

/// Selects string information, that can be set or retrieved from project.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum ProjectInfoStringCategory {
/// Project file name (read-only, is_set will be ignored).
ProjectName,

/// Title field from Project Settings/Notes dialog
ProjectTitle,

/// Author field from Project Settings/Notes dialog
ProjectAuthor,

/// Track group name, value should be 1..64
TrackGroupName(u8),

/// Get the GUID (unique ID) of the marker or region with given index,
/// index is the one, that passed to `enum_project_markers`,
/// not necessarily the displayed number.
MarkerGuid(u32),

/// Recording directory -- may be blank or a relative path,
/// to get the effective path see get_project_path_ex()
RecordPath,

/// Secondary recording directory.
RecordPathSecondary,

/// Render directory
RenderFile,

/// Render file name (may contain wildcards)
RenderPattern,

/// The metadata saved with the project
/// (not metadata embedded in project media).
///
/// # Example ID3 album name metadata:
///
/// value=ReaperStringArg::from("ID3:TALB") to get
/// value=ReaperStringArg::from("ID3:TALB|my album name") to set.
///
/// Returns as a semicolon-separated list of defined project metadata identifiers.
RenderMetadata,

/// Semicolon separated list of files that would be written
/// if the project is rendered using the most recent render settings.
RenderTargets,

/// (read-only) semicolon separated list of statistics
/// for the most recently rendered files.
/// Call with value=ReaperStringArg::from("XXX") to run an action
/// (for example, "42437"=dry run render selected items) before returning statistics.
RenderStats,

/// base64-encoded sink configuration (see project files, etc).
///
/// Callers can also pass a simple 4-byte string (non-base64-encoded),
/// e.g. "evaw" or "l3pm", to use default settings for that sink type.
///
/// Generate ReaScriptAPI from the REAPER to see which formats are supported
/// and retrieve their strings.
///
/// Typical are: "wave" "aiff" "caff" "iso " "ddp " "flac" "mp3l" "oggv"
/// "OggS" "FFMP" "WMF " "GIF " "LCF " "wvpk"
RenderFormat,

/// See RenderFormat
RenderFormat2,
}

impl<'a> ProjectInfoStringCategory {
/// Converts this value to an &str as expected by the low-level API.
pub fn to_raw(self) -> ReaperStringArg<'a> {
match self {
Self::ProjectName => ReaperStringArg::from("PROJECT_NAME"),
Self::ProjectTitle => ReaperStringArg::from("PROJECT_TITLE"),
Self::ProjectAuthor => ReaperStringArg::from("PROJECT_AUTHOR"),
Self::TrackGroupName(val) => {
ReaperStringArg::from(format!("TRACK_GROUP_NAME:{:?}", val))
}
Self::MarkerGuid(val) => ReaperStringArg::from(format!("MARKER_GUID:{:?}", val)),
Self::RecordPath => ReaperStringArg::from("RECORD_PATH"),
Self::RecordPathSecondary => ReaperStringArg::from("RECORD_PATH_SECONDARY"),
Self::RenderFile => ReaperStringArg::from("RENDER_FILE"),
Self::RenderPattern => ReaperStringArg::from("RENDER_PATTERN"),
Self::RenderMetadata => ReaperStringArg::from("RENDER_METADATA"),
Self::RenderTargets => ReaperStringArg::from("RENDER_TARGETS"),
Self::RenderStats => ReaperStringArg::from("RENDER_STATS"),
Self::RenderFormat => ReaperStringArg::from("RENDER_FORMAT"),
Self::RenderFormat2 => ReaperStringArg::from("RENDER_FORMAT2"),
}
}
}
73 changes: 71 additions & 2 deletions main/medium/src/reaper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::{
MidiOutputDeviceId, NativeColor, NormalizedPlayRate, NotificationBehavior, NudgeUnits,
OwnedPcmSource, OwnedReaperPitchShift, OwnedReaperResample, PanMode, ParamId, PcmSource,
PitchShiftMode, PitchShiftSubMode, PlaybackSpeedFactor, PluginContext, PositionInBeats,
PositionInQuarterNotes, PositionInSeconds, Progress, ProjectContext, ProjectRef,
PromptForActionResult, ReaProject, ReaperFunctionError, ReaperFunctionResult,
PositionInQuarterNotes, PositionInSeconds, Progress, ProjectContext, ProjectInfoStringCategory,
ProjectRef, PromptForActionResult, ReaProject, ReaperFunctionError, ReaperFunctionResult,
ReaperNormalizedFxParamValue, ReaperPanLikeValue, ReaperPanValue, ReaperPointer, ReaperStr,
ReaperString, ReaperStringArg, ReaperVersion, ReaperVolumeValue, ReaperWidthValue,
RecordArmMode, RecordingInput, RequiredViewMode, ResampleMode, SectionContext, SectionId,
Expand Down Expand Up @@ -5607,6 +5607,75 @@ impl<UsageScope> Reaper<UsageScope> {
NonNull::new(ptr)
}

/// Set project information.
///
/// For more information of possible values see `ProjectInfoStringCategory`
/// documentation.
///
/// # Known bugs
///
/// This function constantly returns false, but sometimes it works.
///
/// # Safety
///
/// REAPER can crash if you pass an invalid project.
pub unsafe fn get_set_project_info_string_set<'a, I: Into<ReaperStringArg<'a>>>(
&self,
project: ProjectContext,
category: ProjectInfoStringCategory,
value: I,
) -> bool
where
UsageScope: MainThreadOnly,
{
let val: ReaperStringArg = value.into();
let val: CString = CString::from(val.as_reaper_str().as_c_str());
let category_string = category.to_raw();
self.low().GetSetProjectInfo_String(
project.to_raw(),
category_string.as_ptr(),
val.into_raw(),
true,
)
}

/// Get project information.
///
/// For more information of possible values see `ProjectInfoStringCategory`
/// documentation.
///
/// # Known bugs
///
/// There are problems with several categories. At least, with
/// TrackGroupName(x), which makes definitely right string for category,
/// but doesn't work with reaper-rs.
///
/// # Safety
///
/// REAPER can crash if you pass an invalid project.
pub unsafe fn get_set_project_info_string_get(
&self,
project: ProjectContext,
category: ProjectInfoStringCategory,
) -> ReaperFunctionResult<String>
where
UsageScope: MainThreadOnly,
{
let max_size = 1024 * 10;
let (result, status) = with_string_buffer(max_size, |buf, _| -> bool {
self.low().GetSetProjectInfo_String(
project.to_raw(),
category.to_raw().as_ptr(),
buf,
false,
)
});
match status {
true => Ok(result.into_string()),
false => Err(ReaperFunctionError::new("Can not get project info.")),
}
}

/// Returns the take that is currently being edited in the given MIDI editor.
///
/// # Safety
Expand Down
3 changes: 2 additions & 1 deletion test/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ slog = "2.5.2"
helgoboss-midi = "0.4.0"
approx = "0.3.2"
once_cell = "1.5.2"
crossbeam-channel = "0.5"
crossbeam-channel = "0.5"
enumflags2 = "0.7"
41 changes: 41 additions & 0 deletions test/test/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub fn create_test_steps() -> impl Iterator<Item = TestStep> {
main_section_functions(),
register_and_unregister_action(),
register_and_unregister_toggle_action(),
project_info_string(),
]
.into_iter();
let steps_b = vec![
Expand Down Expand Up @@ -272,6 +273,46 @@ fn mark_project_as_dirty() -> TestStep {
})
}

fn project_info_string() -> TestStep {
step(AllVersions, "Test Project info string", |rpr, _| {
// Given
let project = rpr.current_project();
let medium = rpr.medium_reaper();

unsafe {
medium.get_set_project_info_string_set(
project.context(),
reaper_medium::ProjectInfoStringCategory::RenderFile,
"reaper-rs",
);
let result = medium.get_set_project_info_string_get(
project.context(),
reaper_medium::ProjectInfoStringCategory::RenderFile,
);
assert_eq!(result.unwrap(), "reaper-rs");
// assert_eq!(
// reaper_medium::ProjectInfoStringCategory::TrackGroupName(2)
// .to_raw()
// .into_inner()
// .to_string(),
// String::from("TRACK_GROUP_NAME:2")
// );
// medium.get_set_project_info_string_set(
// project.context(),
// reaper_medium::ProjectInfoStringCategory::TrackGroupName(2),
// "My group name",
// )?;
// let result = medium.get_set_project_info_string_get(
// project.context(),
// reaper_medium::ProjectInfoStringCategory::TrackGroupName(2),
// );
// assert_eq!(result.unwrap(), "My group name");
}

Ok(())
})
}

fn get_reaper_window() -> TestStep {
step(AllVersions, "Get REAPER window", |_session, _| {
// Given
Expand Down

0 comments on commit d226787

Please sign in to comment.