reaper_medium/
reaper_pointer.rs

1use super::{MediaItem, MediaItemTake, MediaTrack, ReaProject, TrackEnvelope};
2use crate::{concat_c_strs, ReaperStringArg};
3use c_str_macro::c_str;
4use reaper_low::raw;
5use std::borrow::Cow;
6use std::ffi::CStr;
7use std::os::raw::c_void;
8use std::ptr::NonNull;
9
10/// Validatable REAPER pointer.
11#[derive(Clone, Eq, PartialEq, Hash, Debug)]
12pub enum ReaperPointer<'a> {
13    MediaTrack(MediaTrack),
14    ReaProject(ReaProject),
15    MediaItem(MediaItem),
16    MediaItemTake(MediaItemTake),
17    TrackEnvelope(TrackEnvelope),
18    PcmSource(NonNull<raw::PCM_source>),
19    /// If a variant is missing in this enum, you can use this custom one as a resort.
20    ///
21    /// Use [`custom()`] to create this variant.
22    ///
23    /// [`custom()`]: #method.custom
24    Custom {
25        type_name: Cow<'a, CStr>,
26        pointer: *mut c_void,
27    },
28}
29
30impl<'a> ReaperPointer<'a> {
31    /// Convenience function for creating a [`Custom`] pointer.
32    ///
33    /// **Don't** include the trailing asterisk (`*`)! It will be added automatically.
34    ///
35    /// [`Custom`]: #variant.Custom
36    pub fn custom(pointer: *mut c_void, type_name: impl Into<ReaperStringArg<'a>>) -> Self {
37        Self::Custom {
38            pointer,
39            type_name: type_name.into().into_inner(),
40        }
41    }
42
43    pub(crate) fn key_into_raw(self) -> Cow<'a, CStr> {
44        use ReaperPointer::*;
45        match self {
46            MediaTrack(_) => c_str!("MediaTrack*").into(),
47            ReaProject(_) => c_str!("ReaProject*").into(),
48            MediaItem(_) => c_str!("MediaItem*").into(),
49            MediaItemTake(_) => c_str!("MediaItem_Take*").into(),
50            TrackEnvelope(_) => c_str!("TrackEnvelope*").into(),
51            PcmSource(_) => c_str!("PCM_source*").into(),
52            Custom {
53                pointer: _,
54                type_name,
55            } => concat_c_strs(type_name.as_ref(), c_str!("*")).into(),
56        }
57    }
58
59    pub(crate) fn ptr_as_void(&self) -> *mut c_void {
60        use ReaperPointer::*;
61        match self {
62            MediaTrack(p) => p.as_ptr() as *mut _,
63            ReaProject(p) => p.as_ptr() as *mut _,
64            MediaItem(p) => p.as_ptr() as *mut _,
65            MediaItemTake(p) => p.as_ptr() as *mut _,
66            TrackEnvelope(p) => p.as_ptr() as *mut _,
67            PcmSource(p) => p.as_ptr() as *mut _,
68            Custom { pointer, .. } => *pointer,
69        }
70    }
71}
72
73/// For just having to pass a NonNull pointer to `validate_ptr_2`. Very convenient!
74macro_rules! impl_from_ptr_to_variant {
75    ($struct_type: ty, $enum_name: ident) => {
76        impl<'a> From<$struct_type> for ReaperPointer<'a> {
77            fn from(p: $struct_type) -> Self {
78                ReaperPointer::$enum_name(p)
79            }
80        }
81    };
82}
83
84impl_from_ptr_to_variant!(MediaTrack, MediaTrack);
85impl_from_ptr_to_variant!(ReaProject, ReaProject);
86impl_from_ptr_to_variant!(MediaItem, MediaItem);
87impl_from_ptr_to_variant!(MediaItemTake, MediaItemTake);
88impl_from_ptr_to_variant!(TrackEnvelope, TrackEnvelope);
89impl_from_ptr_to_variant!(NonNull<raw::PCM_source>, PcmSource);