/[svn]/liblscp/trunk/src/client.c
ViewVC logotype

Contents of /liblscp/trunk/src/client.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 994 - (show annotations) (download)
Thu Dec 21 13:33:27 2006 UTC (12 years, 4 months ago) by capela
File MIME type: text/plain
File size: 69134 byte(s)
*  Added support for new (un)subscribable events:
     LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT,
     LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO,
     LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT,
     LSCP_EVENT_MIDI_INPUT_DEVICE_INFO,
     LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT,
     LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO,
     LSCP_EVENT_MIDI_INSTRUMENT_COUNT,
     LSCP_EVENT_MIDI_INSTRUMENT_INFO.

1 // client.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 *****************************************************************************/
22
23 #include "common.h"
24
25 // Default timeout value (in milliseconds).
26 #define LSCP_TIMEOUT_MSECS 500
27
28
29 // Local prototypes.
30
31 static void _lscp_client_evt_proc (void *pvClient);
32
33 static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
34 static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);
35
36
37 //-------------------------------------------------------------------------
38 // Event service (datagram oriented).
39
40 static void _lscp_client_evt_proc ( void *pvClient )
41 {
42 lscp_client_t *pClient = (lscp_client_t *) pvClient;
43
44 fd_set fds; // File descriptor list for select().
45 int fd, fdmax; // Maximum file descriptor number.
46 struct timeval tv; // For specifying a timeout value.
47 int iSelect; // Holds select return status.
48 int iTimeout;
49
50 char achBuffer[LSCP_BUFSIZ];
51 int cchBuffer;
52 const char *pszSeps = ":\r\n";
53 char * pszToken;
54 char * pch;
55 int cchToken;
56 lscp_event_t event;
57
58 #ifdef DEBUG
59 fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
60 #endif
61
62 while (pClient->evt.iState) {
63
64 // Prepare for waiting on select...
65 fd = (int) pClient->evt.sock;
66 FD_ZERO(&fds);
67 FD_SET((unsigned int) fd, &fds);
68 fdmax = fd;
69
70 // Use the timeout (x10) select feature ...
71 iTimeout = 10 * pClient->iTimeout;
72 if (iTimeout >= 1000) {
73 tv.tv_sec = iTimeout / 1000;
74 iTimeout -= tv.tv_sec * 1000;
75 }
76 else tv.tv_sec = 0;
77 tv.tv_usec = iTimeout * 1000;
78
79 // Wait for event...
80 iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
81 if (iSelect > 0 && FD_ISSET(fd, &fds)) {
82 // May recv now...
83 cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
84 if (cchBuffer > 0) {
85 // Make sure received buffer it's null terminated.
86 achBuffer[cchBuffer] = (char) 0;
87 // Parse for the notification event message...
88 pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".
89 if (strcasecmp(pszToken, "NOTIFY") == 0) {
90 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
91 event = lscp_event_from_text(pszToken);
92 // And pick the rest of data...
93 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
94 cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
95 // Double-check if we're really up to it...
96 if (pClient->events & event) {
97 // Invoke the client event callback...
98 if ((*pClient->pfnCallback)(
99 pClient,
100 event,
101 pszToken,
102 cchToken,
103 pClient->pvData) != LSCP_OK) {
104 pClient->evt.iState = 0;
105 }
106 }
107 }
108 } else {
109 lscp_socket_perror("_lscp_client_evt_proc: recv");
110 pClient->evt.iState = 0;
111 }
112 } // Check if select has in error.
113 else if (iSelect < 0) {
114 lscp_socket_perror("_lscp_client_evt_proc: select");
115 pClient->evt.iState = 0;
116 }
117
118 // Finally, always signal the event.
119 lscp_cond_signal(pClient->cond);
120 }
121
122 #ifdef DEBUG
123 fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
124 #endif
125 }
126
127
128 //-------------------------------------------------------------------------
129 // Event subscription helpers.
130
131 // Open the event service socket connection.
132 static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
133 {
134 lscp_socket_t sock;
135 struct sockaddr_in addr;
136 int cAddr;
137 #if defined(WIN32)
138 int iSockOpt = (-1);
139 #endif
140
141 // Prepare the event connection socket...
142 sock = socket(AF_INET, SOCK_STREAM, 0);
143 if (sock == INVALID_SOCKET) {
144 lscp_socket_perror("_lscp_client_evt_connect: socket");
145 return LSCP_FAILED;
146 }
147
148 #if defined(WIN32)
149 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
150 lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
151 #endif
152
153 #ifdef DEBUG
154 lscp_socket_getopts("_lscp_client_evt_connect:", sock);
155 #endif
156
157 // Use same address of the command connection.
158 cAddr = sizeof(struct sockaddr_in);
159 memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
160
161 // Start the connection...
162 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
163 lscp_socket_perror("_lscp_client_evt_connect: connect");
164 closesocket(sock);
165 return LSCP_FAILED;
166 }
167
168 // Set our socket agent struct...
169 lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
170
171 // And finally the service thread...
172 return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
173 }
174
175
176 // Subscribe to a single event.
177 static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )
178 {
179 const char *pszEvent;
180 char szQuery[LSCP_BUFSIZ];
181 int cchQuery;
182
183 if (pClient == NULL)
184 return LSCP_FAILED;
185
186 // Which (single) event?
187 pszEvent = lscp_event_to_text(event);
188 if (pszEvent == NULL)
189 return LSCP_FAILED;
190
191 // Build the query string...
192 cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);
193 // Just send data, forget result...
194 if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
195 lscp_socket_perror("_lscp_client_evt_request: send");
196 return LSCP_FAILED;
197 }
198
199 // Wait on response.
200 lscp_cond_wait(pClient->cond, pClient->mutex);
201
202 // Update as naively as we can...
203 if (iSubscribe)
204 pClient->events |= event;
205 else
206 pClient->events &= ~event;
207
208 return LSCP_OK;
209 }
210
211
212 //-------------------------------------------------------------------------
213 // Client versioning teller fuunction.
214
215
216 /** Retrieve the current client library version string. */
217 const char* lscp_client_package (void) { return LSCP_PACKAGE; }
218
219 /** Retrieve the current client library version string. */
220 const char* lscp_client_version (void) { return LSCP_VERSION; }
221
222 /** Retrieve the current client library build timestamp string. */
223 const char* lscp_client_build (void) { return __DATE__ " " __TIME__; }
224
225
226 //-------------------------------------------------------------------------
227 // Client socket functions.
228
229 /**
230 * Create a client instance, estabilishing a connection to a server hostname,
231 * which must be listening on the given port. A client callback function is
232 * also supplied for server notification event handling.
233 *
234 * @param pszHost Hostname of the linuxsampler listening server.
235 * @param iPort Port number of the linuxsampler listening server.
236 * @param pfnCallback Callback function to receive event notifications.
237 * @param pvData User context opaque data, that will be passed
238 * to the callback function.
239 *
240 * @returns The new client instance pointer if successfull, which shall be
241 * used on all subsequent client calls, NULL otherwise.
242 */
243 lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )
244 {
245 lscp_client_t *pClient;
246 struct hostent *pHost;
247 lscp_socket_t sock;
248 struct sockaddr_in addr;
249 int cAddr;
250 #if defined(WIN32)
251 int iSockOpt = (-1);
252 #endif
253
254 if (pfnCallback == NULL) {
255 fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
256 return NULL;
257 }
258
259 pHost = gethostbyname(pszHost);
260 if (pHost == NULL) {
261 lscp_socket_herror("lscp_client_create: gethostbyname");
262 return NULL;
263 }
264
265 // Allocate client descriptor...
266
267 pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
268 if (pClient == NULL) {
269 fprintf(stderr, "lscp_client_create: Out of memory.\n");
270 return NULL;
271 }
272 memset(pClient, 0, sizeof(lscp_client_t));
273
274 pClient->pfnCallback = pfnCallback;
275 pClient->pvData = pvData;
276
277 #ifdef DEBUG
278 fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);
279 #endif
280
281 // Prepare the command connection socket...
282
283 sock = socket(AF_INET, SOCK_STREAM, 0);
284 if (sock == INVALID_SOCKET) {
285 lscp_socket_perror("lscp_client_create: cmd: socket");
286 free(pClient);
287 return NULL;
288 }
289
290 #if defined(WIN32)
291 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
292 lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
293 #endif
294
295 #ifdef DEBUG
296 lscp_socket_getopts("lscp_client_create: cmd", sock);
297 #endif
298
299 cAddr = sizeof(struct sockaddr_in);
300 memset((char *) &addr, 0, cAddr);
301 addr.sin_family = pHost->h_addrtype;
302 memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
303 addr.sin_port = htons((short) iPort);
304
305 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
306 lscp_socket_perror("lscp_client_create: cmd: connect");
307 closesocket(sock);
308 free(pClient);
309 return NULL;
310 }
311
312 // Initialize the command socket agent struct...
313 lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
314
315 #ifdef DEBUG
316 fprintf(stderr, "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->cmd.sock, inet_ntoa(pClient->cmd.addr.sin_addr), ntohs(pClient->cmd.addr.sin_port));
317 #endif
318
319 // Initialize the event service socket struct...
320 lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
321 // No events subscribed, yet.
322 pClient->events = LSCP_EVENT_NONE;
323 // Initialize cached members.
324 pClient->audio_drivers = NULL;
325 pClient->midi_drivers = NULL;
326 pClient->audio_devices = NULL;
327 pClient->midi_devices = NULL;
328 pClient->engines = NULL;
329 pClient->channels = NULL;
330 pClient->midi_instruments = NULL;
331 pClient->midi_maps = NULL;
332 pClient->midi_map_name = NULL;
333 lscp_driver_info_init(&(pClient->audio_driver_info));
334 lscp_driver_info_init(&(pClient->midi_driver_info));
335 lscp_device_info_init(&(pClient->audio_device_info));
336 lscp_device_info_init(&(pClient->midi_device_info));
337 lscp_param_info_init(&(pClient->audio_param_info));
338 lscp_param_info_init(&(pClient->midi_param_info));
339 lscp_device_port_info_init(&(pClient->audio_channel_info));
340 lscp_device_port_info_init(&(pClient->midi_port_info));
341 lscp_param_info_init(&(pClient->audio_channel_param_info));
342 lscp_param_info_init(&(pClient->midi_port_param_info));
343 lscp_server_info_init(&(pClient->server_info));
344 lscp_engine_info_init(&(pClient->engine_info));
345 lscp_channel_info_init(&(pClient->channel_info));
346 lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
347 // Initialize error stuff.
348 pClient->pszResult = NULL;
349 pClient->iErrno = -1;
350 // Stream usage stuff.
351 pClient->buffer_fill = NULL;
352 pClient->iStreamCount = 0;
353 // Default timeout value.
354 pClient->iTimeout = LSCP_TIMEOUT_MSECS;
355 pClient->iTimeoutCount = 0;
356
357 // Initialize the transaction mutex.
358 lscp_mutex_init(pClient->mutex);
359 lscp_cond_init(pClient->cond);
360
361 // Finally we've some success...
362 return pClient;
363 }
364
365
366 /**
367 * Wait for a client instance to terminate graciously.
368 *
369 * @param pClient Pointer to client instance structure.
370 */
371 lscp_status_t lscp_client_join ( lscp_client_t *pClient )
372 {
373 if (pClient == NULL)
374 return LSCP_FAILED;
375
376 #ifdef DEBUG
377 fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
378 #endif
379
380 // lscp_socket_agent_join(&(pClient->evt));
381 lscp_socket_agent_join(&(pClient->cmd));
382
383 return LSCP_OK;
384 }
385
386
387 /**
388 * Terminate and destroy a client instance.
389 *
390 * @param pClient Pointer to client instance structure.
391 *
392 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
393 */
394 lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
395 {
396 if (pClient == NULL)
397 return LSCP_FAILED;
398
399 #ifdef DEBUG
400 fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
401 #endif
402
403 // Lock this section up.
404 lscp_mutex_lock(pClient->mutex);
405
406 // Free up all cached members.
407 lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
408 lscp_channel_info_free(&(pClient->channel_info));
409 lscp_engine_info_free(&(pClient->engine_info));
410 lscp_server_info_free(&(pClient->server_info));
411 lscp_param_info_free(&(pClient->midi_port_param_info));
412 lscp_param_info_free(&(pClient->audio_channel_param_info));
413 lscp_device_port_info_free(&(pClient->midi_port_info));
414 lscp_device_port_info_free(&(pClient->audio_channel_info));
415 lscp_param_info_free(&(pClient->midi_param_info));
416 lscp_param_info_free(&(pClient->audio_param_info));
417 lscp_device_info_free(&(pClient->midi_device_info));
418 lscp_device_info_free(&(pClient->audio_device_info));
419 lscp_driver_info_free(&(pClient->midi_driver_info));
420 lscp_driver_info_free(&(pClient->audio_driver_info));
421 // Free available engine table.
422 lscp_szsplit_destroy(pClient->audio_drivers);
423 lscp_szsplit_destroy(pClient->midi_drivers);
424 lscp_isplit_destroy(pClient->audio_devices);
425 lscp_isplit_destroy(pClient->midi_devices);
426 lscp_szsplit_destroy(pClient->engines);
427 lscp_isplit_destroy(pClient->channels);
428 lscp_midi_instruments_destroy(pClient->midi_instruments);
429 lscp_isplit_destroy(pClient->midi_maps);
430 if (pClient->midi_map_name)
431 free(pClient->midi_map_name);
432 // Make them null.
433 pClient->audio_drivers = NULL;
434 pClient->midi_drivers = NULL;
435 pClient->audio_devices = NULL;
436 pClient->midi_devices = NULL;
437 pClient->engines = NULL;
438 pClient->channels = NULL;
439 pClient->midi_instruments = NULL;
440 pClient->midi_maps = NULL;
441 pClient->midi_map_name = NULL;
442 // Free result error stuff.
443 lscp_client_set_result(pClient, NULL, 0);
444 // Free stream usage stuff.
445 if (pClient->buffer_fill)
446 free(pClient->buffer_fill);
447 pClient->buffer_fill = NULL;
448 pClient->iStreamCount = 0;
449 pClient->iTimeout = 0;
450
451 // Free socket agents.
452 lscp_socket_agent_free(&(pClient->evt));
453 lscp_socket_agent_free(&(pClient->cmd));
454
455 // Last but not least, free good ol'transaction mutex.
456 lscp_mutex_unlock(pClient->mutex);
457 lscp_mutex_destroy(pClient->mutex);
458 lscp_cond_destroy(pClient->cond);
459
460 free(pClient);
461
462 return LSCP_OK;
463 }
464
465
466 /**
467 * Set the client transaction timeout interval.
468 *
469 * @param pClient Pointer to client instance structure.
470 * @param iTimeout Transaction timeout in milliseconds.
471 *
472 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
473 */
474 lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
475 {
476 if (pClient == NULL)
477 return LSCP_FAILED;
478 if (iTimeout < 0)
479 return LSCP_FAILED;
480
481 pClient->iTimeout = iTimeout;
482 return LSCP_OK;
483 }
484
485
486 /**
487 * Get the client transaction timeout interval.
488 *
489 * @param pClient Pointer to client instance structure.
490 *
491 * @returns The current timeout value milliseconds, -1 in case of failure.
492 */
493 int lscp_client_get_timeout ( lscp_client_t *pClient )
494 {
495 if (pClient == NULL)
496 return -1;
497
498 return pClient->iTimeout;
499 }
500
501
502 //-------------------------------------------------------------------------
503 // Client common protocol functions.
504
505 /**
506 * Submit a command query line string to the server. The query string
507 * must be cr/lf and null terminated. Besides the return code, the
508 * specific server response to the command request is made available
509 * by the @ref lscp_client_get_result and @ref lscp_client_get_errno
510 * function calls.
511 *
512 * @param pClient Pointer to client instance structure.
513 * @param pszQuery Command request line to be sent to server,
514 * must be cr/lf and null terminated.
515 *
516 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
517 */
518 lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
519 {
520 lscp_status_t ret;
521
522 if (pClient == NULL)
523 return LSCP_FAILED;
524
525 // Lock this section up.
526 lscp_mutex_lock(pClient->mutex);
527
528 // Just make the now guarded call.
529 ret = lscp_client_call(pClient, pszQuery, 0);
530
531 // Unlock this section down.
532 lscp_mutex_unlock(pClient->mutex);
533
534 return ret;
535 }
536
537 /**
538 * Get the last received result string. In case of error or warning,
539 * this is the text of the error or warning message issued.
540 *
541 * @param pClient Pointer to client instance structure.
542 *
543 * @returns A pointer to the literal null-terminated result string as
544 * of the last command request.
545 */
546 const char *lscp_client_get_result ( lscp_client_t *pClient )
547 {
548 if (pClient == NULL)
549 return NULL;
550
551 return pClient->pszResult;
552 }
553
554
555 /**
556 * Get the last error/warning number received.
557 *
558 * @param pClient Pointer to client instance structure.
559 *
560 * @returns The numerical value of the last error or warning
561 * response code received.
562 */
563 int lscp_client_get_errno ( lscp_client_t *pClient )
564 {
565 if (pClient == NULL)
566 return -1;
567
568 return pClient->iErrno;
569 }
570
571
572 //-------------------------------------------------------------------------
573 // Client registration protocol functions.
574
575 /**
576 * Register frontend for receiving event messages:
577 * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
578 * | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
579 * | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
580 * | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
581 * | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
582 * | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
583 * | MISCELLANEOUS
584 *
585 * @param pClient Pointer to client instance structure.
586 * @param events Bit-wise OR'ed event flags to subscribe.
587 *
588 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
589 */
590 lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
591 {
592 lscp_status_t ret = LSCP_FAILED;
593
594 if (pClient == NULL)
595 return LSCP_FAILED;
596
597 // Lock this section up.
598 lscp_mutex_lock(pClient->mutex);
599
600 // If applicable, start the alternate connection...
601 if (pClient->events == LSCP_EVENT_NONE)
602 ret = _lscp_client_evt_connect(pClient);
603
604 // Send the subscription commands.
605 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
606 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);
607 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
608 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
609 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
610 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
611 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
612 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
613 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
614 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
615 if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
616 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
617 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
618 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
619 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
620 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
621 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
622 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
623 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
624 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
625 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
626 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
627 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
628 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
629 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
630 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
631 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
632 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
633 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
634 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
635
636 // Unlock this section down.
637 lscp_mutex_unlock(pClient->mutex);
638
639 return ret;
640 }
641
642
643 /**
644 * Deregister frontend from receiving UDP event messages anymore:
645 * UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
646 * | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
647 * | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
648 * | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
649 * | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
650 * | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
651 * | MISCELLANEOUS
652 *
653 * @param pClient Pointer to client instance structure.
654 * @param events Bit-wise OR'ed event flags to unsubscribe.
655 *
656 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
657 */
658 lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
659 {
660 lscp_status_t ret = LSCP_OK;
661
662 if (pClient == NULL)
663 return LSCP_FAILED;
664
665 // Lock this section up.
666 lscp_mutex_lock(pClient->mutex);
667
668 // Send the unsubscription commands.
669 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
670 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT);
671 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
672 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
673 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
674 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
675 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
676 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
677 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
678 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
679 if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
680 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
681 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
682 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
683 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
684 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
685 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
686 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
687 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
688 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
689 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
690 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
691 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
692 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
693 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
694 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
695 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
696 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
697 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
698 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
699
700 // If necessary, close the alternate connection...
701 if (pClient->events == LSCP_EVENT_NONE)
702 lscp_socket_agent_free(&(pClient->evt));
703
704 // Unlock this section down.
705 lscp_mutex_unlock(pClient->mutex);
706
707 return ret;
708 }
709
710
711 /**
712 * Getting current subscribed events.
713 *
714 * @param pClient Pointer to client instance structure.
715 *
716 * @returns The current subscrived bit-wise OR'ed event flags.
717 */
718 lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )
719 {
720 if (pClient == NULL)
721 return LSCP_EVENT_NONE;
722
723 return pClient->events;
724 }
725
726
727 //-------------------------------------------------------------------------
728 // Client command protocol functions.
729
730 /**
731 * Loading an instrument:
732 * LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
733 *
734 * @param pClient Pointer to client instance structure.
735 * @param pszFileName Instrument file name.
736 * @param iInstrIndex Instrument index number.
737 * @param iSamplerChannel Sampler Channel.
738 *
739 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
740 */
741 lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
742 {
743 char szQuery[LSCP_BUFSIZ];
744
745 if (pszFileName == NULL || iSamplerChannel < 0)
746 return LSCP_FAILED;
747
748 sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
749 return lscp_client_query(pClient, szQuery);
750 }
751
752
753 /**
754 * Loading an instrument in the background (non modal):
755 * LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
756 *
757 * @param pClient Pointer to client instance structure.
758 * @param pszFileName Instrument file name.
759 * @param iInstrIndex Instrument index number.
760 * @param iSamplerChannel Sampler Channel.
761 *
762 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
763 */
764 lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
765 {
766 char szQuery[LSCP_BUFSIZ];
767
768 if (pszFileName == NULL || iSamplerChannel < 0)
769 return LSCP_FAILED;
770
771 sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
772 return lscp_client_query(pClient, szQuery);
773 }
774
775
776 /**
777 * Loading a sampler engine:
778 * LOAD ENGINE <engine-name> <sampler-channel>
779 *
780 * @param pClient Pointer to client instance structure.
781 * @param pszEngineName Engine name.
782 * @param iSamplerChannel Sampler channel number.
783 *
784 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
785 */
786 lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
787 {
788 char szQuery[LSCP_BUFSIZ];
789
790 if (pszEngineName == NULL || iSamplerChannel < 0)
791 return LSCP_FAILED;
792
793 sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);
794 return lscp_client_query(pClient, szQuery);
795 }
796
797
798 /**
799 * Current number of sampler channels:
800 * GET CHANNELS
801 *
802 * @param pClient Pointer to client instance structure.
803 *
804 * @returns The current total number of sampler channels on success,
805 * -1 otherwise.
806 */
807 int lscp_get_channels ( lscp_client_t *pClient )
808 {
809 int iChannels = -1;
810
811 if (pClient == NULL)
812 return -1;
813
814 // Lock this section up.
815 lscp_mutex_lock(pClient->mutex);
816
817 if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)
818 iChannels = atoi(lscp_client_get_result(pClient));
819
820 // Unlock this section doen.
821 lscp_mutex_unlock(pClient->mutex);
822
823 return iChannels;
824 }
825
826
827 /**
828 * List current sampler channels number identifiers:
829 * LIST CHANNELS
830 *
831 * @param pClient Pointer to client instance structure.
832 *
833 * @returns An array of the sampler channels identifiers as positive integers,
834 * terminated with -1 on success, NULL otherwise.
835 */
836 int *lscp_list_channels ( lscp_client_t *pClient )
837 {
838 const char *pszSeps = ",";
839
840 if (pClient == NULL)
841 return NULL;
842
843 // Lock this section up.
844 lscp_mutex_lock(pClient->mutex);
845
846 if (pClient->channels) {
847 lscp_isplit_destroy(pClient->channels);
848 pClient->channels = NULL;
849 }
850
851 if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)
852 pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
853
854 // Unlock this section down.
855 lscp_mutex_unlock(pClient->mutex);
856
857 return pClient->channels;
858 }
859
860
861 /**
862 * Adding a new sampler channel:
863 * ADD CHANNEL
864 *
865 * @param pClient Pointer to client instance structure.
866 *
867 * @returns The new sampler channel number identifier,
868 * or -1 in case of failure.
869 */
870 int lscp_add_channel ( lscp_client_t *pClient )
871 {
872 int iSamplerChannel = -1;
873
874 if (pClient == NULL)
875 return -1;
876
877 // Lock this section up.
878 lscp_mutex_lock(pClient->mutex);
879
880 if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)
881 iSamplerChannel = atoi(lscp_client_get_result(pClient));
882
883 // Unlock this section down.
884 lscp_mutex_unlock(pClient->mutex);
885
886 return iSamplerChannel;
887 }
888
889
890 /**
891 * Removing a sampler channel:
892 * REMOVE CHANNEL <sampler-channel>
893 *
894 * @param pClient Pointer to client instance structure.
895 * @param iSamplerChannel Sampler channel number.
896 *
897 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
898 */
899 lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
900 {
901 char szQuery[LSCP_BUFSIZ];
902
903 if (iSamplerChannel < 0)
904 return LSCP_FAILED;
905
906 sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
907 return lscp_client_query(pClient, szQuery);
908 }
909
910
911 /**
912 * Getting all available engines count:
913 * GET AVAILABLE_ENGINES
914 *
915 * @param pClient Pointer to client instance structure.
916 *
917 * @returns The current total number of sampler engines on success,
918 * -1 otherwise.
919 */
920 int lscp_get_available_engines ( lscp_client_t *pClient )
921 {
922 int iAvailableEngines = -1;
923
924 if (pClient == NULL)
925 return -1;
926
927 // Lock this section up.
928 lscp_mutex_lock(pClient->mutex);
929
930 if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
931 iAvailableEngines = atoi(lscp_client_get_result(pClient));
932
933 // Unlock this section down.
934 lscp_mutex_unlock(pClient->mutex);
935
936 return iAvailableEngines;
937 }
938
939
940 /**
941 * Getting all available engines:
942 * LIST AVAILABLE_ENGINES
943 *
944 * @param pClient Pointer to client instance structure.
945 *
946 * @returns A NULL terminated array of engine name strings,
947 * or NULL in case of failure.
948 */
949 const char **lscp_list_available_engines ( lscp_client_t *pClient )
950 {
951 const char *pszSeps = ",";
952
953 if (pClient == NULL)
954 return NULL;
955
956 // Lock this section up.
957 lscp_mutex_lock(pClient->mutex);
958
959 if (pClient->engines) {
960 lscp_szsplit_destroy(pClient->engines);
961 pClient->engines = NULL;
962 }
963
964 if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
965 pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
966
967 // Unlock this section down.
968 lscp_mutex_unlock(pClient->mutex);
969
970 return (const char **) pClient->engines;
971 }
972
973
974 /**
975 * Getting information about an engine.
976 * GET ENGINE INFO <engine-name>
977 *
978 * @param pClient Pointer to client instance structure.
979 * @param pszEngineName Engine name.
980 *
981 * @returns A pointer to a @ref lscp_engine_info_t structure, with all the
982 * information of the given sampler engine, or NULL in case of failure.
983 */
984 lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )
985 {
986 lscp_engine_info_t *pEngineInfo;
987 char szQuery[LSCP_BUFSIZ];
988 const char *pszResult;
989 const char *pszSeps = ":";
990 const char *pszCrlf = "\r\n";
991 char *pszToken;
992 char *pch;
993
994 if (pClient == NULL)
995 return NULL;
996 if (pszEngineName == NULL)
997 return NULL;
998
999 // Lock this section up.
1000 lscp_mutex_lock(pClient->mutex);
1001
1002 pEngineInfo = &(pClient->engine_info);
1003 lscp_engine_info_reset(pEngineInfo);
1004
1005 sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
1006 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1007 pszResult = lscp_client_get_result(pClient);
1008 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1009 while (pszToken) {
1010 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1011 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1012 if (pszToken)
1013 lscp_unquote_dup(&(pEngineInfo->description), &pszToken);
1014 }
1015 else if (strcasecmp(pszToken, "VERSION") == 0) {
1016 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1017 if (pszToken)
1018 lscp_unquote_dup(&(pEngineInfo->version), &pszToken);
1019 }
1020 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1021 }
1022 }
1023 else pEngineInfo = NULL;
1024
1025 // Unlock this section down.
1026 lscp_mutex_unlock(pClient->mutex);
1027
1028 return pEngineInfo;
1029 }
1030
1031
1032 /**
1033 * Getting sampler channel informations:
1034 * GET CHANNEL INFO <sampler-channel>
1035 *
1036 * @param pClient Pointer to client instance structure.
1037 * @param iSamplerChannel Sampler channel number.
1038 *
1039 * @returns A pointer to a @ref lscp_channel_info_t structure, with all the
1040 * information of the given sampler channel, or NULL in case of failure.
1041 */
1042 lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
1043 {
1044 lscp_channel_info_t *pChannelInfo;
1045 char szQuery[LSCP_BUFSIZ];
1046 const char *pszResult;
1047 const char *pszSeps = ":";
1048 const char *pszCrlf = "\r\n";
1049 char *pszToken;
1050 char *pch;
1051
1052 if (pClient == NULL)
1053 return NULL;
1054 if (iSamplerChannel < 0)
1055 return NULL;
1056
1057 // Lock this section up.
1058 lscp_mutex_lock(pClient->mutex);
1059
1060 pChannelInfo = &(pClient->channel_info);
1061 lscp_channel_info_reset(pChannelInfo);
1062
1063 sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1064 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1065 pszResult = lscp_client_get_result(pClient);
1066 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1067 while (pszToken) {
1068 if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
1069 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1070 if (pszToken)
1071 lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);
1072 }
1073 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
1074 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1075 if (pszToken)
1076 pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
1077 }
1078 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
1079 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1080 if (pszToken)
1081 pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
1082 }
1083 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
1084 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1085 if (pszToken) {
1086 if (pChannelInfo->audio_routing)
1087 lscp_szsplit_destroy(pChannelInfo->audio_routing);
1088 pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");
1089 }
1090 }
1091 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
1092 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1093 if (pszToken)
1094 lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);
1095 }
1096 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
1097 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1098 if (pszToken)
1099 pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
1100 }
1101 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
1102 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1103 if (pszToken)
1104 lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);
1105 }
1106 else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
1107 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1108 if (pszToken)
1109 pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
1110 }
1111 else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
1112 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1113 if (pszToken)
1114 pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
1115 }
1116 else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
1117 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1118 if (pszToken)
1119 pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
1120 }
1121 else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
1122 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1123 if (pszToken) {
1124 pszToken = lscp_ltrim(pszToken);
1125 if (strcasecmp(pszToken, "ALL") == 0)
1126 pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;
1127 else
1128 pChannelInfo->midi_channel = atoi(pszToken);
1129 }
1130 }
1131 else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1132 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1133 if (pszToken) {
1134 pszToken = lscp_ltrim(pszToken);
1135 if (strcasecmp(pszToken, "NONE") == 0)
1136 pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1137 else
1138 if (strcasecmp(pszToken, "DEFAULT") == 0)
1139 pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1140 else
1141 pChannelInfo->midi_map = atoi(pszToken);
1142 }
1143 }
1144 else if (strcasecmp(pszToken, "VOLUME") == 0) {
1145 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1146 if (pszToken)
1147 pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));
1148 }
1149 else if (strcasecmp(pszToken, "MUTE") == 0) {
1150 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1151 if (pszToken)
1152 pChannelInfo->mute = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1153 }
1154 else if (strcasecmp(pszToken, "SOLO") == 0) {
1155 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1156 if (pszToken)
1157 pChannelInfo->solo = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1158 }
1159 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1160 }
1161 }
1162 else pChannelInfo = NULL;
1163
1164 // Unlock this section up.
1165 lscp_mutex_unlock(pClient->mutex);
1166
1167 return pChannelInfo;
1168 }
1169
1170
1171 /**
1172 * Current number of active voices:
1173 * GET CHANNEL VOICE_COUNT <sampler-channel>
1174 *
1175 * @param pClient Pointer to client instance structure.
1176 * @param iSamplerChannel Sampler channel number.
1177 *
1178 * @returns The number of voices currently active, -1 in case of failure.
1179 */
1180 int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
1181 {
1182 char szQuery[LSCP_BUFSIZ];
1183 int iVoiceCount = -1;
1184
1185 if (pClient == NULL)
1186 return -1;
1187 if (iSamplerChannel < 0)
1188 return -1;
1189
1190 // Lock this section up.
1191 lscp_mutex_lock(pClient->mutex);
1192
1193 sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
1194 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1195 iVoiceCount = atoi(lscp_client_get_result(pClient));
1196
1197 // Unlock this section down.
1198 lscp_mutex_unlock(pClient->mutex);
1199
1200 return iVoiceCount;
1201 }
1202
1203
1204 /**
1205 * Current number of active disk streams:
1206 * GET CHANNEL STREAM_COUNT <sampler-channel>
1207 *
1208 * @param pClient Pointer to client instance structure.
1209 * @param iSamplerChannel Sampler channel number.
1210 *
1211 * @returns The number of active disk streams on success, -1 otherwise.
1212 */
1213 int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
1214 {
1215 char szQuery[LSCP_BUFSIZ];
1216 int iStreamCount = -1;
1217
1218 if (pClient == NULL)
1219 return -1;
1220 if (iSamplerChannel < 0)
1221 return -1;
1222
1223 // Lock this section up.
1224 lscp_mutex_lock(pClient->mutex);
1225
1226 sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1227 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1228 iStreamCount = atoi(lscp_client_get_result(pClient));
1229
1230 // Unlock this section down.
1231 lscp_mutex_unlock(pClient->mutex);
1232
1233 return iStreamCount;
1234 }
1235
1236
1237 /**
1238 * Current least usage of active disk streams.
1239 *
1240 * @param pClient Pointer to client instance structure.
1241 * @param iSamplerChannel Sampler channel number.
1242 *
1243 * @returns The usage percentage of the least filled active disk stream
1244 * on success, -1 otherwise.
1245 */
1246 int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )
1247 {
1248 char szQuery[LSCP_BUFSIZ];
1249 int iStreamUsage = -1;
1250 const char *pszResult;
1251 const char *pszSeps = "[]%,";
1252 char *pszToken;
1253 char *pch;
1254 int iStream;
1255 int iPercent;
1256
1257 if (pClient == NULL)
1258 return -1;
1259 if (iSamplerChannel < 0)
1260 return -1;
1261
1262 // Lock this section up.
1263 lscp_mutex_lock(pClient->mutex);
1264
1265 iStream = 0;
1266 sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);
1267 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1268 pszResult = lscp_client_get_result(pClient);
1269 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1270 while (pszToken) {
1271 if (*pszToken) {
1272 // Skip stream id.
1273 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1274 if (pszToken == NULL)
1275 break;
1276 // Get least buffer fill percentage.
1277 iPercent = atol(pszToken);
1278 if (iStreamUsage > iPercent || iStream == 0)
1279 iStreamUsage = iPercent;
1280 iStream++;
1281 }
1282 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1283 }
1284 }
1285
1286 // Unlock this section down.
1287 lscp_mutex_unlock(pClient->mutex);
1288
1289 return iStreamUsage;
1290 }
1291
1292
1293 /**
1294 * Current fill state of disk stream buffers:
1295 * GET CHANNEL BUFFER_FILL {BYTES|PERCENTAGE} <sampler-channel>
1296 *
1297 * @param pClient Pointer to client instance structure.
1298 * @param usage_type Usage type to be returned, either
1299 * @ref LSCP_USAGE_BYTES, or
1300 * @ref LSCP_USAGE_PERCENTAGE.
1301 * @param iSamplerChannel Sampler channel number.
1302 *
1303 * @returns A pointer to a @ref lscp_buffer_fill_t structure, with the
1304 * information of the current disk stream buffer fill usage, for the given
1305 * sampler channel, or NULL in case of failure.
1306 */
1307 lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )
1308 {
1309 lscp_buffer_fill_t *pBufferFill;
1310 char szQuery[LSCP_BUFSIZ];
1311 int iStreamCount;
1312 const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1313 const char *pszResult;
1314 const char *pszSeps = "[]%,";
1315 char *pszToken;
1316 char *pch;
1317 int iStream;
1318
1319 // Retrieve a channel stream estimation.
1320 iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1321 if (iStreamCount < 0)
1322 return NULL;
1323
1324 // Lock this section up.
1325 lscp_mutex_lock(pClient->mutex);
1326
1327 // Check if we need to reallocate the stream usage array.
1328 if (pClient->iStreamCount != iStreamCount) {
1329 if (pClient->buffer_fill)
1330 free(pClient->buffer_fill);
1331 if (iStreamCount > 0)
1332 pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1333 else
1334 pClient->buffer_fill = NULL;
1335 pClient->iStreamCount = iStreamCount;
1336 }
1337
1338 // Get buffer fill usage...
1339 pBufferFill = pClient->buffer_fill;
1340 if (pBufferFill && iStreamCount > 0) {
1341 iStream = 0;
1342 pBufferFill = pClient->buffer_fill;
1343 sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1344 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1345 pszResult = lscp_client_get_result(pClient);
1346 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1347 while (pszToken && iStream < pClient->iStreamCount) {
1348 if (*pszToken) {
1349 pBufferFill[iStream].stream_id = atol(pszToken);
1350 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1351 if (pszToken == NULL)
1352 break;
1353 pBufferFill[iStream].stream_usage = atol(pszToken);
1354 iStream++;
1355 }
1356 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1357 }
1358 } // Reset the usage, whatever it was before.
1359 else while (iStream < pClient->iStreamCount)
1360 pBufferFill[iStream++].stream_usage = 0;
1361 }
1362
1363 // Unlock this section down.
1364 lscp_mutex_unlock(pClient->mutex);
1365
1366 return pBufferFill;
1367 }
1368
1369
1370 /**
1371 * Setting audio output type:
1372 * SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
1373 *
1374 * @param pClient Pointer to client instance structure.
1375 * @param iSamplerChannel Sampler channel number.
1376 * @param pszAudioDriver Audio output driver type (e.g. "ALSA" or "JACK").
1377 *
1378 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1379 */
1380 lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )
1381 {
1382 char szQuery[LSCP_BUFSIZ];
1383
1384 if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1385 return LSCP_FAILED;
1386
1387 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);
1388 return lscp_client_query(pClient, szQuery);
1389 }
1390
1391
1392 /**
1393 * Setting audio output device:
1394 * SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1395 *
1396 * @param pClient Pointer to client instance structure.
1397 * @param iSamplerChannel Sampler channel number.
1398 * @param iAudioDevice Audio output device number identifier.
1399 *
1400 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1401 */
1402 lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )
1403 {
1404 char szQuery[LSCP_BUFSIZ];
1405
1406 if (iSamplerChannel < 0 || iAudioDevice < 0)
1407 return LSCP_FAILED;
1408
1409 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);
1410 return lscp_client_query(pClient, szQuery);
1411 }
1412
1413
1414 /**
1415 * Setting audio output channel:
1416 * SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-output-chan> <audio-input-chan>
1417 *
1418 * @param pClient Pointer to client instance structure.
1419 * @param iSamplerChannel Sampler channel number.
1420 * @param iAudioOut Audio output device channel to be routed from.
1421 * @param iAudioIn Audio output device channel to be routed into.
1422 *
1423 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1424 */
1425 lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )
1426 {
1427 char szQuery[LSCP_BUFSIZ];
1428
1429 if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1430 return LSCP_FAILED;
1431
1432 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);
1433 return lscp_client_query(pClient, szQuery);
1434 }
1435
1436
1437 /**
1438 * Setting MIDI input type:
1439 * SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
1440 *
1441 * @param pClient Pointer to client instance structure.
1442 * @param iSamplerChannel Sampler channel number.
1443 * @param pszMidiDriver MIDI input driver type (e.g. "ALSA").
1444 *
1445 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1446 */
1447 lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )
1448 {
1449 char szQuery[LSCP_BUFSIZ];
1450
1451 if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1452 return LSCP_FAILED;
1453
1454 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);
1455 return lscp_client_query(pClient, szQuery);
1456 }
1457
1458
1459 /**
1460 * Setting MIDI input device:
1461 * SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1462 *
1463 * @param pClient Pointer to client instance structure.
1464 * @param iSamplerChannel Sampler channel number.
1465 * @param iMidiDevice MIDI input device number identifier.
1466 *
1467 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1468 */
1469 lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )
1470 {
1471 char szQuery[LSCP_BUFSIZ];
1472
1473 if (iSamplerChannel < 0 || iMidiDevice < 0)
1474 return LSCP_FAILED;
1475
1476 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);
1477 return lscp_client_query(pClient, szQuery);
1478 }
1479
1480
1481 /**
1482 * Setting MIDI input port:
1483 * SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
1484 *
1485 * @param pClient Pointer to client instance structure.
1486 * @param iSamplerChannel Sampler channel number.
1487 * @param iMidiPort MIDI input driver virtual port number.
1488 *
1489 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1490 */
1491 lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )
1492 {
1493 char szQuery[LSCP_BUFSIZ];
1494
1495 if (iSamplerChannel < 0 || iMidiPort < 0)
1496 return LSCP_FAILED;
1497
1498 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);
1499 return lscp_client_query(pClient, szQuery);
1500 }
1501
1502
1503 /**
1504 * Setting MIDI input channel:
1505 * SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
1506 *
1507 * @param pClient Pointer to client instance structure.
1508 * @param iSamplerChannel Sampler channel number.
1509 * @param iMidiChannel MIDI channel address number to listen (0-15) or
1510 * @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1511 *
1512 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1513 */
1514 lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )
1515 {
1516 char szQuery[LSCP_BUFSIZ];
1517
1518 if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1519 return LSCP_FAILED;
1520
1521 if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1522 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);
1523 else
1524 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);
1525 return lscp_client_query(pClient, szQuery);
1526 }
1527
1528
1529 /**
1530 * Setting MIDI instrument map:
1531 * SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1532 *
1533 * @param pClient Pointer to client instance structure.
1534 * @param iSamplerChannel Sampler channel number.
1535 * @param iMidiMap MIDI instrument map number, or either
1536 * @ref LSCP_MIDI_MAP_NONE or
1537 * @ref LSCP_MIDI_MAP_DEFAULT .
1538 *
1539 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1540 */
1541 lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient, int iSamplerChannel, int iMidiMap )
1542 {
1543 char szQuery[LSCP_BUFSIZ];
1544
1545 if (iSamplerChannel < 0)
1546 return LSCP_FAILED;
1547
1548 sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1549 if (iMidiMap == LSCP_MIDI_MAP_NONE)
1550 strcat(szQuery , "NONE");
1551 else
1552 if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1553 strcat(szQuery , "DEFAULT");
1554 else
1555 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1556
1557 strcat(szQuery, "\r\n");
1558
1559 return lscp_client_query(pClient, szQuery);
1560 }
1561
1562
1563 /**
1564 * Setting channel volume:
1565 * SET CHANNEL VOLUME <sampler-channel> <volume>
1566 *
1567 * @param pClient Pointer to client instance structure.
1568 * @param iSamplerChannel Sampler channel number.
1569 * @param fVolume Sampler channel volume as a positive floating point
1570 * number, where a value less than 1.0 for attenuation,
1571 * and greater than 1.0 for amplification.
1572 *
1573 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1574 */
1575 lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )
1576 {
1577 char szQuery[LSCP_BUFSIZ];
1578
1579 if (iSamplerChannel < 0 || fVolume < 0.0)
1580 return LSCP_FAILED;
1581
1582 sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);
1583 return lscp_client_query(pClient, szQuery);
1584 }
1585
1586
1587 /**
1588 * Muting a sampler channel:
1589 * SET CHANNEL MUTE <sampler-channel> <mute>
1590 *
1591 * @param pClient Pointer to client instance structure.
1592 * @param iSamplerChannel Sampler channel number.
1593 * @param iMute Sampler channel mute state as a boolean value,
1594 * either 1 (one) to mute the channel or 0 (zero)
1595 * to unmute the channel.
1596 *
1597 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1598 */
1599 lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )
1600 {
1601 char szQuery[LSCP_BUFSIZ];
1602
1603 if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1604 return LSCP_FAILED;
1605
1606 sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);
1607 return lscp_client_query(pClient, szQuery);
1608 }
1609
1610
1611 /**
1612 * Soloing a sampler channel:
1613 * SET CHANNEL SOLO <sampler-channel> <solo>
1614 *
1615 * @param pClient Pointer to client instance structure.
1616 * @param iSamplerChannel Sampler channel number.
1617 * @param iSolo Sampler channel solo state as a boolean value,
1618 * either 1 (one) to solo the channel or 0 (zero)
1619 * to unsolo the channel.
1620 *
1621 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1622 */
1623 lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )
1624 {
1625 char szQuery[LSCP_BUFSIZ];
1626
1627 if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1628 return LSCP_FAILED;
1629
1630 sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);
1631 return lscp_client_query(pClient, szQuery);
1632 }
1633
1634
1635 /**
1636 * Resetting a sampler channel:
1637 * RESET CHANNEL <sampler-channel>
1638 *
1639 * @param pClient Pointer to client instance structure.
1640 * @param iSamplerChannel Sampler channel number.
1641 *
1642 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1643 */
1644 lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1645 {
1646 char szQuery[LSCP_BUFSIZ];
1647
1648 if (iSamplerChannel < 0)
1649 return LSCP_FAILED;
1650
1651 sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1652 return lscp_client_query(pClient, szQuery);
1653 }
1654
1655
1656 /**
1657 * Resetting the sampler:
1658 * RESET
1659 *
1660 * @param pClient Pointer to client instance structure.
1661 *
1662 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1663 */
1664 lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1665 {
1666 // Do actual whole sampler reset...
1667 return lscp_client_query(pClient, "RESET\r\n");
1668 }
1669
1670
1671 /**
1672 * Getting information about the server.
1673 * GET SERVER INFO
1674 *
1675 * @param pClient Pointer to client instance structure.
1676 *
1677 * @returns A pointer to a @ref lscp_server_info_t structure, with all the
1678 * information of the current connected server, or NULL in case of failure.
1679 */
1680 lscp_server_info_t *lscp_get_server_info ( lscp_client_t *pClient )
1681 {
1682 lscp_server_info_t *pServerInfo;
1683 const char *pszResult;
1684 const char *pszSeps = ":";
1685 const char *pszCrlf = "\r\n";
1686 char *pszToken;
1687 char *pch;
1688
1689 if (pClient == NULL)
1690 return NULL;
1691
1692 // Lock this section up.
1693 lscp_mutex_lock(pClient->mutex);
1694
1695 pServerInfo = &(pClient->server_info);
1696 lscp_server_info_reset(pServerInfo);
1697
1698 if (lscp_client_call(pClient, "GET SERVER INFO\r\n", 1) == LSCP_OK) {
1699 pszResult = lscp_client_get_result(pClient);
1700 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1701 while (pszToken) {
1702 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1703 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1704 if (pszToken)
1705 lscp_unquote_dup(&(pServerInfo->description), &pszToken);
1706 }
1707 else if (strcasecmp(pszToken, "VERSION") == 0) {
1708 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1709 if (pszToken)
1710 lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1711 }
1712 else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1713 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1714 if (pszToken)
1715 lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1716 }
1717 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1718 }
1719 }
1720 else pServerInfo = NULL;
1721
1722 // Unlock this section down.
1723 lscp_mutex_unlock(pClient->mutex);
1724
1725 return pServerInfo;
1726 }
1727
1728
1729 /**
1730 * Current total number of active voices:
1731 * GET TOTAL_VOICE_COUNT
1732 *
1733 * @param pClient Pointer to client instance structure.
1734 *
1735 * @returns The total number of voices currently active,
1736 * -1 in case of failure.
1737 */
1738 int lscp_get_total_voice_count ( lscp_client_t *pClient )
1739 {
1740 int iVoiceCount = -1;
1741
1742 if (pClient == NULL)
1743 return -1;
1744
1745 // Lock this section up.
1746 lscp_mutex_lock(pClient->mutex);
1747
1748 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT\r\n", 0) == LSCP_OK)
1749 iVoiceCount = atoi(lscp_client_get_result(pClient));
1750
1751 // Unlock this section down.
1752 lscp_mutex_unlock(pClient->mutex);
1753
1754 return iVoiceCount;
1755 }
1756
1757
1758 /**
1759 * Maximum amount of active voices:
1760 * GET TOTAL_VOICE_COUNT_MAX
1761 *
1762 * @param pClient Pointer to client instance structure.
1763 *
1764 * @returns The maximum amount of voices currently active,
1765 * -1 in case of failure.
1766 */
1767 int lscp_get_total_voice_count_max ( lscp_client_t *pClient )
1768 {
1769 int iVoiceCount = -1;
1770
1771 if (pClient == NULL)
1772 return -1;
1773
1774 // Lock this section up.
1775 lscp_mutex_lock(pClient->mutex);
1776
1777 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT_MAX\r\n", 0) == LSCP_OK)
1778 iVoiceCount = atoi(lscp_client_get_result(pClient));
1779
1780 // Unlock this section down.
1781 lscp_mutex_unlock(pClient->mutex);
1782
1783 return iVoiceCount;
1784 }
1785
1786
1787 /**
1788 * Create a new MIDI instrument map:
1789 * ADD MIDI_INSTRUMENT_MAP [<name>]
1790 *
1791 * @param pClient Pointer to client instance structure.
1792 * @param pszMapName MIDI instrument map name (optional)
1793 *
1794 * @returns The new MIDI instrument map number identifier,
1795 * or -1 in case of failure.
1796 */
1797 int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
1798 {
1799 int iMidiMap = -1;
1800 char szQuery[LSCP_BUFSIZ];
1801
1802 if (pClient == NULL)
1803 return -1;
1804
1805 // Lock this section up.
1806 lscp_mutex_lock(pClient->mutex);
1807
1808 strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
1809
1810 if (pszMapName)
1811 sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
1812
1813 strcat(szQuery, "\r\n");
1814
1815 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1816 iMidiMap = atoi(lscp_client_get_result(pClient));
1817
1818 // Unlock this section down.
1819 lscp_mutex_unlock(pClient->mutex);
1820
1821 return iMidiMap;
1822 }
1823
1824
1825 /**
1826 * Delete one particular or all MIDI instrument maps:
1827 * REMOVE MIDI_INSTRUMENT_MAP <midi-map>
1828 *
1829 * @param pClient Pointer to client instance structure.
1830 * @param iMidiMap MIDI instrument map number.
1831 *
1832 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1833 */
1834 lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
1835 {
1836 char szQuery[LSCP_BUFSIZ];
1837
1838 if (iMidiMap < 0)
1839 return LSCP_FAILED;
1840
1841 sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
1842
1843 return lscp_client_query(pClient, szQuery);
1844 }
1845
1846
1847 /**
1848 * Get amount of existing MIDI instrument maps:
1849 * GET MIDI_INSTRUMENT_MAPS
1850 *
1851 * @param pClient Pointer to client instance structure.
1852 *
1853 * @returns The current total number of MIDI instrument maps
1854 * on success, -1 otherwise.
1855 */
1856 int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
1857 {
1858 int iMidiMaps = -1;
1859
1860 if (pClient == NULL)
1861 return -1;
1862
1863 // Lock this section up.
1864 lscp_mutex_lock(pClient->mutex);
1865
1866 if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
1867 iMidiMaps = atoi(lscp_client_get_result(pClient));
1868
1869 // Unlock this section doen.
1870 lscp_mutex_unlock(pClient->mutex);
1871
1872 return iMidiMaps;
1873 }
1874
1875
1876 /**
1877 * Getting all created MIDI instrument maps:
1878 * LIST MIDI_INSTRUMENT_MAPS
1879 *
1880 * @param pClient Pointer to client instance structure.
1881 *
1882 * @returns An array of the MIDI instrument map identifiers as positive
1883 * integers, terminated with -1 on success, NULL otherwise.
1884 */
1885 int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
1886 {
1887 const char *pszSeps = ",";
1888
1889 if (pClient == NULL)
1890 return NULL;
1891
1892 // Lock this section up.
1893 lscp_mutex_lock(pClient->mutex);
1894
1895 if (pClient->midi_maps) {
1896 lscp_isplit_destroy(pClient->midi_maps);
1897 pClient->midi_maps = NULL;
1898 }
1899
1900 if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
1901 pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
1902
1903 // Unlock this section down.
1904 lscp_mutex_unlock(pClient->mutex);
1905
1906 return pClient->midi_maps;
1907 }
1908
1909
1910 /**
1911 * Getting a MIDI instrument map name:
1912 * GET MIDI_INSTRUMENT_MAP INFO <midi-map>
1913 *
1914 * @param pClient Pointer to client instance structure.
1915 * @param iMidiMap MIDI instrument map number.
1916 *
1917 * @returns The MIDI instrument map name on success, NULL on failure.
1918 */
1919 const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
1920 {
1921 char szQuery[LSCP_BUFSIZ];
1922 const char *pszResult;
1923 const char *pszSeps = ":";
1924 const char *pszCrlf = "\r\n";
1925 char *pszToken;
1926 char *pch;
1927
1928 if (pClient == NULL)
1929 return NULL;
1930 if (iMidiMap < 0)
1931 return NULL;
1932
1933 // Lock this section up.
1934 lscp_mutex_lock(pClient->mutex);
1935
1936 if (pClient->midi_map_name) {
1937 free(pClient->midi_map_name);
1938 pClient->midi_map_name = NULL;
1939 }
1940
1941 sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
1942 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1943 pszResult = lscp_client_get_result(pClient);
1944 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1945 while (pszToken) {
1946 if (strcasecmp(pszToken, "NAME") == 0) {
1947 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1948 if (pszToken)
1949 lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
1950 }
1951 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1952 }
1953 }
1954
1955 // Unlock this section down.
1956 lscp_mutex_unlock(pClient->mutex);
1957
1958 return pClient->midi_map_name;
1959 }
1960
1961
1962 /**
1963 * Renaming a MIDI instrument map:
1964 * SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
1965 *
1966 * @param pClient Pointer to client instance structure.
1967 * @param iMidiMap MIDI instrument map number.
1968 * @param pszMapName MIDI instrument map name.
1969 *
1970 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1971 */
1972 lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
1973 {
1974 char szQuery[LSCP_BUFSIZ];
1975
1976 if (iMidiMap < 0)
1977 return LSCP_FAILED;
1978 if (pszMapName == NULL)
1979 return LSCP_FAILED;
1980
1981 sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
1982 iMidiMap, pszMapName);
1983
1984 return lscp_client_query(pClient, szQuery);
1985 }
1986
1987
1988 /**
1989 * Create or replace a MIDI instrumnet map entry:
1990 * MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
1991 * <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
1992 *
1993 * @param pClient Pointer to client instance structure.
1994 * @param pMidiInstr MIDI instrument bank and program parameter key.
1995 * @param pszEngineName Engine name.
1996 * @param pszFileName Instrument file name.
1997 * @param iInstrIndex Instrument index number.
1998 * @param fVolume Reflects the master volume of the instrument as
1999 * a positive floating point number, where a value
2000 * less than 1.0 for attenuation, and greater than
2001 * 1.0 for amplification.
2002 * @param load_mode Instrument load life-time strategy, either
2003 * @ref LSCP_LOAD_DEFAULT, or
2004 * @ref LSCP_LOAD_ON_DEMAND, or
2005 * @ref LSCP_LOAD_ON_DEMAND_HOLD, or
2006 * @ref LSCP_LOAD_PERSISTENT.
2007 * @param pszName Instrument custom name for the map entry (optional).
2008 *
2009 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2010 */
2011 lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )
2012 {
2013 char szQuery[LSCP_BUFSIZ];
2014
2015 if (pMidiInstr->map < 0)
2016 return LSCP_FAILED;
2017 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2018 return LSCP_FAILED;
2019 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2020 return LSCP_FAILED;
2021 if (pszEngineName == NULL || pszFileName == NULL)
2022 return LSCP_FAILED;
2023
2024 if (fVolume < 0.0f)
2025 fVolume = 1.0f;
2026
2027 sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2028 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2029 pszEngineName, pszFileName, iInstrIndex, fVolume);
2030
2031 switch (load_mode) {
2032 case LSCP_LOAD_PERSISTENT:
2033 strcat(szQuery, " PERSISTENT");
2034 break;
2035 case LSCP_LOAD_ON_DEMAND_HOLD:
2036 strcat(szQuery, " ON_DEMAND_HOLD");
2037 break;
2038 case LSCP_LOAD_ON_DEMAND:
2039 strcat(szQuery, " ON_DEMAND");
2040 break;
2041 case LSCP_LOAD_DEFAULT:
2042 default:
2043 break;
2044 }
2045
2046 if (pszName)
2047 sprintf(szQuery + strlen(szQuery), " '%s'", pszName);
2048
2049 strcat(szQuery, "\r\n");
2050
2051 return lscp_client_query(pClient, szQuery);
2052 }
2053
2054
2055 /**
2056 * Remove an entry from the MIDI instrument map:
2057 * UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2058 *
2059 * @param pClient Pointer to client instance structure.
2060 * @param pMidiInstr MIDI instrument bank and program parameter key.
2061 *
2062 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2063 */
2064 lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )
2065 {
2066 char szQuery[LSCP_BUFSIZ];
2067
2068 if (pMidiInstr->map < 0)
2069 return LSCP_FAILED;
2070 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2071 return LSCP_FAILED;
2072 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2073 return LSCP_FAILED;
2074
2075 sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2076 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2077
2078 return lscp_client_query(pClient, szQuery);
2079 }
2080
2081
2082 /**
2083 * Get the total count of MIDI instrument map entries:
2084 * GET MIDI_INSTRUMENTS ALL|<midi-map>
2085 *
2086 * @param pClient Pointer to client instance structure.
2087 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2088 *
2089 * @returns The current total number of MIDI instrument map entries
2090 * on success, -1 otherwise.
2091 */
2092 int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2093 {
2094 int iInstruments = -1;
2095 char szQuery[LSCP_BUFSIZ];
2096
2097 if (pClient == NULL)
2098 return -1;
2099
2100 // Lock this section up.
2101 lscp_mutex_lock(pClient->mutex);
2102
2103 strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
2104
2105 if (iMidiMap < 0)
2106 strcat(szQuery, "ALL");
2107 else
2108 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2109
2110 strcat(szQuery, "\r\n");
2111
2112 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2113 iInstruments = atoi(lscp_client_get_result(pClient));
2114
2115 // Unlock this section down.
2116 lscp_mutex_unlock(pClient->mutex);
2117
2118 return iInstruments;
2119 }
2120
2121
2122 /**
2123 * Getting indeces of all MIDI instrument map entries:
2124 * LIST MIDI_INSTRUMENTS ALL|<midi-map>
2125 *
2126 * @param pClient Pointer to client instance structure.
2127 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2128 *
2129 * @returns An array of @ref lscp_midi_instrument_t, terminated with the
2130 * {-1,-1,-1} triplet, NULL otherwise.
2131 */
2132 lscp_midi_instrument_t *lscp_list_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2133 {
2134 char szQuery[LSCP_BUFSIZ];
2135
2136 if (pClient == NULL)
2137 return NULL;
2138
2139 // Lock this section up.
2140 lscp_mutex_lock(pClient->mutex);
2141
2142 if (pClient->midi_instruments) {
2143 lscp_midi_instruments_destroy(pClient->midi_instruments);
2144 pClient->midi_instruments = NULL;
2145 }
2146
2147 strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
2148
2149 if (iMidiMap < 0)
2150 strcat(szQuery, "ALL");
2151 else
2152 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2153
2154 strcat(szQuery, "\r\n");
2155
2156 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2157 pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));
2158
2159 // Unlock this section down.
2160 lscp_mutex_unlock(pClient->mutex);
2161
2162 return pClient->midi_instruments;
2163 }
2164
2165
2166 /**
2167 * Getting information about a MIDI instrument map entry:
2168 * GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2169 *
2170 * @param pClient Pointer to client instance structure.
2171 * @param pMidiInstr MIDI instrument bank and program parameter key.
2172 *
2173 * @returns A pointer to a @ref lscp_midi_instrument_info_t structure,
2174 * with all the information of the given MIDI instrument map entry,
2175 * or NULL in case of failure.
2176 */
2177 lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )
2178 {
2179 lscp_midi_instrument_info_t *pInstrInfo;
2180 char szQuery[LSCP_BUFSIZ];
2181 const char *pszResult;
2182 const char *pszSeps = ":";
2183 const char *pszCrlf = "\r\n";
2184 char *pszToken;
2185 char *pch;
2186
2187 if (pClient == NULL)
2188 return NULL;
2189 if (pMidiInstr->map < 0)
2190 return NULL;
2191 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2192 return NULL;
2193 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2194 return NULL;
2195
2196 // Lock this section up.
2197 lscp_mutex_lock(pClient->mutex);
2198
2199 pInstrInfo = &(pClient->midi_instrument_info);
2200 lscp_midi_instrument_info_reset(pInstrInfo);
2201
2202 sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2203 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2204 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2205 pszResult = lscp_client_get_result(pClient);
2206 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2207 while (pszToken) {
2208 if (strcasecmp(pszToken, "NAME") == 0) {
2209 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2210 if (pszToken)
2211 lscp_unquote_dup(&(pInstrInfo->name), &pszToken);
2212 }
2213 else if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
2214 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2215 if (pszToken)
2216 lscp_unquote_dup(&(pInstrInfo->engine_name), &pszToken);
2217 }
2218 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
2219 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2220 if (pszToken)
2221 lscp_unquote_dup(&(pInstrInfo->instrument_file), &pszToken);
2222 }
2223 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
2224 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2225 if (pszToken)
2226 pInstrInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
2227 }
2228 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
2229 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2230 if (pszToken)
2231 lscp_unquote_dup(&(pInstrInfo->instrument_name), &pszToken);
2232 }
2233 else if (strcasecmp(pszToken, "LOAD_MODE") == 0) {
2234 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2235 if (pszToken) {
2236 pszToken = lscp_ltrim(pszToken);
2237 if (strcasecmp(pszToken, "ON_DEMAND") == 0)
2238 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND;
2239 else
2240 if (strcasecmp(pszToken, "ON_DEMAND_HOLD") == 0)
2241 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND_HOLD;
2242 else
2243 if (strcasecmp(pszToken, "PERSISTENT") == 0)
2244 pInstrInfo->load_mode = LSCP_LOAD_PERSISTENT;
2245 else
2246 pInstrInfo->load_mode = LSCP_LOAD_DEFAULT;
2247 }
2248 }
2249 else if (strcasecmp(pszToken, "VOLUME") == 0) {
2250 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2251 if (pszToken)
2252 pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));
2253 }
2254 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2255 }
2256 }
2257 else pInstrInfo = NULL;
2258
2259 // Unlock this section down.
2260 lscp_mutex_unlock(pClient->mutex);
2261
2262 return pInstrInfo;
2263 }
2264
2265
2266 /**
2267 * Clear the MIDI instrumnet map:
2268 * CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
2269 *
2270 * @param pClient Pointer to client instance structure.
2271 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2272 *
2273 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2274 */
2275 lscp_status_t lscp_clear_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2276 {
2277 char szQuery[LSCP_BUFSIZ];
2278
2279 strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
2280
2281 if (iMidiMap < 0)
2282 strcat(szQuery, "ALL");
2283 else
2284 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2285
2286 strcat(szQuery, "\r\n");
2287
2288 return lscp_client_query(pClient, szQuery);
2289 }
2290
2291
2292 // end of client.c

  ViewVC Help
Powered by ViewVC