reaper_medium/
key_enums.rs

1use crate::{concat_c_strs, ReaperStringArg};
2use c_str_macro::c_str;
3
4use std::borrow::Cow;
5use std::ffi::CStr;
6
7/// Track attribute key which you can pass to [`get_set_media_track_info()`].
8///
9/// [`get_set_media_track_info()`]: struct.ReaperFunctions.html#method.get_set_media_track_info
10#[derive(Clone, Eq, PartialEq, Hash, Debug)]
11pub enum TrackAttributeKey<'a> {
12    /// Parent track (read-only).
13    ///
14    /// `*mut MediaTrack`
15    ParTrack,
16    /// Parent project (read-only).
17    ///
18    /// `*mut ReaProject`
19    Project,
20    /// Track name (on master returns `null_mut()`).
21    ///
22    /// `*mut char`
23    Name,
24    /// Track icon.
25    ///
26    /// `*const char`
27    ///
28    /// Full file name or relative to resource path / data / track icons.
29    Icon,
30    /// Layout name.
31    ///
32    /// `*const char`
33    McpLayout,
34    /// Layout name.
35    ///
36    /// `*const char`
37    TcpLayout,
38    /// Extension-specific persistent data.
39    ///
40    /// `*mut char`
41    ///
42    /// Use [`ext()`] to create this variant.
43    ///
44    /// [`ext()`]: #method.ext
45    Ext(Cow<'a, CStr>),
46    /// 6-byte GUID, can query or update.
47    ///
48    /// `*mut GUID`
49    ///
50    /// If using a `_string()` function, GUID is a string `{xyz-...}`.
51    Guid,
52    /// Muted.
53    ///
54    /// `*mut bool`
55    Mute,
56    /// Track phase inverted.
57    ///
58    /// `*mut bool`
59    Phase,
60    /// Track number
61    ///
62    /// `i32`
63    ///
64    /// 1-based, read-only, returns the i32 directly.
65    ///
66    /// - 0 → not found
67    /// - -1 → master track
68    TrackNumber,
69    /// Soloed.
70    ///
71    /// `*mut i32`
72    ///
73    /// - 0 → not soloed
74    /// - 1 → soloed
75    /// - 2 → soloed in place
76    /// - 5 → safe soloed
77    /// - 6 → safe soloed in place
78    Solo,
79    /// FX enabled.
80    ///
81    /// `*mut i32`
82    ///
83    /// - 0 → bypassed
84    /// - != 0 → FX active
85    FxEn,
86    /// Record armed.
87    ///
88    /// `*mut i32`
89    ///
90    /// - 0 → not record armed
91    /// - 1 → record armed
92    RecArm,
93    /// Record input.
94    ///
95    /// `*mut i32`
96    ///
97    /// - <0 → no input
98    /// - 0..=n → mono hardware input
99    /// - 512 + n → rearoute input
100    /// - &1024 → stereo input pair
101    /// - &4096 → MIDI input, if set then low 5 bits represent channel (0 → all, 1 - 16 → only
102    ///   channel), next 6 bits represent physical input (63 → all, 62 → VKB)
103    RecInput,
104    /// Record mode.
105    ///
106    /// `*mut i32`
107    ///
108    /// - 0 → input
109    /// - 1 → stereo out
110    /// - 2 → none
111    /// - 3 → stereo out with latency compensation
112    /// - 4 → midi output
113    /// - 5 → mono out
114    /// - 6 → mono out with latency compensation
115    /// - 7 → MIDI overdub
116    /// - 8 → MIDI replace
117    RecMode,
118    /// Record monitoring.
119    ///
120    /// `*mut i32`
121    ///
122    /// - 0 → off
123    /// - 1 → normal
124    /// - 2 → not when playing (tape style)
125    RecMon,
126    /// Monitor items while recording.
127    ///
128    /// `*mut i32`
129    ///
130    /// - 0 → off
131    /// - 1 → on
132    RecMonItems,
133    /// Track automation mode.
134    ///
135    /// `*mut i32`
136    ///
137    /// - 0 → trim/off
138    /// - 1 → read
139    /// - 2 → touch
140    /// - 3 → write
141    /// - 4 → latch
142    AutoMode,
143    /// Number of track channels.
144    ///
145    /// `*mut i32`
146    ///
147    /// 2 - 64, even numbers only.
148    Nchan,
149    /// Track selected.
150    ///
151    /// `*mut i32`
152    ///
153    /// - 0 → unselected
154    /// - 1 → selected
155    Selected,
156    /// Current TCP window height in pixels including envelopes (read-only).
157    ///
158    /// `*mut i32`
159    WndH,
160    /// Current TCP window height in pixels not including envelopes (read-only).
161    ///
162    /// `*mut i32`
163    TcpH,
164    /// Current TCP window Y-position in pixels relative to top of arrange view (read-only).
165    ///
166    /// `*mut i32`
167    TcpY,
168    /// Current MCP X-position in pixels relative to mixer container.
169    ///
170    /// `*mut i32`
171    McpX,
172    /// Current MCP Y-position in pixels relative to mixer container.
173    ///
174    /// `*mut i32`
175    McpY,
176    /// Current MCP width in pixels.
177    ///
178    /// `*mut i32`
179    McpW,
180    /// Current MCP height in pixels.
181    ///
182    /// `*mut i32`
183    McpH,
184    /// Folder depth change.
185    ///
186    /// `*mut i32`
187    ///
188    /// - 0 → normal
189    /// - 1 → track is a folder parent
190    /// - -1 → track is the last in the innermost folder
191    /// - -2 → track is the last in the innermost and next-innermost folders
192    /// - ...
193    FolderDepth,
194    /// Folder compacted state (only valid on folders).
195    ///
196    /// `*mut i32`
197    ///
198    /// - 0 → normal
199    /// - 1 → small
200    /// - 2 → tiny children
201    FolderCompact,
202    /// Track midi hardware output index.
203    ///
204    /// `*mut i32`
205    ///
206    /// Low 5 bits are which channels (1..=16, 0 → all), next 5 bits are output device index
207    /// (0..=31). < 0 means disabled.
208    MidiHwOut,
209    /// Track performance flags.
210    ///
211    /// `*mut i32`
212    ///
213    /// &1 → no media buffering
214    /// &2 → no anticipative FX
215    PerfFlags,
216    /// Custom color.
217    ///
218    /// `*mut i32`
219    ///
220    /// `<OS dependent color> | 0x100000` (i.e. `ColorToNative(r, g, b) | 0x100000`).
221    /// If you don't do `| 0x100000`, then it will not be used, but will store the color anyway.
222    CustomColor,
223    /// Custom height override for TCP window.
224    ///
225    /// `*mut i32`
226    ///
227    /// 0 for none, otherwise size in pixels.
228    HeightOverride,
229    /// Track height lock.
230    ///
231    /// `*mut bool`
232    ///
233    /// Must set [`HeightOverride`] before locking.
234    ///
235    /// [`HeightOverride`]: #variant.HeightOverride
236    HeightLock,
237    /// Trim volume of track.
238    ///
239    /// `*mut f64`
240    ///
241    /// - 0 → -inf
242    /// - 0.5 → -6dB
243    /// - 1 → +0dB
244    /// - 2 → +6dB
245    /// - ...
246    Vol,
247    /// Trim pan of track
248    ///
249    /// `*mut f64`
250    ///
251    /// -1..=1.
252    Pan,
253    /// Width of track
254    ///
255    /// `*mut f64`
256    ///
257    /// -1..=1.
258    Width,
259    /// Dual pan position 1.
260    ///
261    /// `*mut f64`
262    ///
263    /// -1..=1, only if [`PanMode`] == 6.
264    ///
265    /// [`PanMode`]: #variant.PanMode
266    DualPanL,
267    /// Dual pan position 2.
268    ///
269    /// `*mut f64`
270    ///
271    /// -1..=1, only if [`PanMode`] == 6.
272    ///
273    /// [`PanMode`]: #variant.PanMode
274    DualPanR,
275    /// Pan mode.
276    ///
277    /// `*mut i32`
278    ///
279    /// - 0 → classic 3.x
280    /// - 3 → new balance
281    /// - 5 → stereo pan
282    /// - 6 → dual pan
283    PanMode,
284    /// Pan law.
285    ///
286    /// `*mut f64`
287    ///
288    /// - < 0 → project default
289    /// - 1 → +0 dB
290    /// - ...
291    PanLaw,
292    /// TrackEnvelope (read only).
293    ///
294    /// `*mut TrackEnvelope`
295    Env(EnvChunkName<'a>),
296    /// Track control panel visible in mixer.
297    ///
298    /// `*mut bool`
299    ///
300    /// Do not use on master track.
301    ShowInMixer,
302    /// Track control panel visible in arrange view.
303    ///
304    /// `*mut bool`
305    ///
306    /// Do not use on master track.
307    ShowInTcp,
308    /// Track sends audio to parent.
309    ///
310    /// `*mut bool`
311    MainSend,
312    /// Channel offset of track send to parent.
313    ///
314    /// `*mut char`
315    MainSendOffs,
316    /// Track free item positioning enabled
317    ///
318    /// `*mut bool`
319    ///
320    /// Call [`update_timeline`] after changing.
321    ///
322    /// [`update_timeline`]: struct.Reaper.html#method.update_timeline
323    FreeMode,
324    /// Track timebase.
325    ///
326    /// `*mut char`
327    ///
328    /// - -1 → project default
329    /// - 0 → time
330    /// - 1 → beats (position, length, rate)
331    /// - 2 → beats (position only)
332    BeatAttachMode,
333    /// Scale of FX and send area in MCP.
334    ///
335    /// `*mut f32`
336    ///
337    /// - 0 → minimum allowed
338    /// - 1 → maximum allowed
339    McpFxSendScale,
340    /// Scale of send area as proportion of the FX and send total area.
341    ///
342    /// `*mut f32`
343    ///
344    /// - 0 → minimum allowed
345    /// - 1 → maximum allowed
346    McpSendRgnScale,
347    /// Track playback offset state.
348    ///
349    /// `*mut i32`
350    ///
351    /// - &1 → bypassed
352    /// - &2 → offset
353    ///
354    /// Value is measured in samples (otherwise measured in seconds).
355    PlayOffsetFlag,
356    /// Track playback offset.
357    ///
358    /// `*mut f64`
359    ///
360    /// Units depend on [`PlayOffsetFlag`].
361    ///
362    /// [`PlayOffsetFlag`]: #variant.PlayOffsetFlag
363    PlayOffset,
364    /// If a variant is missing in this enum, you can use this custom one as a resort.
365    ///
366    /// Use [`custom()`] to create this variant.
367    ///
368    /// [`custom()`]: #method.custom
369    Custom(Cow<'a, CStr>),
370}
371
372impl<'a> TrackAttributeKey<'a> {
373    /// Convenience function for creating an [`Ext`] key.
374    ///
375    /// [`Ext`]: #variant.Ext
376    pub fn ext(key: impl Into<ReaperStringArg<'a>>) -> TrackAttributeKey<'a> {
377        TrackAttributeKey::Ext(key.into().into_inner())
378    }
379
380    /// Convenience function for creating a [`Custom`] key.
381    ///
382    /// [`Custom`]: #variant.Custom
383    pub fn custom(key: impl Into<ReaperStringArg<'a>>) -> TrackAttributeKey<'a> {
384        TrackAttributeKey::Custom(key.into().into_inner())
385    }
386
387    pub(crate) fn into_raw(self) -> Cow<'a, CStr> {
388        use TrackAttributeKey::*;
389        match self {
390            FreeMode => c_str!("B_FREEMODE").into(),
391            HeightLock => c_str!("B_HEIGHTLOCK").into(),
392            MainSend => c_str!("B_MAINSEND").into(),
393            Mute => c_str!("B_MUTE").into(),
394            Phase => c_str!("B_PHASE").into(),
395            ShowInMixer => c_str!("B_SHOWINMIXER").into(),
396            ShowInTcp => c_str!("B_SHOWINTCP").into(),
397            BeatAttachMode => c_str!("C_BEATATTACHMODE").into(),
398            MainSendOffs => c_str!("C_MAINSEND_OFFS").into(),
399            DualPanL => c_str!("D_DUALPANL").into(),
400            DualPanR => c_str!("D_DUALPANR").into(),
401            Pan => c_str!("D_PAN").into(),
402            PanLaw => c_str!("D_PANLAW").into(),
403            PlayOffset => c_str!("D_PLAY_OFFSET").into(),
404            Vol => c_str!("D_VOL").into(),
405            Width => c_str!("D_WIDTH").into(),
406            McpFxSendScale => c_str!("F_MCP_FXSEND_SCALE").into(),
407            McpSendRgnScale => c_str!("F_MCP_SENDRGN_SCALE").into(),
408            Guid => c_str!("GUID").into(),
409            AutoMode => c_str!("I_AUTOMODE").into(),
410            CustomColor => c_str!("I_CUSTOMCOLOR").into(),
411            FolderCompact => c_str!("I_FOLDERCOMPACT").into(),
412            FolderDepth => c_str!("I_FOLDERDEPTH").into(),
413            FxEn => c_str!("I_FXEN").into(),
414            HeightOverride => c_str!("I_HEIGHTOVERRIDE").into(),
415            McpH => c_str!("I_MCPH").into(),
416            McpW => c_str!("I_MCPW").into(),
417            McpX => c_str!("I_MCPX").into(),
418            McpY => c_str!("I_MCPY").into(),
419            MidiHwOut => c_str!("I_MIDIHWOUT").into(),
420            Nchan => c_str!("I_NCHAN").into(),
421            PanMode => c_str!("I_PANMODE").into(),
422            PerfFlags => c_str!("I_PERFFLAGS").into(),
423            PlayOffsetFlag => c_str!("I_PLAY_OFFSET_FLAG").into(),
424            RecArm => c_str!("I_RECARM").into(),
425            RecInput => c_str!("I_RECINPUT").into(),
426            RecMode => c_str!("I_RECMODE").into(),
427            RecMon => c_str!("I_RECMON").into(),
428            RecMonItems => c_str!("I_RECMONITEMS").into(),
429            Selected => c_str!("I_SELECTED").into(),
430            Solo => c_str!("I_SOLO").into(),
431            TcpH => c_str!("I_TCPH").into(),
432            TcpY => c_str!("I_TCPY").into(),
433            WndH => c_str!("I_WNDH").into(),
434            TrackNumber => c_str!("IP_TRACKNUMBER").into(),
435            Env(env_chunk_name) => {
436                concat_c_strs(c_str!("P_ENV:<"), env_chunk_name.into_raw().as_ref()).into()
437            }
438            Ext(extension_specific_key) => {
439                concat_c_strs(c_str!("P_EXT:"), extension_specific_key.as_ref()).into()
440            }
441            Icon => c_str!("P_ICON").into(),
442            McpLayout => c_str!("P_MCP_LAYOUT").into(),
443            Name => c_str!("P_NAME").into(),
444            ParTrack => c_str!("P_PARTRACK").into(),
445            Project => c_str!("P_PROJECT").into(),
446            TcpLayout => c_str!("P_TCP_LAYOUT").into(),
447            Custom(key) => key,
448        }
449    }
450}
451
452/// Track send attribute key which you can pass to [`get_set_track_send_info()`].
453///
454/// [`get_set_track_send_info()`]: struct.ReaperFunctions.html#method.get_set_track_send_info
455#[derive(Clone, Eq, PartialEq, Hash, Debug)]
456pub enum TrackSendAttributeKey<'a> {
457    /// Destination track (read-only).
458    ///
459    /// `*mut MediaTrack`
460    ///
461    /// Only applies for sends/receives.
462    DestTrack,
463    /// Source track (read-only).
464    ///
465    /// `*mut MediaTrack`
466    ///
467    /// Only applies for sends/receives.
468    SrcTrack,
469    /// Corresponding track send envelope.
470    ///
471    /// `*mut TrackEnvelope`
472    Env(EnvChunkName<'a>),
473    /// Extension-specific persistent data.
474    ///
475    /// `*mut char`
476    ///
477    /// Use [`ext()`] to create this variant.
478    ///
479    /// [`ext()`]: #method.ext
480    Ext(Cow<'a, CStr>),
481    /// Muted.
482    ///
483    /// `*mut bool`
484    Mute,
485    /// Phase.
486    ///
487    /// `*mut bool`
488    ///
489    /// `true` to flip phase.
490    Phase,
491    /// Mono.
492    ///
493    /// `*mut bool`
494    Mono,
495    /// Volume.
496    ///
497    /// `*mut f64`
498    ///
499    /// 1.0 → +0 dB etc.
500    Vol,
501    /// Pan.
502    ///
503    /// `*mut f64`
504    ///
505    /// -1..=1
506    Pan,
507    /// Pan law.
508    ///
509    /// `*mut f64`
510    ///
511    /// - 1.0 → +0.0 dB
512    /// - 0.5 → -6 dB
513    /// - -1.0 → value defined in project
514    PanLaw,
515    /// Send mode.
516    ///
517    /// `*mut i32`
518    ///
519    /// - 0 → post-fader
520    /// - 1 → pre-fx
521    /// - 2 → post-fx (deprecated)
522    /// - 3 → post-fx
523    SendMode,
524    /// Automation mode.
525    ///
526    /// `*mut i32`
527    ///
528    /// - -1 → use track automation mode
529    /// - 0 → trim/off
530    /// - 1 → read
531    /// - 2 → touch
532    /// - 3 → write
533    /// - 4 → latch
534    AutoMode,
535    /// Source channel.
536    ///
537    /// `*mut i32`
538    ///
539    /// Index, &1024 → mono, -1 → none
540    SrcChan,
541    /// Destination channel.
542    ///
543    /// `*mut i32`
544    /// Index, &1024 → mono, otherwise stereo pair, hwout: &512 → rearoute
545    DstChan,
546    /// MIDI flags.
547    ///
548    /// `*mut i32`
549    ///
550    /// - Low 5 bits → source channel (0 → all, 1..=16)
551    /// - Next 5 bits → destination channel (0 → original, 1..=16)
552    MidiFlags,
553    /// If a variant is missing in this enum, you can use this custom one as a resort.
554    ///
555    /// Use [`custom()`] to create this variant.
556    ///
557    /// [`custom()`]: #method.custom
558    Custom(Cow<'a, CStr>),
559}
560
561impl<'a> TrackSendAttributeKey<'a> {
562    /// Convenience function for creating an [`Ext`] key.
563    ///
564    /// [`Ext`]: #variant.Ext
565    pub fn ext(key: impl Into<ReaperStringArg<'a>>) -> TrackSendAttributeKey<'a> {
566        TrackSendAttributeKey::Ext(key.into().into_inner())
567    }
568
569    /// Convenience function for creating a [`Custom`] key.
570    ///
571    /// [`Custom`]: #variant.Custom
572    pub fn custom(key: impl Into<ReaperStringArg<'a>>) -> TrackSendAttributeKey<'a> {
573        TrackSendAttributeKey::Custom(key.into().into_inner())
574    }
575
576    pub(crate) fn into_raw(self) -> Cow<'a, CStr> {
577        use TrackSendAttributeKey::*;
578        match self {
579            Mono => c_str!("B_MONO").into(),
580            Mute => c_str!("B_MUTE").into(),
581            Phase => c_str!("B_PHASE").into(),
582            Pan => c_str!("D_PAN").into(),
583            PanLaw => c_str!("D_PANLAW").into(),
584            Vol => c_str!("D_VOL").into(),
585            AutoMode => c_str!("I_AUTOMODE").into(),
586            DstChan => c_str!("I_DSTCHAN").into(),
587            MidiFlags => c_str!("I_MIDIFLAGS").into(),
588            SendMode => c_str!("I_SENDMODE").into(),
589            SrcChan => c_str!("I_SRCCHAN").into(),
590            DestTrack => c_str!("P_DESTTRACK").into(),
591            SrcTrack => c_str!("P_SRCTRACK").into(),
592            Env(env_chunk_name) => {
593                concat_c_strs(c_str!("P_ENV:<"), env_chunk_name.into_raw().as_ref()).into()
594            }
595            Ext(key) => concat_c_strs(c_str!("P_EXT:"), key.as_ref()).into(),
596            Custom(key) => key.into(),
597        }
598    }
599}
600
601/// Envelope chunk name which you can pass e.g. to [`TrackAttributeKey::Env()`].
602///
603/// [`TrackAttributeKey::Env()`]: enum.TrackAttributeKey.html#variant.Env
604#[derive(Clone, Eq, PartialEq, Hash, Debug)]
605pub enum EnvChunkName<'a> {
606    /// Volume (Pre-FX)
607    VolEnv,
608    /// Pan (Pre-FX)
609    PanEnv,
610    /// Volume
611    VolEnv2,
612    /// Pan
613    PanEnv2,
614    /// Width (Pre-FX)
615    WidthEnv,
616    /// Width
617    WidthEnv2,
618    /// Trim Volume
619    VolEnv3,
620    /// Mute
621    MuteEnv,
622    /// Use this for all non-common envelope names.
623    ///
624    /// Use [`custom()`] to create this variant.
625    ///
626    /// [`custom()`]: #method.custom
627    Custom(Cow<'a, CStr>),
628}
629
630impl<'a> EnvChunkName<'a> {
631    /// Convenience function for creating a [`Custom`] name.
632    ///
633    /// [`Custom`]: #variant.Custom
634    pub fn custom(name: impl Into<ReaperStringArg<'a>>) -> EnvChunkName<'a> {
635        EnvChunkName::Custom(name.into().into_inner())
636    }
637
638    pub(crate) fn into_raw(self) -> Cow<'a, CStr> {
639        use EnvChunkName::*;
640        match self {
641            VolEnv => c_str!("VOLENV").into(),
642            PanEnv => c_str!("PANENV").into(),
643            VolEnv2 => c_str!("VOLENV2").into(),
644            PanEnv2 => c_str!("PANENV2").into(),
645            WidthEnv => c_str!("WIDTHENV").into(),
646            WidthEnv2 => c_str!("WIDTHENV2").into(),
647            VolEnv3 => c_str!("VOLENV3").into(),
648            MuteEnv => c_str!("MUTEENV").into(),
649            Custom(name) => name,
650        }
651    }
652}
653
654#[cfg(test)]
655mod tests {
656    use super::*;
657
658    #[test]
659    fn serialize_track_attribute_key() {
660        use TrackAttributeKey::*;
661        assert_eq!(Mute.into_raw().as_ref(), c_str!("B_MUTE"));
662        assert_eq!(
663            Env(EnvChunkName::VolEnv).into_raw().as_ref(),
664            c_str!("P_ENV:<VOLENV")
665        );
666        assert_eq!(
667            Env(EnvChunkName::Custom(c_str!("MYENV").into()))
668                .into_raw()
669                .as_ref(),
670            c_str!("P_ENV:<MYENV")
671        );
672        assert_eq!(
673            TrackAttributeKey::ext("SWS_FOO").into_raw().as_ref(),
674            c_str!("P_EXT:SWS_FOO")
675        );
676        assert_eq!(
677            TrackAttributeKey::custom(c_str!("BLA")).into_raw().as_ref(),
678            c_str!("BLA")
679        );
680    }
681}