1
1
use * ;
2
+ use std:: panic:: { AssertUnwindSafe , catch_unwind} ;
2
3
3
4
/// Context for some callbacks.
4
5
pub struct JackCallbackContext {
@@ -33,6 +34,10 @@ pub enum JackControl {
33
34
/// Stop processing.
34
35
Stop = -1
35
36
}
37
+ /// Trait for an object that implements JACK callbacks.
38
+ ///
39
+ /// Most of the default implementations return `JackControl::Continue` - however, **process() does not** - you
40
+ /// must explicitly override this behaviour if you want to specify nothing for `process()`.
36
41
pub trait JackHandler : Send {
37
42
/// This function is called by the engine any time there is work to be done.
38
43
/// Return `JackControl::Stop` to stop processing, otherwise return
@@ -53,34 +58,119 @@ pub trait JackHandler: Send {
53
58
fn process ( & mut self , _ctx : & JackCallbackContext ) -> JackControl {
54
59
JackControl :: Stop
55
60
}
61
+ /// This is called whenever the size of the the buffer that will be passed to the
62
+ /// `process()` function is about to change.
63
+ /// Clients that depend on knowing the buffer size must implement this callback.
64
+ fn buffer_size ( & mut self , _new_size : jack_nframes_t ) -> JackControl { JackControl :: Continue }
65
+ /// Called whenever the system sample rate changes.
66
+ ///
67
+ /// Given that the JACK API exposes no way to change the sample rate, the library author
68
+ /// would like you to know that this is a decidedly rare occurence. Still, it's worth
69
+ /// being prepared ;)
70
+ fn sample_rate ( & mut self , _new_rate : jack_nframes_t ) -> JackControl { JackControl :: Continue }
71
+ /// Called just once after the creation of the thread in which all other callbacks are
72
+ /// handled.
73
+ fn thread_init ( & mut self ) { }
74
+ /// To be called if and when the JACK server shuts down the client thread.
75
+ fn shutdown ( & mut self , _status : JackStatus , _reason : & str ) { }
76
+ /// Called whenever a client is registered or unregistered.
77
+ ///
78
+ /// Use the `registered` argument to determine which it is.
79
+ fn client_registered ( & mut self , _name : & str , _registered : bool ) { }
80
+ /// Called when an XRUN (over- or under- run) occurs.
81
+ fn xrun ( & mut self ) -> JackControl { JackControl :: Continue }
56
82
}
83
+ /*
84
+ /// Called whenever a port is registered or unregistered.
85
+ ///
86
+ /// Use the `registered` argument to determine which it is.
87
+ fn port_registered(&mut self, _port: JackPort, _registered: bool) { }
88
+ /// Called whenever a port is renamed.
89
+ fn port_renamed(&mut self, _port: JackPort, _old_name: &str, _new_name: &str) { }
90
+ /// Called whenever ports are connected or disconnected.
91
+ ///
92
+ /// Use the `connected` argument to determine which it is.
93
+ fn port_connected(&mut self, _from: JackPort, _to: JackPort, _connected: bool) { }
94
+ /// Called whenever the processing graph is reordered.
95
+ fn graph_reorder(&mut self) -> JackControl { JackControl::Continue }
96
+ /// Called when the JACK server starts or stops freewheeling.
97
+ ///
98
+ /// Use the `freewheel` argument to determine which it is.
99
+ fn freewheel(&mut self, _freewheel: bool) { }
100
+ */
57
101
58
102
impl < F > JackHandler for F where F : FnMut ( & JackCallbackContext ) -> JackControl + Send + ' static {
59
103
fn process ( & mut self , ctx : & JackCallbackContext ) -> JackControl {
60
104
self ( ctx)
61
105
}
62
106
}
107
+ unsafe extern "C" fn buffer_size_callback < T > ( frames : jack_nframes_t , user : * mut libc:: c_void ) -> libc:: c_int where T : JackHandler {
108
+ let callbacks = & mut * ( user as * mut T ) ;
109
+ catch_unwind ( AssertUnwindSafe ( || {
110
+ callbacks. buffer_size ( frames) as _
111
+ } ) ) . unwrap_or ( -1 )
112
+ }
113
+ unsafe extern "C" fn sample_rate_callback < T > ( frames : jack_nframes_t , user : * mut libc:: c_void ) -> libc:: c_int where T : JackHandler {
114
+ let callbacks = & mut * ( user as * mut T ) ;
115
+ catch_unwind ( AssertUnwindSafe ( || {
116
+ callbacks. sample_rate ( frames) as _
117
+ } ) ) . unwrap_or ( -1 )
118
+ }
119
+ unsafe extern "C" fn client_registration_callback < T > ( name : * const libc:: c_char , register : libc:: c_int , user : * mut libc:: c_void ) where T : JackHandler {
120
+ let callbacks = & mut * ( user as * mut T ) ;
121
+ let name = CStr :: from_ptr ( name) ;
122
+ let _ = catch_unwind ( AssertUnwindSafe ( || {
123
+ callbacks. client_registered ( & name. to_string_lossy ( ) , register != 0 )
124
+ } ) ) ;
63
125
64
- extern "C" fn process_callback < T > ( nframes : jack_nframes_t , user : * mut libc:: c_void ) -> i32 where T : JackHandler {
65
- unsafe {
66
- let callbacks = & mut * ( user as * mut T ) ;
67
- let ctx = JackCallbackContext {
68
- nframes : nframes
69
- } ;
70
- callbacks. process ( & ctx) as i32
71
- }
72
126
}
127
+ unsafe extern "C" fn info_shutdown_callback < T > ( code : jack_status_t , reason : * const libc:: c_char , user : * mut libc:: c_void ) where T : JackHandler {
128
+ let callbacks = & mut * ( user as * mut T ) ;
129
+ let code = JackStatus :: from_bits_truncate ( code) ;
130
+ let reason = CStr :: from_ptr ( reason) ;
131
+ let _ = catch_unwind ( AssertUnwindSafe ( || {
132
+ callbacks. shutdown ( code, & reason. to_string_lossy ( ) )
133
+ } ) ) ;
73
134
135
+ }
136
+ unsafe extern "C" fn thread_init_callback < T > ( user : * mut libc:: c_void ) where T : JackHandler {
137
+ let callbacks = & mut * ( user as * mut T ) ;
138
+ let _ = catch_unwind ( AssertUnwindSafe ( || {
139
+ callbacks. thread_init ( )
140
+ } ) ) ;
141
+ }
142
+ unsafe extern "C" fn process_callback < T > ( nframes : jack_nframes_t , user : * mut libc:: c_void ) -> libc:: c_int where T : JackHandler {
143
+ let callbacks = & mut * ( user as * mut T ) ;
144
+ let ctx = JackCallbackContext {
145
+ nframes : nframes
146
+ } ;
147
+ catch_unwind ( AssertUnwindSafe ( || {
148
+ callbacks. process ( & ctx) as _
149
+ } ) ) . unwrap_or ( -1 )
150
+ }
151
+ unsafe extern "C" fn xrun_callback < T > ( user : * mut libc:: c_void ) -> libc:: c_int where T : JackHandler {
152
+ let callbacks = & mut * ( user as * mut T ) ;
153
+ catch_unwind ( AssertUnwindSafe ( || {
154
+ callbacks. xrun ( ) as _
155
+ } ) ) . unwrap_or ( -1 )
156
+ }
74
157
pub fn set_handler < F > ( conn : & mut JackConnection < Deactivated > , handler : F ) -> JackResult < ( ) > where F : JackHandler {
75
158
let user_ptr = Box :: into_raw ( Box :: new ( handler) ) ;
76
159
let user_ptr = user_ptr as * mut libc:: c_void ;
77
- let code = unsafe {
78
- jack_set_process_callback ( conn. handle , Some ( process_callback :: < F > ) , user_ptr)
79
- } ;
80
- if code != 0 {
81
- Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback()" , code) ) ?
82
- }
83
- else {
84
- Ok ( ( ) )
160
+ unsafe {
161
+ let code = jack_set_process_callback ( conn. handle , Some ( process_callback :: < F > ) , user_ptr) ;
162
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - process" , code) ) ? }
163
+ let code = jack_set_thread_init_callback ( conn. handle , Some ( thread_init_callback :: < F > ) , user_ptr) ;
164
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - thread_init" , code) ) ? }
165
+ let code = jack_set_buffer_size_callback ( conn. handle , Some ( buffer_size_callback :: < F > ) , user_ptr) ;
166
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - buffer_size" , code) ) ? }
167
+ let code = jack_set_sample_rate_callback ( conn. handle , Some ( sample_rate_callback :: < F > ) , user_ptr) ;
168
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - sample_rate" , code) ) ? }
169
+ let code = jack_set_xrun_callback ( conn. handle , Some ( xrun_callback :: < F > ) , user_ptr) ;
170
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - xrun" , code) ) ? }
171
+ let code = jack_set_client_registration_callback ( conn. handle , Some ( client_registration_callback :: < F > ) , user_ptr) ;
172
+ if code != 0 { Err ( ErrorKind :: UnknownErrorCode ( "set_process_callback() - client_registration" , code) ) ? }
173
+ jack_on_info_shutdown ( conn. handle , Some ( info_shutdown_callback :: < F > ) , user_ptr) ;
85
174
}
175
+ Ok ( ( ) )
86
176
}
0 commit comments