1/** 2 3@mainpage liblscp 4 5 6@section Intro 7 8Hi all, 9 10On the path to a GUI for linuxsampler, I've been taking some of my spare 11time by writing an early implementation for the LSCP (the LinuxSampler 12Control Protocol), as defined from the current available draft document 13(https://www.linuxsampler.org/api/draft-linuxsampler-protocol.html). 14 15My implementation, while still rather crude, is taking the form of a 16programming library for plain conventional C, codenamed liblscp. 17 18One of my objectives is that liblscp evolves as the implementation for a 19linuxsampler API, while being a fair abstraction for the network and/or 20IPC aspects of LSCP. 21 22For the facts, liblscp is actually a wrapper for the LSCP specification, 23taking all the TCP/UDP socket communication into it's main control, hiding 24all or some of the protocol bureoucracy from the user and exposing a 25simple and opaque C programming language interface, mainly by mapping 26events to user function callback handlers. 27 28The design of liblscp assumed that the programming interface provided is 29useable and applicable either for server (linuxsampler itself) and/or 30client (gui's) development. 31 32Some design features (no rocket-sci here :) 33 34- Multi-threaded or multiplexed server; clients block for synchronous 35 request calls. 36- Multi-client; one server instance serves many clients, local and/or 37 remote. 38- Server events broadcasted and delivered to client callbacks. 39- Client requests processed on server supplied callback. 40 41Please note that (as usual :) documentation is none at this stage but I'll 42challenge you to look at the source code provided on the tarball below. A 43barebones server and client test programs are included (lscp_server_test 44and lscp_client_test). 45 46 47@section Client 48 49As a quick reference for the client programming, one links to liblscp to 50create a client instance handle, just like this:<pre> 51 52 #include <lscp/@ref:client.h> 53 54 @ref lscp_client_t *client; 55 56 client = @ref lscp_client_create (server_host, server_port, 57 client_callback, client_data); 58 59</pre>where server_host is the hostname of the server we wish to connect, and 60server_port is the respective port number; client_callback is the client 61supplied callback function that will handle every server notification 62event; client_data is intended for client context and will be fed to 63client_callback without intervention. 64 65The client may issue a request to server by use of:<pre> 66 67 @ref lscp_client_query (client, query); 68 69</pre>where you'll submit a single command to the server and wait for it's response. 70The query string must be null terminated. The server response result maybe 71retrieved by:<pre> 72 73 char *result; 74 75 result = @ref lscp_client_get_result(client); 76 77</pre>and the eventual error status code:<pre> 78 79 int errno; 80 81 errno = @ref lscp_client_get_errno(client); 82 83</pre>The client callback function must have the following prototype (@ref lscp_client_proc_t): 84 85- @ref lscp_status_t <i>client_callback</i> ( @ref lscp_client_t *client, 86 @ref lscp_event_t event, const char *buf, int buflen, void *client_data ); 87 88where event is the specific event type notification, buf will be a pointer to 89the event text which is buflen bytes in length; client_data is exactly the same 90value given on @ref lscp_client_create call. 91 92This callback function is the place to handle all server notifications and 93will be only called if the client is currently subscribed. No response 94from the client is expected while processing an event within 95client_callback. 96 97A client subscribes to receive event notifications by calling:<pre> 98 99 @ref lscp_client_subscribe (client, events); 100 101</pre>after which it will start receiving events by means of the supplied 102client_callback function. To unsubscribe and stop this deliverance:<pre> 103 104 @ref lscp_client_unsubscribe (client, events); 105 106</pre>Finally, when a client is about to quit, the proper terminator is in order:<pre> 107 108 @ref lscp_client_destroy (client); 109 110</pre>As for the current protocol draft (11), the client interface already maps 111the following functions defined in <lscp/@ref:client.h>, one for each corresponding 112LSCP comand, and regarding the sampler channel space:<pre> 113 114 @ref lscp_get_available_engines (client); 115 @ref lscp_list_available_engines (client); 116 @ref lscp_get_engine_info (client, engine_name); 117 @ref lscp_get_channels (client); 118 @ref lscp_list_channels (client); 119 @ref lscp_add_channel (client); 120 @ref lscp_load_engine (client, engine_name, channel); 121 @ref lscp_set_channel_audio_device (client, channel, audio_device); 122 @ref lscp_set_channel_audio_type (client, channel, audio_type); 123 @ref lscp_set_channel_audio_channel (client, channel, audio_in, audio_out); 124 @ref lscp_set_channel_midi_device (client, channel, midi_device); 125 @ref lscp_set_channel_midi_type (client, channel, midi_type); 126 @ref lscp_set_channel_midi_port (client, channel, midi_port); 127 @ref lscp_set_channel_midi_channel (client, channel, midi_channel); 128 @ref lscp_set_channel_midi_map (client, channel, midi_map); 129 @ref lscp_set_channel_mute (client, channel, mute); 130 @ref lscp_set_channel_solo (client, channel, solo); 131 @ref lscp_set_channel_volume (client, channel, volume); 132 @ref lscp_load_instrument (client, file_name, instr_index, channel); 133 @ref lscp_load_instrument_non_modal (client, file_name, instr_index, channel); 134 @ref lscp_get_channel_info (client, channel); 135 @ref lscp_get_channel_voice_count (client, channel); 136 @ref lscp_get_channel_stream_count (client, channel); 137 @ref lscp_get_channel_buffer_fill (client, usage_type, channel); 138 @ref lscp_reset_channel (client, channel); 139 @ref lscp_remove_channel (client, channel); 140 @ref lscp_reset_sampler (client); 141 @ref lscp_get_server_info (client); 142 @ref lscp_get_total_voice_count (client); 143 @ref lscp_get_total_voice_count_max (client); 144 @ref lscp_get_volume (client); 145 @ref lscp_set_volume (client); 146 147</pre>Specific for sampler channel effect sends control:<pre> 148 149 @ref lscp_create_fxsend (client, channel, midi_controller, name); 150 @ref lscp_destroy_fxsend (client, channel, fxsend); 151 @ref lscp_get_fxsends (client, channel); 152 @ref lscp_list_fxsends (client, channel); 153 @ref lscp_get_fxsend_info (client, channel, fxsend); 154 @ref lscp_set_fxsend_name (client, channel, fxsend, name); 155 @ref lscp_set_fxsend_midi_controller (client, channel, fxsend, midi_controller); 156 @ref lscp_set_fxsend_audio_channel (client, channel, fxsend, audio_src, audio_dst); 157 @ref lscp_set_fxsend_level (client, channel, fxsend, level); 158 159</pre>Specific to MIDI instrument mapping interface:<pre> 160 161 @ref lscp_add_midi_instrument_map (client, map_name); 162 @ref lscp_remove_midi_instrument_map (client, midi_map); 163 @ref lscp_get_midi_instrument_maps (client); 164 @ref lscp_list_midi_instrument_maps (client); 165 @ref lscp_get_midi_instrument_map_name (client, midi_map); 166 @ref lscp_set_midi_instrument_map_name (client, midi_map, map_name); 167 @ref lscp_map_midi_instrument (client, midi_instr, engine_name, file_name, instr_index, volume, load_mode, name); 168 @ref lscp_unmap_midi_instrument (client, midi_instr); 169 @ref lscp_get_midi_instruments (client, midi_map); 170 @ref lscp_list_midi_instruments (client, midi_map); 171 @ref lscp_get_midi_instrument_info (client, midi_instr); 172 @ref lscp_clear_midi_instruments (client, midi_map); 173 174</pre>For the audio output and MIDI input device configuration interface, 175the following functions are respectively defined in <lscp/@ref:device.h>:<pre> 176 177 @ref lscp_get_available_audio_drivers (client); 178 @ref lscp_list_available_audio_drivers (client); 179 @ref lscp_get_audio_driver_info (client, audio_driver); 180 @ref lscp_get_audio_driver_param_info (client, audio_driver, param_key, deplist); 181 @ref lscp_create_audio_device (client, audio_driver, params); 182 @ref lscp_destroy_audio_device (client, audio_device); 183 @ref lscp_get_audio_devices (client); 184 @ref lscp_list_audio_devices (client); 185 @ref lscp_get_audio_device_info (client, audio_device); 186 @ref lscp_set_audio_device_param (client, audio_device, param); 187 @ref lscp_get_audio_channel_info (client, audio_device, audio_channel); 188 @ref lscp_get_audio_channel_param_info (client, audio_device, audio_channel, param); 189 @ref lscp_set_audio_channel_param (client, audio_device, audio_channel, param); 190 191 @ref lscp_get_available_midi_drivers (client); 192 @ref lscp_list_available_midi_drivers (client); 193 @ref lscp_get_midi_driver_info (client, midi_driver); 194 @ref lscp_get_midi_driver_param_info (client, midi_driver, param_key, deplist); 195 @ref lscp_create_midi_device (client, midi_driver, params); 196 @ref lscp_destroy_midi_device (client, midi_device); 197 @ref lscp_get_midi_devices (client); 198 @ref lscp_list_midi_devices (client); 199 @ref lscp_get_midi_device_info (client, midi_device); 200 @ref lscp_set_midi_device_param (client, midi_device, param); 201 @ref lscp_get_midi_port_info (client, midi_device, midi_port); 202 @ref lscp_get_midi_port_param_info (client, midi_device, midi_port, param); 203 @ref lscp_set_midi_port_param (client, midi_device, midi_port, param); 204 205</pre>For editing instruments while playing them with the sampler:<pre> 206 207 @ref lscp_edit_channel_instrument (client, channel); 208 209</pre>Most of these functions are wrappers to @ref lscp_client_query, and some will handle 210and change the result string accordingly. 211 212 213@section Server 214 215Likewise, and least important yet as for server programming, you create a server 216instance handle just like that:<pre> 217 218 #include <lscp/@ref:server.h> 219 220 @ref lscp_server_t *server; 221 222 server = @ref lscp_server_create (server_port, server_callback, server_data); 223 224</pre>where server_port is the port number where the server will be 225listening for connections; server_callback is the server supplied 226callback function that will handle every client request; server_data is 227any reference to data that will be fed into server_callback without 228modification. 229 230The server callback function prototype is very similar to the client one 231(@ref lscp_server_proc_t): 232 233- @ref lscp_status_t <i>server_callback</i> ( @ref lscp_connect_t *conn, 234 const char *request, int reqlen, void *server_data ); 235 236where conn is just a client connection handle, that shall be used for the 237server responses; the request text which has a length of reqlen bytes; 238server_data is the same value given on lscp_server_create. 239 240There's two special server callback cases, flagged by a null request pointer 241and described with reqlen as a boolean value: when zero it announces a new 242client connection, otherwise it tells that a client connection has closed. 243 244While handling each request the server must cook it's response and 245eventually issue the following:<pre> 246 247 @ref lscp_server_result (conn, result, reslen); 248 249</pre>where conn is the client handle, and result is a pointer to the server 250response literal text of reslen bytes. Of course the response shall obey 251to the protocol specification. 252 253The server issues a broadcast to its subscribers by simply issuing:<pre> 254 255 @ref lscp_server_broadcast (server, buf, buflen); 256 257</pre>which will trigger the client callback function, which will be fed with an 258exact copy of buf/len; this is the intended way to deliver all 259notifications to each subscribed client. 260 261When its time to shutdown the server instance, just don't forget to call 262the server destructor:<pre> 263 264 @ref lscp_server_destroy (server); 265 266</pre>and we're done with the server. 267 268 269@section Outro 270 271Nuff said. If you care or dare, track the revolving under: 272 273- https://www.rncbc.org/snapshots/#liblscp 274- https://www.rncbc.org/archive/#liblscp 275 276Please note that the code is known to compile and run on Linux AND on 277Windows (!). On Linux the main target is a shared library (liblscp.so) so 278remember to set your LD_LIBRARY_PATH accordingly before running the test 279programs. 280 281A final disclaimer goes to the fact that I AM NOT a socket nor thread 282programming guru, whatsoever. So fundamental mistakes may be laying around, 283somewhere. Besides that ItJustWorks(tm:). 284 285I'm eager to hear your feedback and comments. As usual, destructive 286criticism will be sent to /dev/null ;) 287 288Hope to be on the right track, and towards linuxsampler integration. 289 290Otherwise sorry for the bandwidth waste. 291 292Cheers. 293 294rncbc aka Rui Nuno Capela 295rncbc at rncbc.org 296 297@see https://www.linuxsampler.org 298 299*/ 300