1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! User-facing macros.
//!
//! The only macro for now is [`plugin_entry!`](crate::plugin_entry),
//! which emits the `#[no_mangle] extern "C"` CFPlugIn factory
//! function `coreaudiod` resolves to instantiate the plug-in. It is
//! the macOS counterpart of `tympan-apo`'s `register_apo!` and
//! `tympan-ladspa`'s `plugin_entry!`.
/// Expose a `T: Driver` implementation as the AudioServerPlugin this
/// `.driver` bundle provides.
///
/// Emits, in the calling crate's root:
///
/// - A hidden `__tympan_aspl_create` constructor that yields an
/// `Arc<dyn AnyDriver>` over [`DriverInstance<T>`](crate::driver::DriverInstance).
/// - A `#[no_mangle] pub unsafe extern "C"` factory function — by
/// default named `TympanAsplDriverFactory` — that forwards to
/// `raw::driver_factory_dispatch`
/// with that constructor.
///
/// The factory function name is the symbol the bundle `Info.plist`'s
/// `CFPlugInFactories` dictionary must point at — pass the same name
/// to [`BundleConfig`](crate::bundle::BundleConfig). An optional
/// second argument overrides the default symbol name.
///
/// ## Usage
///
/// ```ignore
/// use tympan_aspl::{Driver, DeviceSpec, IoBuffer, RealtimeContext};
///
/// struct MyDriver;
/// impl Driver for MyDriver {
/// const NAME: &'static str = "My Driver";
/// const MANUFACTURER: &'static str = "Me";
/// const VERSION: &'static str = "0.1.0";
/// fn new() -> Self { Self }
/// fn device(&self) -> DeviceSpec {
/// DeviceSpec::new("com.me.mydriver", "My Driver", "Me")
/// }
/// fn process_io(&mut self, _rt: &RealtimeContext, buf: &mut IoBuffer<'_>) {
/// buf.silence_output();
/// }
/// }
///
/// // Default factory symbol name (`TympanAsplDriverFactory`):
/// tympan_aspl::plugin_entry!(MyDriver);
///
/// // …or an explicit one, matched in the bundle Info.plist:
/// // tympan_aspl::plugin_entry!(MyDriver, MyDriverFactory);
/// ```
///
/// ## Single call per crate
///
/// The macro emits a `#[no_mangle]` symbol, which must be unique in
/// the link tree. Each `.driver` cdylib invokes `plugin_entry!`
/// exactly once at its crate root.
///
/// ## Cross-platform expansion
///
/// The macro expands on every platform: the CFPlugIn factory it
/// emits forwards to `raw::driver_factory_dispatch`, and the `raw`
/// module is ordinary cross-platform Rust — an `extern "C"`
/// function merely *uses* the C calling convention. So a driver
/// crate invoking `plugin_entry!` builds and unit-tests on any
/// host; only loading the resulting `.driver` bundle into
/// `coreaudiod` is macOS-specific.