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
// Author: Lars Op den Kamp (lars@opdenkamp-it.nl)
// Copyright (c) 2026 Op den Kamp IT Solutions
// Every type here is named as it appears in C, because C is the only thing
// that reads it. A header whose names were transliterated from Rust would make
// the reader translate in both directions.
//! C ABI for [`mx_remote`].
//!
//! The whole of this crate is one translation: it holds every `unsafe` in the
//! workspace, and adds no protocol logic of its own. Anything a caller can do
//! here is something the core crate already does; if a rule is not enforced in
//! `mx_remote`, it is not enforced at all.
//!
//! Three conventions run through the header, and knowing them is most of
//! knowing the API:
//!
//! - **A device is addressed by value.** There is no handle for a device or a
//! bay: a device is a [`mxr_uid_t`], a bay is a [`mxr_bay_uid_t`], and state
//! is read by passing one in and having a struct filled out. Nothing hands
//! back a pointer into state that a lock protects.
//! - **Every call returns, whatever happens.** An unwind across the boundary
//! is undefined behaviour, so each entry point catches: a panic becomes
//! [`mxr_result_t::MXR_ERR_PANIC`] rather than a corrupted stack.
//! - **A borrowed pointer lives for one call.** Strings and arrays handed to a
//! callback point into memory the library owns and reuses. A caller that
//! needs one afterwards copies it.
//!
//! Every failure code is negative and [`mxr_result_t::MXR_OK`] is zero, so
//! `if (rc < 0)` is a complete test, and a code added later cannot turn a
//! failure into a success.
//!
//! # From C
//!
//! ```c
//! #include <mx_remote.h>
//!
//! /* The client cannot be its own userdata: it does not exist when the table
//! * is handed over, so it reaches the callbacks through a struct that does. */
//! struct app { mxr_remote_t *remote; };
//!
//! static void on_device_update(void *userdata, mxr_uid_t device) {
//! mxr_device_info_t info;
//! if (mxr_device(((struct app *)userdata)->remote, device, &info) == MXR_OK)
//! printf("%s %s\n", info.model, info.name);
//! }
//!
//! int main(void) {
//! struct app app = {0};
//! mxr_callbacks_t cb = {0};
//! cb.on_device_update = on_device_update;
//!
//! /* Zeroing a config asks for every default; NULL does the same. */
//! app.remote = mxr_remote_new(NULL, &cb, &app);
//! mxr_remote_start(app.remote);
//! /* ... */
//! mxr_remote_free(app.remote);
//! return 0;
//! }
//! ```
//!
//! `include/mx_remote.h` is generated from this source by cbindgen and checked
//! into the repository. `include/mx_remote.hpp` is a hand-written header-only
//! C++ layer over it, with a move-only `mxr::Remote` that closes and joins in
//! its destructor and an `mxr::Handler` base class carrying a virtual method
//! per event.
// Everything the header exposes, re-exported flat: a Rust caller reaching for
// this crate wants the same surface a C caller gets, under the same names.
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;