rust_jack/port.rs
1use std::{ffi, slice};
2use jack_sys as j;
3use flags::*;
4use enums::*;
5use utils;
6
7/// Converts a jack client handle and jack port handle in a `Port`. If either
8/// `client` or `port` is `null`, then `None` is returned.
9pub unsafe fn ptrs_to_port(client: *mut j::jack_client_t,
10 port: *mut j::jack_port_t)
11 -> Option<Port> {
12 if client.is_null() || port.is_null() {
13 None
14 } else {
15 Some(Port {
16 client: client,
17 port: port,
18 })
19 }
20}
21
22pub unsafe fn port_pointer(port: &Port) -> *mut j::jack_port_t {
23 port.port
24}
25
26/// An endpoint to interact with Jack data streams, for audio, midi, etc...
27#[derive(Debug, Clone, Copy)]
28pub struct Port {
29 client: *mut j::jack_client_t,
30 port: *mut j::jack_port_t,
31}
32
33impl Port {
34 /// The maximum length of a full Jack port name. Unlike the "C" Jack API,
35 /// this does not count the `NULL` character and corresponds to a string's
36 /// `.len()`.
37 ///
38 /// The port's full name contains the owning client name concatenated with a
39 /// colon (:) followed by its short name.
40 ///
41 /// This value is constant
42 pub fn name_size() -> usize {
43 let s = unsafe { j::jack_port_name_size() - 1 };
44 s as usize
45 }
46
47 /// The maximum length of a port type. Unlike the "C" Jack API, this does
48 /// not count the `NULL` character and corresponds to a string's `.len()`.
49 ///
50 /// This value is constant.
51 pub fn type_size() -> usize {
52 let s = unsafe { j::jack_port_type_size() - 1 };
53 s as usize
54 }
55
56 /// Remove the port from the client, disconnecting any existing connections.
57 pub fn unregister(self) -> Result<(), JackErr> {
58 let res = unsafe { j::jack_port_unregister(self.client, self.port) };
59 match res {
60 0 => Ok(()),
61 _ => Err(JackErr::CallbackDeregistrationError),
62 }
63 }
64
65 /// Returns the full name of the port, including the "client_name:" prefix.
66 pub fn name<'a>(&'a self) -> &'a str {
67 unsafe { ffi::CStr::from_ptr(j::jack_port_name(self.port)).to_str().unwrap() }
68 }
69
70 /// Returns the short name of the port, it excludes the "client_name:" prefix.
71 pub fn short_name<'a>(&'a self) -> &'a str {
72 unsafe { ffi::CStr::from_ptr(j::jack_port_short_name(self.port)).to_str().unwrap() }
73 }
74
75 /// Returns the uuid of the port as a u64.
76 pub fn uuid(&self) -> u64 {
77 unsafe { j::jack_port_uuid(self.port) }
78 }
79
80 /// The flags for the port. These are set when the port is registered with
81 /// its client.
82 pub fn flags(&self) -> PortFlags {
83 let bits = unsafe { j::jack_port_flags(self.port) };
84 PortFlags::from_bits(bits as u32).unwrap()
85 }
86
87 /// The port type. Jack's built in types include "32 bit float mono audio"
88 /// and "8 bit raw midi". Custom types may also be used.
89 pub fn port_type<'a>(&self) -> &'a str {
90 unsafe { ffi::CStr::from_ptr(j::jack_port_type(self.port)).to_str().unwrap() }
91 }
92
93 /// Number of ports connected to/from
94 pub fn connected_count(&self) -> usize {
95 let n = unsafe { j::jack_port_connected(self.port) };
96 n as usize
97 }
98
99 /// Returns `true` if the port is directly connected to a port with the name
100 /// `port_name`.
101 pub fn is_connected_to(&self, port_name: &str) -> bool {
102 let res = unsafe {
103 let port_name = ffi::CString::new(port_name).unwrap();
104 j::jack_port_connected_to(self.port, port_name.as_ptr())
105 };
106 match res {
107 0 => false,
108 _ => true,
109 }
110 }
111
112 /// Full port names to which `self` is connected to. This combines Jack's
113 /// `jack_port_get_all_connections()` and `jack_port_get_connections()`. If
114 /// the `client` from which `port` was spawned from is the owner, then it
115 /// may be used in the graph reordered callback or else it should not be
116 /// used.
117 ///
118 /// # Unsafe
119 ///
120 /// * Can't be used in the callback for graph reordering under certain
121 /// conditions.
122 pub unsafe fn connections(&self) -> Vec<String> {
123 let connections_ptr = {
124 let ptr = if j::jack_port_is_mine(self.client, self.port) != 0 {
125 j::jack_port_get_connections(self.port)
126 } else {
127 j::jack_port_get_all_connections(self.client, self.port)
128 };
129 utils::collect_strs(ptr)
130 };
131 connections_ptr
132 }
133
134 /// Get the alias names for `self`.
135 ///
136 /// Will return a vector of strings of up to 2 elements.
137 ///
138 /// # TODO: Implement
139 pub fn aliases(&self) -> Vec<String> {
140 unimplemented!();
141 }
142
143 /// Returns `true` if monitoring has been requested for `self`.
144 pub fn is_monitoring_input(&self) -> bool {
145 match unsafe { j::jack_port_monitoring_input(self.port) } {
146 0 => false,
147 _ => true,
148 }
149 }
150
151 /// Set's the short name of the port. If the full name is longer than
152 /// `Port::name_size()`, then it will be truncated.
153 pub fn set_name(&self, short_name: &str) -> Result<(), JackErr> {
154 let short_name = ffi::CString::new(short_name).unwrap();
155 let res = unsafe { j::jack_port_set_name(self.port, short_name.as_ptr()) };
156 match res {
157 0 => Ok(()),
158 _ => Err(JackErr::PortNamingError),
159 }
160 }
161
162 /// Sets `alias` as an alias for `self`.
163 ///
164 /// May be called at any time. If the alias is longer than
165 /// `Client::name_size()`, it will be truncated.
166 ///
167 /// After a successful call, and until Jack exists, or the alias is unset,
168 /// `alias` may be used as an alternate name for the port.
169 ///
170 /// Ports can have up to two aliases - if both are already set, this
171 /// function will return an error.
172 pub fn set_alias(&self, alias: &str) -> Result<(), JackErr> {
173 let alias = ffi::CString::new(alias).unwrap();
174 let res = unsafe { j::jack_port_set_alias(self.port, alias.as_ptr()) };
175 match res {
176 0 => Ok(()),
177 _ => Err(JackErr::PortAliasError),
178 }
179 }
180
181 /// Remove `alias` as an alias for port. May be called at any time.
182 ///
183 /// After a successful call, `alias` can no longer be used as an alternate
184 /// name for `self`.
185 pub fn unset_alias(&self, alias: &str) -> Result<(), JackErr> {
186 let alias = ffi::CString::new(alias).unwrap();
187 let res = unsafe { j::jack_port_unset_alias(self.port, alias.as_ptr()) };
188 match res {
189 0 => Ok(()),
190 _ => Err(JackErr::PortAliasError),
191 }
192 }
193
194 /// Turn input monitoring for the port on or off.
195 ///
196 /// This only works if the port has the `CAN_MONITOR` flag set.
197 pub fn request_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
198 let onoff = match enable_monitor {
199 true => 1,
200 false => 0,
201 };
202 let res = unsafe { j::jack_port_request_monitor(self.port, onoff) };
203 match res {
204 0 => Ok(()),
205 _ => Err(JackErr::PortMonitorError),
206 }
207 }
208
209 /// If the `CAN_MONITOR` flag is set for the port, then input monitoring is
210 /// turned on if it was off, and turns it off if only one request has been
211 /// made to turn it on. Otherwise it does nothing.
212 pub fn ensure_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
213 let onoff = match enable_monitor {
214 true => 1,
215 false => 0,
216 };
217 let res = unsafe { j::jack_port_ensure_monitor(self.port, onoff) };
218 match res {
219 0 => Ok(()),
220 _ => Err(JackErr::PortMonitorError),
221 }
222 }
223
224 /// Perform the same function as `Client::disconnect_ports()`, but with a
225 /// port handle instead.
226 ///
227 /// Avoids the name lookup inherent in the name-based version.
228 ///
229 /// Clients connecting their own ports are likely to use this function,
230 /// while generic connection clients (e.g. patchbays) would use
231 /// `Client::disconnect_ports()`.
232 pub fn disconnect(&self) -> Result<(), JackErr> {
233 match unsafe { j::jack_port_disconnect(self.client, self.port) } {
234 0 => Ok(()),
235 _ => Err(JackErr::PortDisconnectionError),
236 }
237 }
238
239 /// Returns a pointer to the memory area associated with the specified
240 /// port. For an output port, it will be a memory area that can be written
241 /// to; for an input port, it will be an area containing the data from the
242 /// port's connection(s), or zero-filled. If there are multiple inbound
243 /// connections, the data will be mixed appropriately.
244 ///
245 /// Do not cache the returned address across `process()` calls. Port buffers
246 /// have to be retrieved in each callback for proper functioning.
247 pub unsafe fn buffer(&self, n_frames: u32) -> *mut ::libc::c_void {
248 j::jack_port_get_buffer(self.port, n_frames)
249 }
250
251 /// Interprets the buffer as a slice of type `T` with length `n_frames`.
252 pub unsafe fn as_slice<T>(&self, n_frames: u32) -> &[T] {
253 let buffer = self.buffer(n_frames) as *const T;
254 slice::from_raw_parts(buffer, n_frames as usize)
255 }
256
257 /// Interprets the buffer as a mutable slice of type `T` with length
258 /// `n_frames`.
259 pub unsafe fn as_slice_mut<T>(&self, n_frames: u32) -> &mut [T] {
260 let buffer = self.buffer(n_frames) as *mut T;
261 slice::from_raw_parts_mut(buffer, n_frames as usize)
262 }
263}