@@ -65,7 +65,49 @@ impl Client {
6565 ///
6666 /// Although the client may be successful in opening, there still may be some errors minor
6767 /// errors when attempting to opening. To access these, check the returned `ClientStatus`.
68+ ///
69+ /// `options` must not contain `SERVER_NAME`, `LOAD_NAME`, `LOAD_INIT`, or `SESSION_ID`, since
70+ /// those require extra arguments that this function does not take. If any are present,
71+ /// `Err(Error::InvalidClientOptions(options))` is returned. To connect to a named server, use
72+ /// [`Client::new_with_server_name`].
6873 pub fn new ( client_name : & str , options : ClientOptions ) -> Result < ( Self , ClientStatus ) , Error > {
74+ Self :: open ( client_name, None , options)
75+ }
76+
77+ /// Opens a JACK client connected to the JACK server named `server_name`. Behaves like
78+ /// [`Client::new`] otherwise.
79+ ///
80+ /// `ClientOptions::SERVER_NAME` is set automatically, and may also be included in `options`.
81+ /// `options` must not contain `LOAD_NAME`, `LOAD_INIT`, or `SESSION_ID`; if any are present,
82+ /// `Err(Error::InvalidClientOptions(options))` is returned.
83+ pub fn new_with_server_name (
84+ client_name : & str ,
85+ server_name : & str ,
86+ options : ClientOptions ,
87+ ) -> Result < ( Self , ClientStatus ) , Error > {
88+ Self :: open ( client_name, Some ( server_name) , options)
89+ }
90+
91+ fn open (
92+ client_name : & str ,
93+ server_name : Option < & str > ,
94+ options : ClientOptions ,
95+ ) -> Result < ( Self , ClientStatus ) , Error > {
96+ // `jack_client_open` is variadic: these options make libjack read extra arguments via
97+ // `va_arg`. Only the server name argument is ever passed, so any other such option would
98+ // cause libjack to read garbage.
99+ let mut allowed_vararg_options = ClientOptions :: empty ( ) ;
100+ if server_name. is_some ( ) {
101+ allowed_vararg_options |= ClientOptions :: SERVER_NAME ;
102+ }
103+ if !options
104+ . intersection ( ClientOptions :: VARARG_OPTIONS )
105+ . difference ( allowed_vararg_options)
106+ . is_empty ( )
107+ {
108+ return Err ( Error :: InvalidClientOptions ( options) ) ;
109+ }
110+
69111 let _m = CREATE_OR_DESTROY_CLIENT_MUTEX . lock ( ) . ok ( ) ;
70112
71113 // All of the jack_sys functions below assume the client library is loaded and will panic if
@@ -77,9 +119,22 @@ impl Client {
77119
78120 crate :: logging:: maybe_init_logging ( ) ;
79121 let mut status_bits = 0 ;
80- let client = unsafe {
81- let client_name = ffi:: CString :: new ( client_name) . unwrap ( ) ;
82- j:: jack_client_open ( client_name. as_ptr ( ) , options. bits ( ) , & mut status_bits)
122+ let client_name = ffi:: CString :: new ( client_name) . unwrap ( ) ;
123+ let client = match server_name {
124+ None => unsafe {
125+ j:: jack_client_open ( client_name. as_ptr ( ) , options. bits ( ) , & mut status_bits)
126+ } ,
127+ Some ( server_name) => {
128+ let server_name = ffi:: CString :: new ( server_name) . unwrap ( ) ;
129+ unsafe {
130+ j:: jack_client_open_with_server_name (
131+ client_name. as_ptr ( ) ,
132+ options. bits ( ) ,
133+ & mut status_bits,
134+ server_name. as_ptr ( ) ,
135+ )
136+ }
137+ }
83138 } ;
84139 let status = ClientStatus :: from_bits ( status_bits) . unwrap_or_else ( ClientStatus :: empty) ;
85140 if client. is_null ( ) {
0 commit comments