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}