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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3663 - (show annotations) (download)
Sun Dec 22 12:41:28 2019 UTC (4 years, 3 months ago) by schoenebeck
File MIME type: text/plain
File size: 90136 byte(s)
- Fixed compile errors on macOS.

1 // client.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 Copyright (C) 2004-2019, 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 <locale.h>
24 #include "common.h"
25 #include <sys/time.h>
26
27 // Default timeout value (in milliseconds).
28 #define LSCP_TIMEOUT_MSECS 500
29
30
31 // Whether to use getaddrinfo() instead
32 // of deprecated gethostbyname()
33 #if !defined(WIN32)
34 #define USE_GETADDRINFO 1
35 #endif
36
37
38 // Local prototypes.
39
40 static void _lscp_client_evt_proc (void *pvClient);
41
42 static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
43 static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
44 int iSubscribe, lscp_event_t event);
45
46
47 //-------------------------------------------------------------------------
48 // General helper functions.
49
50 struct _locale_t {
51 char numeric[32];
52 char ctype[32];
53 };
54
55 // we need to ensure a constant locale setting e.g. for parsing
56 // floating point numbers with atof(), as the floating point separator
57 // character varies by the invidual locale settings
58 static void _save_and_set_c_locale(struct _locale_t* locale)
59 {
60 strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
61 strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
62 setlocale(LC_NUMERIC, "C");
63 setlocale(LC_CTYPE, "C");
64 }
65
66 // restore the original locale setting as nothing happened
67 static void _restore_locale(struct _locale_t* locale)
68 {
69 setlocale(LC_NUMERIC, locale->numeric);
70 setlocale(LC_CTYPE, locale->ctype);
71 }
72
73 // seems the standard atof() function doesnt care much about locale
74 // runtime modifications, so we use this workaround
75 static float _atof(const char* txt) {
76 float f;
77 sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
78 return f;
79 }
80
81
82 //-------------------------------------------------------------------------
83 // Event service (datagram oriented).
84
85 static void _lscp_client_evt_proc ( void *pvClient )
86 {
87 lscp_client_t *pClient = (lscp_client_t *) pvClient;
88
89 fd_set fds; // File descriptor list for select().
90 int fd, fdmax; // Maximum file descriptor number.
91 struct timeval tv; // For specifying a timeout value.
92 int iSelect; // Holds select return status.
93 int iTimeout;
94
95 char achBuffer[LSCP_BUFSIZ];
96 int cchBuffer;
97 const char *pszSeps = ":\r\n";
98 char *pszToken;
99 char *pch;
100 int cchToken;
101
102 lscp_event_t event;
103
104 #ifdef DEBUG
105 fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
106 #endif
107
108 while (pClient->evt.iState) {
109
110 // Prepare for waiting on select...
111 fd = (int) pClient->evt.sock;
112 FD_ZERO(&fds);
113 FD_SET((unsigned int) fd, &fds);
114 fdmax = fd;
115
116 // Use the timeout (x10) select feature ...
117 iTimeout = 10 * pClient->iTimeout;
118 if (iTimeout >= 1000) {
119 tv.tv_sec = iTimeout / 1000;
120 iTimeout -= tv.tv_sec * 1000;
121 }
122 else tv.tv_sec = 0;
123 tv.tv_usec = iTimeout * 1000;
124
125 // Wait for event...
126 iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
127 if (iSelect > 0 && FD_ISSET(fd, &fds)) {
128 // May recv now...
129 cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
130 if (cchBuffer > 0) {
131 // Make sure received buffer it's null terminated.
132 achBuffer[cchBuffer] = (char) 0;
133 pch = achBuffer;
134 do {
135 // Parse for the notification event message...
136 pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
137 if (strcasecmp(pszToken, "NOTIFY") == 0) {
138 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
139 event = lscp_event_from_text(pszToken);
140 // And pick the rest of data...
141 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
142 cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
143 // Double-check if we're really up to it...
144 if (pClient->events & event) {
145 // Invoke the client event callback...
146 if ((*pClient->pfnCallback)(
147 pClient,
148 event,
149 pszToken,
150 cchToken,
151 pClient->pvData) != LSCP_OK) {
152 pClient->evt.iState = 0;
153 }
154 }
155 }
156 } while (*pch);
157 } else {
158 lscp_socket_perror("_lscp_client_evt_proc: recv");
159 pClient->evt.iState = 0;
160 }
161 } // Check if select has in error.
162 else if (iSelect < 0) {
163 lscp_socket_perror("_lscp_client_evt_proc: select");
164 pClient->evt.iState = 0;
165 }
166
167 // Finally, always signal the event.
168 lscp_cond_signal(pClient->cond);
169 }
170
171 #ifdef DEBUG
172 fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
173 #endif
174 }
175
176
177 //-------------------------------------------------------------------------
178 // Event subscription helpers.
179
180 // Open the event service socket connection.
181 static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
182 {
183 lscp_socket_t sock;
184 struct sockaddr_in addr;
185 int cAddr;
186 #if defined(WIN32)
187 int iSockOpt = (-1);
188 #endif
189
190 // Prepare the event connection socket...
191 sock = socket(AF_INET, SOCK_STREAM, 0);
192 if (sock == INVALID_SOCKET) {
193 lscp_socket_perror("_lscp_client_evt_connect: socket");
194 return LSCP_FAILED;
195 }
196
197 #if defined(WIN32)
198 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
199 (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
200 lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
201 #endif
202
203 #ifdef DEBUG
204 lscp_socket_getopts("_lscp_client_evt_connect:", sock);
205 #endif
206
207 // Use same address of the command connection.
208 cAddr = sizeof(struct sockaddr_in);
209 memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
210
211 // Start the connection...
212 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
213 lscp_socket_perror("_lscp_client_evt_connect: connect");
214 closesocket(sock);
215 return LSCP_FAILED;
216 }
217
218 // Set our socket agent struct...
219 lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
220
221 // And finally the service thread...
222 return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
223 }
224
225
226 // Subscribe to a single event.
227 static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
228 int iSubscribe, lscp_event_t event )
229 {
230 const char *pszEvent;
231 char szQuery[LSCP_BUFSIZ];
232 int cchQuery;
233
234 if (pClient == NULL)
235 return LSCP_FAILED;
236
237 // Which (single) event?
238 pszEvent = lscp_event_to_text(event);
239 if (pszEvent == NULL)
240 return LSCP_FAILED;
241
242 // Build the query string...
243 cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
244 (iSubscribe == 0 ? "UN" : ""), pszEvent);
245 // Just send data, forget result...
246 if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
247 lscp_socket_perror("_lscp_client_evt_request: send");
248 return LSCP_FAILED;
249 }
250
251 // Wait on response.
252 lscp_cond_wait(pClient->cond, pClient->mutex);
253
254 // Update as naively as we can...
255 if (iSubscribe)
256 pClient->events |= event;
257 else
258 pClient->events &= ~event;
259
260 return LSCP_OK;
261 }
262
263
264 //-------------------------------------------------------------------------
265 // Client versioning teller fuunction.
266
267
268 /** Retrieve the current client library version string. */
269 const char* lscp_client_package (void) { return LSCP_PACKAGE; }
270
271 /** Retrieve the current client library version string. */
272 const char* lscp_client_version (void) { return LSCP_VERSION; }
273
274 /** Retrieve the current client library build string. */
275 const char* lscp_client_build (void) { return LSCP_BUILD; }
276
277
278 //-------------------------------------------------------------------------
279 // Client socket functions.
280
281 /**
282 * Create a client instance, estabilishing a connection to a server hostname,
283 * which must be listening on the given port. A client callback function is
284 * also supplied for server notification event handling.
285 *
286 * @param pszHost Hostname of the linuxsampler listening server.
287 * @param iPort Port number of the linuxsampler listening server.
288 * @param pfnCallback Callback function to receive event notifications.
289 * @param pvData User context opaque data, that will be passed
290 * to the callback function.
291 *
292 * @returns The new client instance pointer if successfull, which shall be
293 * used on all subsequent client calls, NULL otherwise.
294 */
295 lscp_client_t* lscp_client_create ( const char *pszHost, int iPort,
296 lscp_client_proc_t pfnCallback, void *pvData )
297 {
298 lscp_client_t *pClient;
299 #if defined(USE_GETADDRINFO)
300 char szPort[33];
301 struct addrinfo hints;
302 struct addrinfo *result, *res;
303 #else
304 struct hostent *pHost;
305 struct sockaddr_in addr;
306 int cAddr;
307 #endif /* !USE_GETADDRINFO */
308 lscp_socket_t sock;
309 #if defined(WIN32)
310 int iSockOpt = (-1);
311 #endif
312
313 if (pfnCallback == NULL) {
314 fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
315 return NULL;
316 }
317
318 #if defined(USE_GETADDRINFO)
319
320 // Convert port number to string/name...
321 snprintf(szPort, sizeof(szPort), "%d", iPort);
322
323 // Obtain address(es) matching host/port...
324 memset(&hints, 0, sizeof(struct addrinfo));
325 hints.ai_family = AF_INET;
326 hints.ai_socktype = SOCK_STREAM;
327
328 result = NULL;
329
330 if (getaddrinfo(pszHost, szPort, &hints, &result)) {
331 lscp_socket_herror("lscp_client_create: getaddrinfo");
332 return NULL;
333 }
334
335 #else
336
337 // Obtain host matching name...
338 pHost = gethostbyname(pszHost);
339 if (pHost == NULL) {
340 lscp_socket_herror("lscp_client_create: gethostbyname");
341 return NULL;
342 }
343
344 #endif /* !USE_GETADDRINFO */
345
346 // Allocate client descriptor...
347
348 pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
349 if (pClient == NULL) {
350 fprintf(stderr, "lscp_client_create: Out of memory.\n");
351 return NULL;
352 }
353 memset(pClient, 0, sizeof(lscp_client_t));
354
355 pClient->pfnCallback = pfnCallback;
356 pClient->pvData = pvData;
357
358 #ifdef DEBUG
359 fprintf(stderr,
360 "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
361 pClient, pszHost, iPort);
362 #endif
363
364 // Prepare the command connection socket...
365
366 #if defined(USE_GETADDRINFO)
367
368 // getaddrinfo() returns a list of address structures;
369 // try each address until we successfully connect(2);
370 // if socket or connect fails, we close the socket and
371 // try the next address...
372 sock = INVALID_SOCKET;
373
374 for (res = result; res; res = res->ai_next) {
375 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
376 if (sock == INVALID_SOCKET)
377 continue;
378 #if defined(WIN32)
379 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
380 (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
381 lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
382 #endif
383 #ifdef DEBUG
384 lscp_socket_getopts("lscp_client_create: cmd", sock);
385 #endif
386 if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
387 break;
388 closesocket(sock);
389 }
390
391 if (sock == INVALID_SOCKET) {
392 lscp_socket_perror("lscp_client_create: cmd: socket");
393 free(pClient);
394 return NULL;
395 }
396
397 if (res == NULL) {
398 lscp_socket_perror("lscp_client_create: cmd: connect");
399 free(pClient);
400 return NULL;
401 }
402
403 // Initialize the command socket agent struct...
404 lscp_socket_agent_init(&(pClient->cmd), sock,
405 (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
406
407 // No longer needed...
408 freeaddrinfo(result);
409
410 #else
411
412 sock = socket(AF_INET, SOCK_STREAM, 0);
413 if (sock == INVALID_SOCKET) {
414 lscp_socket_perror("lscp_client_create: cmd: socket");
415 free(pClient);
416 return NULL;
417 }
418
419 #if defined(WIN32)
420 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
421 (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
422 lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
423 #endif
424
425 #ifdef DEBUG
426 lscp_socket_getopts("lscp_client_create: cmd", sock);
427 #endif
428
429 cAddr = sizeof(struct sockaddr_in);
430 memset((char *) &addr, 0, cAddr);
431 addr.sin_family = pHost->h_addrtype;
432 memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
433 addr.sin_port = htons((short) iPort);
434
435 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
436 lscp_socket_perror("lscp_client_create: cmd: connect");
437 closesocket(sock);
438 free(pClient);
439 return NULL;
440 }
441
442 // Initialize the command socket agent struct...
443 lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
444
445 #endif /* !USE_GETADDRINFO */
446
447 #ifdef DEBUG
448 fprintf(stderr,
449 "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
450 pClient, pClient->cmd.sock,
451 inet_ntoa(pClient->cmd.addr.sin_addr),
452 ntohs(pClient->cmd.addr.sin_port));
453 #endif
454
455 // Initialize the event service socket struct...
456 lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
457 // No events subscribed, yet.
458 pClient->events = LSCP_EVENT_NONE;
459 // Initialize cached members.
460 pClient->audio_drivers = NULL;
461 pClient->midi_drivers = NULL;
462 pClient->audio_devices = NULL;
463 pClient->midi_devices = NULL;
464 pClient->engines = NULL;
465 pClient->channels = NULL;
466 pClient->fxsends = NULL;
467 pClient->midi_instruments = NULL;
468 pClient->midi_maps = NULL;
469 pClient->midi_map_name = NULL;
470 lscp_driver_info_init(&(pClient->audio_driver_info));
471 lscp_driver_info_init(&(pClient->midi_driver_info));
472 lscp_device_info_init(&(pClient->audio_device_info));
473 lscp_device_info_init(&(pClient->midi_device_info));
474 lscp_param_info_init(&(pClient->audio_param_info));
475 lscp_param_info_init(&(pClient->midi_param_info));
476 lscp_device_port_info_init(&(pClient->audio_channel_info));
477 lscp_device_port_info_init(&(pClient->midi_port_info));
478 lscp_param_info_init(&(pClient->audio_channel_param_info));
479 lscp_param_info_init(&(pClient->midi_port_param_info));
480 lscp_server_info_init(&(pClient->server_info));
481 lscp_engine_info_init(&(pClient->engine_info));
482 lscp_channel_info_init(&(pClient->channel_info));
483 lscp_fxsend_info_init(&(pClient->fxsend_info));
484 lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
485 // Initialize error stuff.
486 pClient->pszResult = NULL;
487 pClient->iErrno = -1;
488 // Stream usage stuff.
489 pClient->buffer_fill = NULL;
490 pClient->iStreamCount = 0;
491 // Default timeout value.
492 pClient->iTimeout = LSCP_TIMEOUT_MSECS;
493 pClient->iTimeoutCount = 0;
494
495 // Initialize the transaction mutex.
496 lscp_mutex_init(pClient->mutex);
497 lscp_cond_init(pClient->cond);
498
499 // Finally we've some success...
500 return pClient;
501 }
502
503
504 /**
505 * Wait for a client instance to terminate graciously.
506 *
507 * @param pClient Pointer to client instance structure.
508 */
509 lscp_status_t lscp_client_join ( lscp_client_t *pClient )
510 {
511 if (pClient == NULL)
512 return LSCP_FAILED;
513
514 #ifdef DEBUG
515 fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
516 #endif
517
518 // lscp_socket_agent_join(&(pClient->evt));
519 lscp_socket_agent_join(&(pClient->cmd));
520
521 return LSCP_OK;
522 }
523
524
525 /**
526 * Terminate and destroy a client instance.
527 *
528 * @param pClient Pointer to client instance structure.
529 *
530 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
531 */
532 lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
533 {
534 if (pClient == NULL)
535 return LSCP_FAILED;
536
537 #ifdef DEBUG
538 fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
539 #endif
540
541 // Lock this section up.
542 lscp_mutex_lock(pClient->mutex);
543
544 // Free up all cached members.
545 lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
546 lscp_fxsend_info_free(&(pClient->fxsend_info));
547 lscp_channel_info_free(&(pClient->channel_info));
548 lscp_engine_info_free(&(pClient->engine_info));
549 lscp_server_info_free(&(pClient->server_info));
550 lscp_param_info_free(&(pClient->midi_port_param_info));
551 lscp_param_info_free(&(pClient->audio_channel_param_info));
552 lscp_device_port_info_free(&(pClient->midi_port_info));
553 lscp_device_port_info_free(&(pClient->audio_channel_info));
554 lscp_param_info_free(&(pClient->midi_param_info));
555 lscp_param_info_free(&(pClient->audio_param_info));
556 lscp_device_info_free(&(pClient->midi_device_info));
557 lscp_device_info_free(&(pClient->audio_device_info));
558 lscp_driver_info_free(&(pClient->midi_driver_info));
559 lscp_driver_info_free(&(pClient->audio_driver_info));
560 // Free available engine table.
561 lscp_szsplit_destroy(pClient->audio_drivers);
562 lscp_szsplit_destroy(pClient->midi_drivers);
563 lscp_isplit_destroy(pClient->audio_devices);
564 lscp_isplit_destroy(pClient->midi_devices);
565 lscp_szsplit_destroy(pClient->engines);
566 lscp_isplit_destroy(pClient->channels);
567 lscp_isplit_destroy(pClient->fxsends);
568 lscp_midi_instruments_destroy(pClient->midi_instruments);
569 lscp_isplit_destroy(pClient->midi_maps);
570 if (pClient->midi_map_name)
571 free(pClient->midi_map_name);
572 // Make them null.
573 pClient->audio_drivers = NULL;
574 pClient->midi_drivers = NULL;
575 pClient->audio_devices = NULL;
576 pClient->midi_devices = NULL;
577 pClient->engines = NULL;
578 pClient->channels = NULL;
579 pClient->fxsends = NULL;
580 pClient->midi_instruments = NULL;
581 pClient->midi_maps = NULL;
582 pClient->midi_map_name = NULL;
583 // Free result error stuff.
584 lscp_client_set_result(pClient, NULL, 0);
585 // Free stream usage stuff.
586 if (pClient->buffer_fill)
587 free(pClient->buffer_fill);
588 pClient->buffer_fill = NULL;
589 pClient->iStreamCount = 0;
590 pClient->iTimeout = 0;
591
592 // Free socket agents.
593 lscp_socket_agent_free(&(pClient->evt));
594 lscp_socket_agent_free(&(pClient->cmd));
595
596 // Last but not least, free good ol'transaction mutex.
597 lscp_mutex_unlock(pClient->mutex);
598 lscp_mutex_destroy(pClient->mutex);
599 lscp_cond_destroy(pClient->cond);
600
601 free(pClient);
602
603 return LSCP_OK;
604 }
605
606
607 /**
608 * Set the client transaction timeout interval.
609 *
610 * @param pClient Pointer to client instance structure.
611 * @param iTimeout Transaction timeout in milliseconds.
612 *
613 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
614 */
615 lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
616 {
617 if (pClient == NULL)
618 return LSCP_FAILED;
619 if (iTimeout < 0)
620 return LSCP_FAILED;
621
622 pClient->iTimeout = iTimeout;
623 return LSCP_OK;
624 }
625
626
627 /**
628 * Get the client transaction timeout interval.
629 *
630 * @param pClient Pointer to client instance structure.
631 *
632 * @returns The current timeout value milliseconds, -1 in case of failure.
633 */
634 int lscp_client_get_timeout ( lscp_client_t *pClient )
635 {
636 if (pClient == NULL)
637 return -1;
638
639 return pClient->iTimeout;
640 }
641
642
643 //-------------------------------------------------------------------------
644 // Client common protocol functions.
645
646 /**
647 * Submit a command query line string to the server. The query string
648 * must be cr/lf and null terminated. Besides the return code, the
649 * specific server response to the command request is made available
650 * by the @ref lscp_client_get_result and @ref lscp_client_get_errno
651 * function calls.
652 *
653 * @param pClient Pointer to client instance structure.
654 * @param pszQuery Command request line to be sent to server,
655 * must be cr/lf and null terminated.
656 *
657 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
658 */
659 lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
660 {
661 lscp_status_t ret;
662
663 if (pClient == NULL)
664 return LSCP_FAILED;
665
666 // Lock this section up.
667 lscp_mutex_lock(pClient->mutex);
668
669 // Just make the now guarded call.
670 ret = lscp_client_call(pClient, pszQuery, 0);
671
672 // Unlock this section down.
673 lscp_mutex_unlock(pClient->mutex);
674
675 return ret;
676 }
677
678 /**
679 * Get the last received result string. In case of error or warning,
680 * this is the text of the error or warning message issued.
681 *
682 * @param pClient Pointer to client instance structure.
683 *
684 * @returns A pointer to the literal null-terminated result string as
685 * of the last command request.
686 */
687 const char *lscp_client_get_result ( lscp_client_t *pClient )
688 {
689 if (pClient == NULL)
690 return NULL;
691
692 return pClient->pszResult;
693 }
694
695
696 /**
697 * Get the last error/warning number received.
698 *
699 * @param pClient Pointer to client instance structure.
700 *
701 * @returns The numerical value of the last error or warning
702 * response code received.
703 */
704 int lscp_client_get_errno ( lscp_client_t *pClient )
705 {
706 if (pClient == NULL)
707 return -1;
708
709 return pClient->iErrno;
710 }
711
712
713 //-------------------------------------------------------------------------
714 // Client registration protocol functions.
715
716 /**
717 * Register frontend for receiving event messages by the sampler backend.
718 * @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
719 * for @e each event you want to subscribe. That is the old bitflag approach
720 * was abondoned at this point. You can however still register all older
721 * events with one lscp_client_subscribe() call at once. Thus, the old
722 * behavior of this functions was not broken. Those older events are namely:
723 * @code
724 * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
725 * | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
726 * | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
727 * | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
728 * | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
729 * | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
730 * | MISCELLANEOUS
731 * @endcode
732 * The old events occupy the lower 16 bits (as bit flags), and all younger
733 * events enumerate the whole upper 16 bits range. The new, enumerated
734 * events are namely:
735 * @code
736 * SUBSCRIBE CHANNEL_MIDI
737 * @endcode
738 *
739 * @param pClient Pointer to client instance structure.
740 * @param events LSCP event to subscribe.
741 *
742 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
743 */
744 lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
745 {
746 lscp_status_t ret = LSCP_OK;
747 lscp_event_t currentEvent;
748
749 if (pClient == NULL)
750 return LSCP_FAILED;
751
752 // Lock this section up.
753 lscp_mutex_lock(pClient->mutex);
754
755 // If applicable, start the alternate connection...
756 if (pClient->events == LSCP_EVENT_NONE)
757 ret = _lscp_client_evt_connect(pClient);
758
759 // Send the subscription commands.
760 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
761 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);
762 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
763 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
764 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
765 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
766 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
767 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
768 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
769 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
770 if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
771 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
772 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
773 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
774 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
775 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
776 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
777 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
778 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
779 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
780 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
781 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
782 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
783 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
784 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
785 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
786 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
787 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
788 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
789 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
790 // Caution: for the upper 16 bits, we don't use bit flags anymore ...
791 currentEvent = events & 0xffff0000;
792 if (ret == LSCP_OK && currentEvent) {
793 switch (currentEvent) {
794 case LSCP_EVENT_CHANNEL_MIDI:
795 case LSCP_EVENT_DEVICE_MIDI:
796 ret = _lscp_client_evt_request(pClient, 1, currentEvent);
797 break;
798 default: // unknown "upper" event type
799 ret = LSCP_FAILED;
800 break;
801 }
802 }
803
804 // Unlock this section down.
805 lscp_mutex_unlock(pClient->mutex);
806
807 return ret;
808 }
809
810
811 /**
812 * Deregister frontend from receiving UDP event messages anymore.
813 * @e Caution: since liblscp v0.5.5.4 you have to call
814 * lscp_client_unsubscribe() for @e each event you want to unsubscribe.
815 * That is the old bitflag approach was abondoned at this point. You can
816 * however still register all older events with one lscp_client_subscribe()
817 * call at once. Thus, the old behavior of this functions was not broken.
818 * Those older events are namely:
819 * @code
820 * UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
821 * | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
822 * | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
823 * | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
824 * | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
825 * | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
826 * | MISCELLANEOUS
827 * @endcode
828 * The old events occupy the lower 16 bits (as bit flags), and all younger
829 * events enumerate the whole upper 16 bits range. The new, enumerated
830 * events are namely:
831 * @code
832 * UNSUBSCRIBE CHANNEL_MIDI
833 * @endcode
834 *
835 * @param pClient Pointer to client instance structure.
836 * @param events LSCP event to unsubscribe.
837 *
838 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
839 */
840 lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
841 {
842 lscp_status_t ret = LSCP_OK;
843 lscp_event_t currentEvent;
844
845 if (pClient == NULL)
846 return LSCP_FAILED;
847
848 // Lock this section up.
849 lscp_mutex_lock(pClient->mutex);
850
851 // Send the unsubscription commands.
852 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
853 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT);
854 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
855 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
856 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
857 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
858 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
859 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
860 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
861 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
862 if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
863 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
864 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
865 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
866 if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
867 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
868 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
869 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
870 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
871 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
872 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
873 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
874 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
875 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
876 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
877 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
878 if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
879 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
880 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
881 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
882 // Caution: for the upper 16 bits, we don't use bit flags anymore ...
883 currentEvent = events & 0xffff0000;
884 if (ret == LSCP_OK && currentEvent) {
885 switch (currentEvent) {
886 case LSCP_EVENT_CHANNEL_MIDI:
887 case LSCP_EVENT_DEVICE_MIDI:
888 ret = _lscp_client_evt_request(pClient, 0, currentEvent);
889 break;
890 default: // unknown "upper" event type
891 ret = LSCP_FAILED;
892 break;
893 }
894 }
895
896 // If necessary, close the alternate connection...
897 if (pClient->events == LSCP_EVENT_NONE)
898 lscp_socket_agent_free(&(pClient->evt));
899
900 // Unlock this section down.
901 lscp_mutex_unlock(pClient->mutex);
902
903 return ret;
904 }
905
906
907 /**
908 * Getting current subscribed events.
909 *
910 * @param pClient Pointer to client instance structure.
911 *
912 * @returns The current subscrived bit-wise OR'ed event flags.
913 */
914 lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )
915 {
916 if (pClient == NULL)
917 return LSCP_EVENT_NONE;
918
919 return pClient->events;
920 }
921
922
923 //-------------------------------------------------------------------------
924 // Client command protocol functions.
925
926 /**
927 * Loading an instrument:
928 * LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
929 *
930 * @param pClient Pointer to client instance structure.
931 * @param pszFileName Instrument file name.
932 * @param iInstrIndex Instrument index number.
933 * @param iSamplerChannel Sampler Channel.
934 *
935 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
936 */
937 lscp_status_t lscp_load_instrument ( lscp_client_t *pClient,
938 const char *pszFileName, int iInstrIndex, int iSamplerChannel )
939 {
940 char szQuery[LSCP_BUFSIZ];
941
942 if (pszFileName == NULL || iSamplerChannel < 0)
943 return LSCP_FAILED;
944
945 sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
946 pszFileName, iInstrIndex, iSamplerChannel);
947 return lscp_client_query(pClient, szQuery);
948 }
949
950
951 /**
952 * Loading an instrument in the background (non modal):
953 * LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
954 *
955 * @param pClient Pointer to client instance structure.
956 * @param pszFileName Instrument file name.
957 * @param iInstrIndex Instrument index number.
958 * @param iSamplerChannel Sampler Channel.
959 *
960 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
961 */
962 lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient,
963 const char *pszFileName, int iInstrIndex, int iSamplerChannel )
964 {
965 char szQuery[LSCP_BUFSIZ];
966
967 if (pszFileName == NULL || iSamplerChannel < 0)
968 return LSCP_FAILED;
969
970 sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n",
971 pszFileName, iInstrIndex, iSamplerChannel);
972 return lscp_client_query(pClient, szQuery);
973 }
974
975
976 /**
977 * Loading a sampler engine:
978 * LOAD ENGINE <engine-name> <sampler-channel>
979 *
980 * @param pClient Pointer to client instance structure.
981 * @param pszEngineName Engine name.
982 * @param iSamplerChannel Sampler channel number.
983 *
984 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
985 */
986 lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
987 {
988 char szQuery[LSCP_BUFSIZ];
989
990 if (pszEngineName == NULL || iSamplerChannel < 0)
991 return LSCP_FAILED;
992
993 sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
994 pszEngineName, iSamplerChannel);
995 return lscp_client_query(pClient, szQuery);
996 }
997
998
999 /**
1000 * Current number of sampler channels:
1001 * GET CHANNELS
1002 *
1003 * @param pClient Pointer to client instance structure.
1004 *
1005 * @returns The current total number of sampler channels on success,
1006 * -1 otherwise.
1007 */
1008 int lscp_get_channels ( lscp_client_t *pClient )
1009 {
1010 int iChannels = -1;
1011
1012 if (pClient == NULL)
1013 return -1;
1014
1015 // Lock this section up.
1016 lscp_mutex_lock(pClient->mutex);
1017
1018 if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)
1019 iChannels = atoi(lscp_client_get_result(pClient));
1020
1021 // Unlock this section doen.
1022 lscp_mutex_unlock(pClient->mutex);
1023
1024 return iChannels;
1025 }
1026
1027
1028 /**
1029 * List current sampler channels number identifiers:
1030 * LIST CHANNELS
1031 *
1032 * @param pClient Pointer to client instance structure.
1033 *
1034 * @returns An array of the sampler channels identifiers as positive integers,
1035 * terminated with -1 on success, NULL otherwise.
1036 */
1037 int *lscp_list_channels ( lscp_client_t *pClient )
1038 {
1039 const char *pszSeps = ",";
1040
1041 if (pClient == NULL)
1042 return NULL;
1043
1044 // Lock this section up.
1045 lscp_mutex_lock(pClient->mutex);
1046
1047 if (pClient->channels) {
1048 lscp_isplit_destroy(pClient->channels);
1049 pClient->channels = NULL;
1050 }
1051
1052 if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)
1053 pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
1054
1055 // Unlock this section down.
1056 lscp_mutex_unlock(pClient->mutex);
1057
1058 return pClient->channels;
1059 }
1060
1061
1062 /**
1063 * Adding a new sampler channel:
1064 * ADD CHANNEL
1065 *
1066 * @param pClient Pointer to client instance structure.
1067 *
1068 * @returns The new sampler channel number identifier,
1069 * or -1 in case of failure.
1070 */
1071 int lscp_add_channel ( lscp_client_t *pClient )
1072 {
1073 int iSamplerChannel = -1;
1074
1075 if (pClient == NULL)
1076 return -1;
1077
1078 // Lock this section up.
1079 lscp_mutex_lock(pClient->mutex);
1080
1081 if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)
1082 iSamplerChannel = atoi(lscp_client_get_result(pClient));
1083
1084 // Unlock this section down.
1085 lscp_mutex_unlock(pClient->mutex);
1086
1087 return iSamplerChannel;
1088 }
1089
1090
1091 /**
1092 * Removing a sampler channel:
1093 * REMOVE CHANNEL <sampler-channel>
1094 *
1095 * @param pClient Pointer to client instance structure.
1096 * @param iSamplerChannel Sampler channel number.
1097 *
1098 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1099 */
1100 lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
1101 {
1102 char szQuery[LSCP_BUFSIZ];
1103
1104 if (iSamplerChannel < 0)
1105 return LSCP_FAILED;
1106
1107 sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
1108 return lscp_client_query(pClient, szQuery);
1109 }
1110
1111
1112 /**
1113 * Getting all available engines count:
1114 * GET AVAILABLE_ENGINES
1115 *
1116 * @param pClient Pointer to client instance structure.
1117 *
1118 * @returns The current total number of sampler engines on success,
1119 * -1 otherwise.
1120 */
1121 int lscp_get_available_engines ( lscp_client_t *pClient )
1122 {
1123 int iAvailableEngines = -1;
1124
1125 if (pClient == NULL)
1126 return -1;
1127
1128 // Lock this section up.
1129 lscp_mutex_lock(pClient->mutex);
1130
1131 if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
1132 iAvailableEngines = atoi(lscp_client_get_result(pClient));
1133
1134 // Unlock this section down.
1135 lscp_mutex_unlock(pClient->mutex);
1136
1137 return iAvailableEngines;
1138 }
1139
1140
1141 /**
1142 * Getting all available engines:
1143 * LIST AVAILABLE_ENGINES
1144 *
1145 * @param pClient Pointer to client instance structure.
1146 *
1147 * @returns A NULL terminated array of engine name strings,
1148 * or NULL in case of failure.
1149 */
1150 const char **lscp_list_available_engines ( lscp_client_t *pClient )
1151 {
1152 const char *pszSeps = ",";
1153
1154 if (pClient == NULL)
1155 return NULL;
1156
1157 // Lock this section up.
1158 lscp_mutex_lock(pClient->mutex);
1159
1160 if (pClient->engines) {
1161 lscp_szsplit_destroy(pClient->engines);
1162 pClient->engines = NULL;
1163 }
1164
1165 if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
1166 pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
1167
1168 // Unlock this section down.
1169 lscp_mutex_unlock(pClient->mutex);
1170
1171 return (const char **) pClient->engines;
1172 }
1173
1174
1175 /**
1176 * Getting information about an engine.
1177 * GET ENGINE INFO <engine-name>
1178 *
1179 * @param pClient Pointer to client instance structure.
1180 * @param pszEngineName Engine name.
1181 *
1182 * @returns A pointer to a @ref lscp_engine_info_t structure, with all the
1183 * information of the given sampler engine, or NULL in case of failure.
1184 */
1185 lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient,
1186 const char *pszEngineName )
1187 {
1188 lscp_engine_info_t *pEngineInfo;
1189 char szQuery[LSCP_BUFSIZ];
1190 const char *pszResult;
1191 const char *pszSeps = ":";
1192 const char *pszCrlf = "\r\n";
1193 char *pszToken;
1194 char *pch;
1195
1196 if (pClient == NULL)
1197 return NULL;
1198 if (pszEngineName == NULL)
1199 return NULL;
1200
1201 // Lock this section up.
1202 lscp_mutex_lock(pClient->mutex);
1203
1204 pEngineInfo = &(pClient->engine_info);
1205 lscp_engine_info_reset(pEngineInfo);
1206
1207 sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
1208 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1209 pszResult = lscp_client_get_result(pClient);
1210 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1211 while (pszToken) {
1212 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1213 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1214 if (pszToken)
1215 lscp_unquote_dup(&(pEngineInfo->description), &pszToken);
1216 }
1217 else if (strcasecmp(pszToken, "VERSION") == 0) {
1218 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1219 if (pszToken)
1220 lscp_unquote_dup(&(pEngineInfo->version), &pszToken);
1221 }
1222 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1223 }
1224 }
1225 else pEngineInfo = NULL;
1226
1227 // Unlock this section down.
1228 lscp_mutex_unlock(pClient->mutex);
1229
1230 return pEngineInfo;
1231 }
1232
1233
1234 /**
1235 * Getting sampler channel informations:
1236 * GET CHANNEL INFO <sampler-channel>
1237 *
1238 * @param pClient Pointer to client instance structure.
1239 * @param iSamplerChannel Sampler channel number.
1240 *
1241 * @returns A pointer to a @ref lscp_channel_info_t structure, with all the
1242 * information of the given sampler channel, or NULL in case of failure.
1243 */
1244 lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
1245 {
1246 lscp_channel_info_t *pChannelInfo;
1247 char szQuery[LSCP_BUFSIZ];
1248 const char *pszResult;
1249 const char *pszSeps = ":";
1250 const char *pszCrlf = "\r\n";
1251 char *pszToken;
1252 char *pch;
1253 struct _locale_t locale;
1254
1255 if (pClient == NULL)
1256 return NULL;
1257 if (iSamplerChannel < 0)
1258 return NULL;
1259
1260 // Lock this section up.
1261 lscp_mutex_lock(pClient->mutex);
1262
1263 pChannelInfo = &(pClient->channel_info);
1264 lscp_channel_info_reset(pChannelInfo);
1265
1266 _save_and_set_c_locale(&locale);
1267
1268 sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1269 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1270 pszResult = lscp_client_get_result(pClient);
1271 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1272 while (pszToken) {
1273 if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
1274 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1275 if (pszToken)
1276 lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);
1277 }
1278 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
1279 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1280 if (pszToken)
1281 pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
1282 }
1283 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
1284 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1285 if (pszToken)
1286 pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
1287 }
1288 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
1289 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1290 if (pszToken) {
1291 if (pChannelInfo->audio_routing)
1292 lscp_isplit_destroy(pChannelInfo->audio_routing);
1293 pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1294 }
1295 }
1296 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
1297 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1298 if (pszToken)
1299 lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);
1300 }
1301 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
1302 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1303 if (pszToken)
1304 pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
1305 }
1306 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
1307 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1308 if (pszToken)
1309 lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);
1310 }
1311 else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
1312 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1313 if (pszToken)
1314 pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
1315 }
1316 else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
1317 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1318 if (pszToken)
1319 pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
1320 }
1321 else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
1322 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1323 if (pszToken)
1324 pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
1325 }
1326 else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
1327 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1328 if (pszToken) {
1329 pszToken = lscp_ltrim(pszToken);
1330 if (strcasecmp(pszToken, "ALL") == 0)
1331 pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;
1332 else
1333 pChannelInfo->midi_channel = atoi(pszToken);
1334 }
1335 }
1336 else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1337 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1338 if (pszToken) {
1339 pszToken = lscp_ltrim(pszToken);
1340 if (strcasecmp(pszToken, "NONE") == 0)
1341 pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1342 else
1343 if (strcasecmp(pszToken, "DEFAULT") == 0)
1344 pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1345 else
1346 pChannelInfo->midi_map = atoi(pszToken);
1347 }
1348 }
1349 else if (strcasecmp(pszToken, "VOLUME") == 0) {
1350 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1351 if (pszToken)
1352 pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1353 }
1354 else if (strcasecmp(pszToken, "MUTE") == 0) {
1355 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1356 if (pszToken)
1357 pChannelInfo->mute = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1358 }
1359 else if (strcasecmp(pszToken, "SOLO") == 0) {
1360 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1361 if (pszToken)
1362 pChannelInfo->solo = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1363 }
1364 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1365 }
1366 }
1367 else pChannelInfo = NULL;
1368
1369 _restore_locale(&locale);
1370
1371 // Unlock this section up.
1372 lscp_mutex_unlock(pClient->mutex);
1373
1374 return pChannelInfo;
1375 }
1376
1377
1378 /**
1379 * Current number of active voices:
1380 * GET CHANNEL VOICE_COUNT <sampler-channel>
1381 *
1382 * @param pClient Pointer to client instance structure.
1383 * @param iSamplerChannel Sampler channel number.
1384 *
1385 * @returns The number of voices currently active, -1 in case of failure.
1386 */
1387 int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
1388 {
1389 char szQuery[LSCP_BUFSIZ];
1390 int iVoiceCount = -1;
1391
1392 if (pClient == NULL)
1393 return -1;
1394 if (iSamplerChannel < 0)
1395 return -1;
1396
1397 // Lock this section up.
1398 lscp_mutex_lock(pClient->mutex);
1399
1400 sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
1401 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1402 iVoiceCount = atoi(lscp_client_get_result(pClient));
1403
1404 // Unlock this section down.
1405 lscp_mutex_unlock(pClient->mutex);
1406
1407 return iVoiceCount;
1408 }
1409
1410
1411 /**
1412 * Current number of active disk streams:
1413 * GET CHANNEL STREAM_COUNT <sampler-channel>
1414 *
1415 * @param pClient Pointer to client instance structure.
1416 * @param iSamplerChannel Sampler channel number.
1417 *
1418 * @returns The number of active disk streams on success, -1 otherwise.
1419 */
1420 int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
1421 {
1422 char szQuery[LSCP_BUFSIZ];
1423 int iStreamCount = -1;
1424
1425 if (pClient == NULL)
1426 return -1;
1427 if (iSamplerChannel < 0)
1428 return -1;
1429
1430 // Lock this section up.
1431 lscp_mutex_lock(pClient->mutex);
1432
1433 sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1434 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1435 iStreamCount = atoi(lscp_client_get_result(pClient));
1436
1437 // Unlock this section down.
1438 lscp_mutex_unlock(pClient->mutex);
1439
1440 return iStreamCount;
1441 }
1442
1443
1444 /**
1445 * Current least usage of active disk streams.
1446 *
1447 * @param pClient Pointer to client instance structure.
1448 * @param iSamplerChannel Sampler channel number.
1449 *
1450 * @returns The usage percentage of the least filled active disk stream
1451 * on success, -1 otherwise.
1452 */
1453 int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )
1454 {
1455 char szQuery[LSCP_BUFSIZ];
1456 int iStreamUsage = -1;
1457 const char *pszResult;
1458 const char *pszSeps = "[]%,";
1459 char *pszToken;
1460 char *pch;
1461 int iStream;
1462 int iPercent;
1463
1464 if (pClient == NULL)
1465 return -1;
1466 if (iSamplerChannel < 0)
1467 return -1;
1468
1469 // Lock this section up.
1470 lscp_mutex_lock(pClient->mutex);
1471
1472 iStream = 0;
1473 sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);
1474 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1475 pszResult = lscp_client_get_result(pClient);
1476 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1477 while (pszToken) {
1478 if (*pszToken) {
1479 // Skip stream id.
1480 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1481 if (pszToken == NULL)
1482 break;
1483 // Get least buffer fill percentage.
1484 iPercent = atol(pszToken);
1485 if (iStreamUsage > iPercent || iStream == 0)
1486 iStreamUsage = iPercent;
1487 iStream++;
1488 }
1489 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1490 }
1491 }
1492
1493 // Unlock this section down.
1494 lscp_mutex_unlock(pClient->mutex);
1495
1496 return iStreamUsage;
1497 }
1498
1499
1500 /**
1501 * Current fill state of disk stream buffers:
1502 * GET CHANNEL BUFFER_FILL {BYTES|PERCENTAGE} <sampler-channel>
1503 *
1504 * @param pClient Pointer to client instance structure.
1505 * @param usage_type Usage type to be returned, either
1506 * @ref LSCP_USAGE_BYTES, or
1507 * @ref LSCP_USAGE_PERCENTAGE.
1508 * @param iSamplerChannel Sampler channel number.
1509 *
1510 * @returns A pointer to a @ref lscp_buffer_fill_t structure, with the
1511 * information of the current disk stream buffer fill usage, for the given
1512 * sampler channel, or NULL in case of failure.
1513 */
1514 lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient,
1515 lscp_usage_t usage_type, int iSamplerChannel )
1516 {
1517 lscp_buffer_fill_t *pBufferFill;
1518 char szQuery[LSCP_BUFSIZ];
1519 int iStreamCount;
1520 const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1521 const char *pszResult;
1522 const char *pszSeps = "[]%,";
1523 char *pszToken;
1524 char *pch;
1525 int iStream;
1526
1527 // Retrieve a channel stream estimation.
1528 iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1529 if (iStreamCount < 0)
1530 return NULL;
1531
1532 // Lock this section up.
1533 lscp_mutex_lock(pClient->mutex);
1534
1535 // Check if we need to reallocate the stream usage array.
1536 if (pClient->iStreamCount != iStreamCount) {
1537 if (pClient->buffer_fill)
1538 free(pClient->buffer_fill);
1539 if (iStreamCount > 0)
1540 pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1541 else
1542 pClient->buffer_fill = NULL;
1543 pClient->iStreamCount = iStreamCount;
1544 }
1545
1546 // Get buffer fill usage...
1547 pBufferFill = pClient->buffer_fill;
1548 if (pBufferFill && iStreamCount > 0) {
1549 iStream = 0;
1550 pBufferFill = pClient->buffer_fill;
1551 sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1552 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1553 pszResult = lscp_client_get_result(pClient);
1554 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1555 while (pszToken && iStream < pClient->iStreamCount) {
1556 if (*pszToken) {
1557 pBufferFill[iStream].stream_id = atol(pszToken);
1558 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1559 if (pszToken == NULL)
1560 break;
1561 pBufferFill[iStream].stream_usage = atol(pszToken);
1562 iStream++;
1563 }
1564 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1565 }
1566 } // Reset the usage, whatever it was before.
1567 else while (iStream < pClient->iStreamCount)
1568 pBufferFill[iStream++].stream_usage = 0;
1569 }
1570
1571 // Unlock this section down.
1572 lscp_mutex_unlock(pClient->mutex);
1573
1574 return pBufferFill;
1575 }
1576
1577
1578 /**
1579 * Setting audio output type:
1580 * SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
1581 *
1582 * @param pClient Pointer to client instance structure.
1583 * @param iSamplerChannel Sampler channel number.
1584 * @param pszAudioDriver Audio output driver type (e.g. "ALSA" or "JACK").
1585 *
1586 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1587 */
1588 lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1589 int iSamplerChannel, const char *pszAudioDriver )
1590 {
1591 char szQuery[LSCP_BUFSIZ];
1592
1593 if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1594 return LSCP_FAILED;
1595
1596 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1597 iSamplerChannel, pszAudioDriver);
1598 return lscp_client_query(pClient, szQuery);
1599 }
1600
1601
1602 /**
1603 * Setting audio output device:
1604 * SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1605 *
1606 * @param pClient Pointer to client instance structure.
1607 * @param iSamplerChannel Sampler channel number.
1608 * @param iAudioDevice Audio output device number identifier.
1609 *
1610 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1611 */
1612 lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1613 int iSamplerChannel, int iAudioDevice )
1614 {
1615 char szQuery[LSCP_BUFSIZ];
1616
1617 if (iSamplerChannel < 0 || iAudioDevice < 0)
1618 return LSCP_FAILED;
1619
1620 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1621 iSamplerChannel, iAudioDevice);
1622 return lscp_client_query(pClient, szQuery);
1623 }
1624
1625
1626 /**
1627 * Setting audio output channel:
1628 * SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-output-chan> <audio-input-chan>
1629 *
1630 * @param pClient Pointer to client instance structure.
1631 * @param iSamplerChannel Sampler channel number.
1632 * @param iAudioOut Audio output device channel to be routed from.
1633 * @param iAudioIn Audio output device channel to be routed into.
1634 *
1635 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1636 */
1637 lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1638 int iSamplerChannel, int iAudioOut, int iAudioIn )
1639 {
1640 char szQuery[LSCP_BUFSIZ];
1641
1642 if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1643 return LSCP_FAILED;
1644
1645 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n",
1646 iSamplerChannel, iAudioOut, iAudioIn);
1647 return lscp_client_query(pClient, szQuery);
1648 }
1649
1650
1651 /**
1652 * Setting MIDI input type:
1653 * SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
1654 *
1655 * @param pClient Pointer to client instance structure.
1656 * @param iSamplerChannel Sampler channel number.
1657 * @param pszMidiDriver MIDI input driver type (e.g. "ALSA").
1658 *
1659 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1660 */
1661 lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1662 int iSamplerChannel, const char *pszMidiDriver )
1663 {
1664 char szQuery[LSCP_BUFSIZ];
1665
1666 if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1667 return LSCP_FAILED;
1668
1669 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1670 iSamplerChannel, pszMidiDriver);
1671 return lscp_client_query(pClient, szQuery);
1672 }
1673
1674
1675 /**
1676 * Setting MIDI input device:
1677 * SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1678 *
1679 * @param pClient Pointer to client instance structure.
1680 * @param iSamplerChannel Sampler channel number.
1681 * @param iMidiDevice MIDI input device number identifier.
1682 *
1683 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1684 */
1685 lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1686 int iSamplerChannel, int iMidiDevice )
1687 {
1688 char szQuery[LSCP_BUFSIZ];
1689
1690 if (iSamplerChannel < 0 || iMidiDevice < 0)
1691 return LSCP_FAILED;
1692
1693 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1694 iSamplerChannel, iMidiDevice);
1695 return lscp_client_query(pClient, szQuery);
1696 }
1697
1698
1699 /**
1700 * Setting MIDI input port:
1701 * SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
1702 *
1703 * @param pClient Pointer to client instance structure.
1704 * @param iSamplerChannel Sampler channel number.
1705 * @param iMidiPort MIDI input driver virtual port number.
1706 *
1707 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1708 */
1709 lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1710 int iSamplerChannel, int iMidiPort )
1711 {
1712 char szQuery[LSCP_BUFSIZ];
1713
1714 if (iSamplerChannel < 0 || iMidiPort < 0)
1715 return LSCP_FAILED;
1716
1717 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1718 iSamplerChannel, iMidiPort);
1719 return lscp_client_query(pClient, szQuery);
1720 }
1721
1722
1723 /**
1724 * Setting MIDI input channel:
1725 * SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
1726 *
1727 * @param pClient Pointer to client instance structure.
1728 * @param iSamplerChannel Sampler channel number.
1729 * @param iMidiChannel MIDI channel address number to listen (0-15) or
1730 * @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1731 *
1732 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1733 */
1734 lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient,
1735 int iSamplerChannel, int iMidiChannel )
1736 {
1737 char szQuery[LSCP_BUFSIZ];
1738
1739 if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1740 return LSCP_FAILED;
1741
1742 if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1743 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1744 iSamplerChannel);
1745 else
1746 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1747 iSamplerChannel, iMidiChannel);
1748 return lscp_client_query(pClient, szQuery);
1749 }
1750
1751
1752 /**
1753 * Setting MIDI instrument map:
1754 * SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1755 *
1756 * @param pClient Pointer to client instance structure.
1757 * @param iSamplerChannel Sampler channel number.
1758 * @param iMidiMap MIDI instrument map number, or either
1759 * @ref LSCP_MIDI_MAP_NONE or
1760 * @ref LSCP_MIDI_MAP_DEFAULT .
1761 *
1762 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1763 */
1764 lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1765 int iSamplerChannel, int iMidiMap )
1766 {
1767 char szQuery[LSCP_BUFSIZ];
1768
1769 if (iSamplerChannel < 0)
1770 return LSCP_FAILED;
1771
1772 sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1773 if (iMidiMap == LSCP_MIDI_MAP_NONE)
1774 strcat(szQuery , "NONE");
1775 else
1776 if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1777 strcat(szQuery , "DEFAULT");
1778 else
1779 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1780
1781 strcat(szQuery, "\r\n");
1782
1783 return lscp_client_query(pClient, szQuery);
1784 }
1785
1786
1787 /**
1788 * Setting channel volume:
1789 * SET CHANNEL VOLUME <sampler-channel> <volume>
1790 *
1791 * @param pClient Pointer to client instance structure.
1792 * @param iSamplerChannel Sampler channel number.
1793 * @param fVolume Sampler channel volume as a positive floating point
1794 * number, where a value less than 1.0 for attenuation,
1795 * and greater than 1.0 for amplification.
1796 *
1797 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1798 */
1799 lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient,
1800 int iSamplerChannel, float fVolume )
1801 {
1802 char szQuery[LSCP_BUFSIZ];
1803 struct _locale_t locale;
1804
1805 if (iSamplerChannel < 0 || fVolume < 0.0f)
1806 return LSCP_FAILED;
1807
1808 _save_and_set_c_locale(&locale);
1809 sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1810 iSamplerChannel, fVolume);
1811 _restore_locale(&locale);
1812
1813 return lscp_client_query(pClient, szQuery);
1814 }
1815
1816
1817 /**
1818 * Muting a sampler channel:
1819 * SET CHANNEL MUTE <sampler-channel> <mute>
1820 *
1821 * @param pClient Pointer to client instance structure.
1822 * @param iSamplerChannel Sampler channel number.
1823 * @param iMute Sampler channel mute state as a boolean value,
1824 * either 1 (one) to mute the channel or 0 (zero)
1825 * to unmute the channel.
1826 *
1827 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1828 */
1829 lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1830 int iSamplerChannel, int iMute )
1831 {
1832 char szQuery[LSCP_BUFSIZ];
1833
1834 if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1835 return LSCP_FAILED;
1836
1837 sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1838 iSamplerChannel, iMute);
1839 return lscp_client_query(pClient, szQuery);
1840 }
1841
1842
1843 /**
1844 * Soloing a sampler channel:
1845 * SET CHANNEL SOLO <sampler-channel> <solo>
1846 *
1847 * @param pClient Pointer to client instance structure.
1848 * @param iSamplerChannel Sampler channel number.
1849 * @param iSolo Sampler channel solo state as a boolean value,
1850 * either 1 (one) to solo the channel or 0 (zero)
1851 * to unsolo the channel.
1852 *
1853 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1854 */
1855 lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient,
1856 int iSamplerChannel, int iSolo )
1857 {
1858 char szQuery[LSCP_BUFSIZ];
1859
1860 if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1861 return LSCP_FAILED;
1862
1863 sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1864 iSamplerChannel, iSolo);
1865 return lscp_client_query(pClient, szQuery);
1866 }
1867
1868
1869 /**
1870 * Resetting a sampler channel:
1871 * RESET CHANNEL <sampler-channel>
1872 *
1873 * @param pClient Pointer to client instance structure.
1874 * @param iSamplerChannel Sampler channel number.
1875 *
1876 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1877 */
1878 lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1879 {
1880 char szQuery[LSCP_BUFSIZ];
1881
1882 if (iSamplerChannel < 0)
1883 return LSCP_FAILED;
1884
1885 sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1886 return lscp_client_query(pClient, szQuery);
1887 }
1888
1889
1890 /**
1891 * Resetting the sampler:
1892 * RESET
1893 *
1894 * @param pClient Pointer to client instance structure.
1895 *
1896 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1897 */
1898 lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1899 {
1900 // Do actual whole sampler reset...
1901 return lscp_client_query(pClient, "RESET\r\n");
1902 }
1903
1904
1905 /**
1906 * Getting information about the server.
1907 * GET SERVER INFO
1908 *
1909 * @param pClient Pointer to client instance structure.
1910 *
1911 * @returns A pointer to a @ref lscp_server_info_t structure, with all the
1912 * information of the current connected server, or NULL in case of failure.
1913 */
1914 lscp_server_info_t *lscp_get_server_info ( lscp_client_t *pClient )
1915 {
1916 lscp_server_info_t *pServerInfo;
1917 const char *pszResult;
1918 const char *pszSeps = ":";
1919 const char *pszCrlf = "\r\n";
1920 char *pszToken;
1921 char *pch;
1922
1923 if (pClient == NULL)
1924 return NULL;
1925
1926 // Lock this section up.
1927 lscp_mutex_lock(pClient->mutex);
1928
1929 pServerInfo = &(pClient->server_info);
1930 lscp_server_info_reset(pServerInfo);
1931
1932 if (lscp_client_call(pClient, "GET SERVER INFO\r\n", 1) == LSCP_OK) {
1933 pszResult = lscp_client_get_result(pClient);
1934 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1935 while (pszToken) {
1936 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1937 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1938 if (pszToken)
1939 lscp_unquote_dup(&(pServerInfo->description), &pszToken);
1940 }
1941 else if (strcasecmp(pszToken, "VERSION") == 0) {
1942 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1943 if (pszToken)
1944 lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1945 }
1946 else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1947 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1948 if (pszToken)
1949 lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1950 }
1951 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1952 }
1953 }
1954 else pServerInfo = NULL;
1955
1956 // Unlock this section down.
1957 lscp_mutex_unlock(pClient->mutex);
1958
1959 return pServerInfo;
1960 }
1961
1962
1963 /**
1964 * Current total number of active voices:
1965 * GET TOTAL_VOICE_COUNT
1966 *
1967 * @param pClient Pointer to client instance structure.
1968 *
1969 * @returns The total number of voices currently active,
1970 * -1 in case of failure.
1971 */
1972 int lscp_get_total_voice_count ( lscp_client_t *pClient )
1973 {
1974 int iVoiceCount = -1;
1975
1976 if (pClient == NULL)
1977 return -1;
1978
1979 // Lock this section up.
1980 lscp_mutex_lock(pClient->mutex);
1981
1982 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT\r\n", 0) == LSCP_OK)
1983 iVoiceCount = atoi(lscp_client_get_result(pClient));
1984
1985 // Unlock this section down.
1986 lscp_mutex_unlock(pClient->mutex);
1987
1988 return iVoiceCount;
1989 }
1990
1991
1992 /**
1993 * Maximum amount of active voices:
1994 * GET TOTAL_VOICE_COUNT_MAX
1995 *
1996 * @param pClient Pointer to client instance structure.
1997 *
1998 * @returns The maximum amount of voices currently active,
1999 * -1 in case of failure.
2000 */
2001 int lscp_get_total_voice_count_max ( lscp_client_t *pClient )
2002 {
2003 int iVoiceCount = -1;
2004
2005 if (pClient == NULL)
2006 return -1;
2007
2008 // Lock this section up.
2009 lscp_mutex_lock(pClient->mutex);
2010
2011 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT_MAX\r\n", 0) == LSCP_OK)
2012 iVoiceCount = atoi(lscp_client_get_result(pClient));
2013
2014 // Unlock this section down.
2015 lscp_mutex_unlock(pClient->mutex);
2016
2017 return iVoiceCount;
2018 }
2019
2020
2021 /**
2022 * Get global volume attenuation:
2023 * GET VOLUME
2024 *
2025 * @param pClient Pointer to client instance structure.
2026 *
2027 * @returns The global volume as positive floating point value usually in
2028 * the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2029 */
2030 float lscp_get_volume ( lscp_client_t *pClient )
2031 {
2032 float fVolume = 0.0f;
2033 struct _locale_t locale;
2034
2035 if (pClient == NULL)
2036 return 0.0f;
2037
2038 // Lock this section up.
2039 lscp_mutex_lock(pClient->mutex);
2040
2041 _save_and_set_c_locale(&locale);
2042
2043 if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2044 fVolume = _atof(lscp_client_get_result(pClient));
2045
2046 _restore_locale(&locale);
2047
2048 // Unlock this section down.
2049 lscp_mutex_unlock(pClient->mutex);
2050
2051 return fVolume;
2052 }
2053
2054
2055 /**
2056 * Setting global volume attenuation:
2057 * SET VOLUME <volume>
2058 *
2059 * @param pClient Pointer to client instance structure.
2060 * @param fVolume Global volume parameter as positive floating point
2061 * value usually be in the range between 0.0 and 1.0,
2062 * that is for attenuating the overall volume.
2063 *
2064 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2065 */
2066 lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2067 {
2068 char szQuery[LSCP_BUFSIZ];
2069 struct _locale_t locale;
2070
2071 if (fVolume < 0.0f)
2072 return LSCP_FAILED;
2073
2074 _save_and_set_c_locale(&locale);
2075 sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2076 _restore_locale(&locale);
2077
2078 return lscp_client_query(pClient, szQuery);
2079 }
2080
2081
2082 /**
2083 * Get global voice limit setting:
2084 * @code
2085 * GET VOICES
2086 * @endcode
2087 * This value reflects the maximum amount of voices a sampler engine
2088 * processes simultaniously before voice stealing kicks in.
2089 *
2090 * @param pClient Pointer to client instance structure.
2091 *
2092 * @returns The current global maximum amount of voices limit or a
2093 * negative value on error (e.g. if sampler doesn't support
2094 * this command).
2095 */
2096 int lscp_get_voices ( lscp_client_t *pClient )
2097 {
2098 int iVoices = -1;
2099
2100 if (pClient == NULL)
2101 return -1;
2102
2103 // Lock this section up.
2104 lscp_mutex_lock(pClient->mutex);
2105
2106 if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2107 iVoices = atoi(lscp_client_get_result(pClient));
2108
2109 // Unlock this section down.
2110 lscp_mutex_unlock(pClient->mutex);
2111
2112 return iVoices;
2113 }
2114
2115
2116 /**
2117 * Setting global voice limit setting:
2118 * @code
2119 * SET VOICES <max-voices>
2120 * @endcode
2121 * This value reflects the maximum amount of voices a sampler engine
2122 * processes simultaniously before voice stealing kicks in. Note that
2123 * this value will be passed to all sampler engine instances, that is
2124 * the total amount of maximum voices on the running system is thus
2125 * @param iMaxVoices multiplied with the current amount of sampler
2126 * engine instances.
2127 *
2128 * @param pClient Pointer to client instance structure.
2129 * @param iMaxVoices Global voice limit setting as integer value larger
2130 * or equal to 1.
2131 *
2132 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2133 */
2134 lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2135 {
2136 char szQuery[LSCP_BUFSIZ];
2137
2138 if (iMaxVoices < 1)
2139 return LSCP_FAILED;
2140
2141 sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2142 return lscp_client_query(pClient, szQuery);
2143 }
2144
2145
2146 /**
2147 * Get global disk streams limit setting:
2148 * @code
2149 * GET STREAMS
2150 * @endcode
2151 * This value reflects the maximum amount of disk streams a sampler
2152 * engine processes simultaniously.
2153 *
2154 * @param pClient Pointer to client instance structure.
2155 *
2156 * @returns The current global maximum amount of disk streams limit
2157 * or a negative value on error (e.g. if sampler doesn't
2158 * support this command).
2159 */
2160 int lscp_get_streams ( lscp_client_t *pClient )
2161 {
2162 int iStreams = -1;
2163
2164 if (pClient == NULL)
2165 return -1;
2166
2167 // Lock this section up.
2168 lscp_mutex_lock(pClient->mutex);
2169
2170 if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2171 iStreams = atoi(lscp_client_get_result(pClient));
2172
2173 // Unlock this section down.
2174 lscp_mutex_unlock(pClient->mutex);
2175
2176 return iStreams;
2177 }
2178
2179
2180 /**
2181 * Setting global disk streams limit setting:
2182 * @code
2183 * SET STREAMS <max-streams>
2184 * @endcode
2185 * This value reflects the maximum amount of dist streams a sampler
2186 * engine instance processes simultaniously. Note that this value will
2187 * be passed to all sampler engine instances, that is the total amount
2188 * of maximum disk streams on the running system is thus
2189 * @param iMaxStreams multiplied with the current amount of sampler
2190 * engine instances.
2191 *
2192 * @param pClient Pointer to client instance structure.
2193 * @param iMaxStreams Global streams limit setting as positive integer
2194 * value (larger or equal to 0).
2195 *
2196 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2197 */
2198 lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2199 {
2200 char szQuery[LSCP_BUFSIZ];
2201
2202 if (iMaxStreams < 0)
2203 return LSCP_FAILED;
2204
2205 sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2206 return lscp_client_query(pClient, szQuery);
2207 }
2208
2209
2210 /**
2211 * Add an effect send to a sampler channel:
2212 * CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2213 *
2214 * @param pClient Pointer to client instance structure.
2215 * @param iSamplerChannel Sampler channel number.
2216 * @param iMidiController MIDI controller used to alter the effect,
2217 * usually a number between 0 and 127.
2218 * @param pszFxName Optional name for the effect send entity,
2219 * does not have to be unique.
2220 *
2221 * @returns The new effect send number identifier, or -1 in case of failure.
2222 */
2223 int lscp_create_fxsend ( lscp_client_t *pClient,
2224 int iSamplerChannel, int iMidiController, const char *pszFxName )
2225 {
2226 int iFxSend = -1;
2227 char szQuery[LSCP_BUFSIZ];
2228
2229 if (pClient == NULL)
2230 return -1;
2231 if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2232 return -1;
2233
2234 // Lock this section up.
2235 lscp_mutex_lock(pClient->mutex);
2236
2237 sprintf(szQuery, "CREATE FX_SEND %d %d",
2238 iSamplerChannel, iMidiController);
2239
2240 if (pszFxName)
2241 sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2242
2243 strcat(szQuery, "\r\n");
2244
2245 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2246 iFxSend = atoi(lscp_client_get_result(pClient));
2247
2248 // Unlock this section down.
2249 lscp_mutex_unlock(pClient->mutex);
2250
2251 return iFxSend;
2252 }
2253
2254
2255 /**
2256 * Remove an effect send from a sampler channel:
2257 * DESTROY FX_SEND <sampler-channel> <fx-send-id>
2258 *
2259 * @param pClient Pointer to client instance structure.
2260 * @param iSamplerChannel Sampler channel number.
2261 * @param iFxSend Effect send number.
2262 *
2263 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2264 */
2265 lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2266 int iSamplerChannel, int iFxSend )
2267 {
2268 char szQuery[LSCP_BUFSIZ];
2269
2270 if (iSamplerChannel < 0 || iFxSend < 0)
2271 return LSCP_FAILED;
2272
2273 sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2274 iSamplerChannel, iFxSend);
2275
2276 return lscp_client_query(pClient, szQuery);
2277 }
2278
2279
2280 /**
2281 * Get amount of effect sends on a sampler channel:
2282 * GET FX_SENDS <sampler-channel>
2283 *
2284 * @param pClient Pointer to client instance structure.
2285 * @param iSamplerChannel Sampler channel number.
2286 *
2287 * @returns The current total number of effect sends of the sampler channel
2288 * on success, -1 otherwise.
2289 */
2290 int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2291 {
2292 int iFxSends = -1;
2293 char szQuery[LSCP_BUFSIZ];
2294
2295 if (pClient == NULL)
2296 return -1;
2297 if (iSamplerChannel < 0)
2298 return -1;
2299
2300 // Lock this section up.
2301 lscp_mutex_lock(pClient->mutex);
2302
2303 sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2304
2305 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2306 iFxSends = atoi(lscp_client_get_result(pClient));
2307
2308 // Unlock this section doen.
2309 lscp_mutex_unlock(pClient->mutex);
2310
2311 return iFxSends;
2312 }
2313
2314
2315 /**
2316 * List all effect sends on a sampler channel:
2317 * LIST FX_SENDS <sampler-channel>
2318 *
2319 * @param pClient Pointer to client instance structure.
2320 * @param iSamplerChannel Sampler channel number.
2321 *
2322 * @returns An array of the effect sends identifiers as positive integers,
2323 * terminated with -1 on success, NULL otherwise.
2324 */
2325 int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2326 {
2327 const char *pszSeps = ",";
2328 char szQuery[LSCP_BUFSIZ];
2329
2330 if (pClient == NULL)
2331 return NULL;
2332
2333 // Lock this section up.
2334 lscp_mutex_lock(pClient->mutex);
2335
2336 if (pClient->fxsends) {
2337 lscp_isplit_destroy(pClient->fxsends);
2338 pClient->fxsends = NULL;
2339 }
2340
2341 sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2342
2343 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2344 pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2345
2346 // Unlock this section down.
2347 lscp_mutex_unlock(pClient->mutex);
2348
2349 return pClient->fxsends;
2350 }
2351
2352
2353 /**
2354 * Getting effect send information
2355 * GET FX_SEND INFO <sampler-channel> <fx-send-id>
2356 *
2357 * @param pClient Pointer to client instance structure.
2358 * @param iSamplerChannel Sampler channel number.
2359 * @param iFxSend Effect send number.
2360 *
2361 * @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2362 * information of the given FX send, or NULL in case of failure.
2363 */
2364 lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2365 int iSamplerChannel, int iFxSend )
2366 {
2367 lscp_fxsend_info_t *pFxSendInfo;
2368 char szQuery[LSCP_BUFSIZ];
2369 const char *pszResult;
2370 const char *pszSeps = ":";
2371 const char *pszCrlf = "\r\n";
2372 char *pszToken;
2373 char *pch;
2374 struct _locale_t locale;
2375
2376 if (pClient == NULL)
2377 return NULL;
2378 if (iSamplerChannel < 0 || iFxSend < 0)
2379 return NULL;
2380
2381 // Lock this section up.
2382 lscp_mutex_lock(pClient->mutex);
2383
2384 _save_and_set_c_locale(&locale);
2385
2386 pFxSendInfo = &(pClient->fxsend_info);
2387 lscp_fxsend_info_reset(pFxSendInfo);
2388
2389 sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2390 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2391 pszResult = lscp_client_get_result(pClient);
2392 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2393 while (pszToken) {
2394 if (strcasecmp(pszToken, "NAME") == 0) {
2395 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2396 if (pszToken)
2397 lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2398 }
2399 else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2400 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2401 if (pszToken)
2402 pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2403 }
2404 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2405 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2406 if (pszToken) {
2407 if (pFxSendInfo->audio_routing)
2408 lscp_isplit_destroy(pFxSendInfo->audio_routing);
2409 pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2410 }
2411 }
2412 else if (strcasecmp(pszToken, "LEVEL") == 0) {
2413 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2414 if (pszToken)
2415 pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2416 }
2417 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2418 }
2419 }
2420 else pFxSendInfo = NULL;
2421
2422 _restore_locale(&locale);
2423
2424 // Unlock this section up.
2425 lscp_mutex_unlock(pClient->mutex);
2426
2427 return pFxSendInfo;
2428 }
2429
2430
2431 /**
2432 * Alter effect send's name:
2433 * @code
2434 * SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2435 * @endcode
2436 *
2437 * @param pClient Pointer to client instance structure.
2438 * @param iSamplerChannel Sampler channel number.
2439 * @param iFxSend Effect send number.
2440 * @param pszFxName Effect send's new name.
2441 *
2442 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2443 */
2444 lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2445 int iSamplerChannel, int iFxSend, const char *pszFxName )
2446 {
2447 char szQuery[LSCP_BUFSIZ];
2448
2449 if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2450 return LSCP_FAILED;
2451
2452 snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2453 iSamplerChannel, iFxSend, pszFxName);
2454 return lscp_client_query(pClient, szQuery);
2455 }
2456
2457
2458 /**
2459 * Alter effect send's audio routing:
2460 * SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2461 * <audio-src> <audio-dst>
2462 *
2463 * @param pClient Pointer to client instance structure.
2464 * @param iSamplerChannel Sampler channel number.
2465 * @param iFxSend Effect send number.
2466 * @param iAudioSrc Audio output device channel to be routed from.
2467 * @param iAudioDst Audio output device channel to be routed into.
2468 *
2469 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2470 */
2471 lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2472 int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2473 {
2474 char szQuery[LSCP_BUFSIZ];
2475
2476 if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2477 return LSCP_FAILED;
2478
2479 sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2480 iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2481 return lscp_client_query(pClient, szQuery);
2482 }
2483
2484
2485 /**
2486 * Alter effect send's MIDI controller:
2487 * SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2488 *
2489 * @param pClient Pointer to client instance structure.
2490 * @param iSamplerChannel Sampler channel number.
2491 * @param iFxSend Effect send number.
2492 * @param iMidiController MIDI controller used to alter the effect,
2493 * usually a number between 0 and 127.
2494 *
2495 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2496 */
2497 lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2498 int iSamplerChannel, int iFxSend, int iMidiController )
2499 {
2500 char szQuery[LSCP_BUFSIZ];
2501
2502 if (iSamplerChannel < 0 || iFxSend < 0 ||
2503 iMidiController < 0 || iMidiController > 127)
2504 return LSCP_FAILED;
2505
2506 sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2507 iSamplerChannel, iFxSend, iMidiController);
2508 return lscp_client_query(pClient, szQuery);
2509 }
2510
2511
2512 /**
2513 * Alter effect send's audio level:
2514 * SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2515 *
2516 * @param pClient Pointer to client instance structure.
2517 * @param iSamplerChannel Sampler channel number.
2518 * @param iFxSend Effect send number.
2519 * @param fLevel Effect send volume level.
2520 *
2521 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2522 */
2523 lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2524 int iSamplerChannel, int iFxSend, float fLevel )
2525 {
2526 char szQuery[LSCP_BUFSIZ];
2527 struct _locale_t locale;
2528
2529 if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2530 return LSCP_FAILED;
2531
2532 _save_and_set_c_locale(&locale);
2533 sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2534 iSamplerChannel, iFxSend, fLevel);
2535 _restore_locale(&locale);
2536
2537 return lscp_client_query(pClient, szQuery);
2538 }
2539
2540
2541 /**
2542 * Create a new MIDI instrument map:
2543 * ADD MIDI_INSTRUMENT_MAP [<name>]
2544 *
2545 * @param pClient Pointer to client instance structure.
2546 * @param pszMapName MIDI instrument map name (optional)
2547 *
2548 * @returns The new MIDI instrument map number identifier,
2549 * or -1 in case of failure.
2550 */
2551 int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
2552 {
2553 int iMidiMap = -1;
2554 char szQuery[LSCP_BUFSIZ];
2555
2556 if (pClient == NULL)
2557 return -1;
2558
2559 // Lock this section up.
2560 lscp_mutex_lock(pClient->mutex);
2561
2562 strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2563
2564 if (pszMapName)
2565 sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2566
2567 strcat(szQuery, "\r\n");
2568
2569 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2570 iMidiMap = atoi(lscp_client_get_result(pClient));
2571
2572 // Unlock this section down.
2573 lscp_mutex_unlock(pClient->mutex);
2574
2575 return iMidiMap;
2576 }
2577
2578
2579 /**
2580 * Delete one particular or all MIDI instrument maps:
2581 * REMOVE MIDI_INSTRUMENT_MAP <midi-map>
2582 *
2583 * @param pClient Pointer to client instance structure.
2584 * @param iMidiMap MIDI instrument map number.
2585 *
2586 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2587 */
2588 lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
2589 {
2590 char szQuery[LSCP_BUFSIZ];
2591
2592 if (iMidiMap < 0)
2593 return LSCP_FAILED;
2594
2595 sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
2596
2597 return lscp_client_query(pClient, szQuery);
2598 }
2599
2600
2601 /**
2602 * Get amount of existing MIDI instrument maps:
2603 * GET MIDI_INSTRUMENT_MAPS
2604 *
2605 * @param pClient Pointer to client instance structure.
2606 *
2607 * @returns The current total number of MIDI instrument maps
2608 * on success, -1 otherwise.
2609 */
2610 int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
2611 {
2612 int iMidiMaps = -1;
2613
2614 if (pClient == NULL)
2615 return -1;
2616
2617 // Lock this section up.
2618 lscp_mutex_lock(pClient->mutex);
2619
2620 if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2621 iMidiMaps = atoi(lscp_client_get_result(pClient));
2622
2623 // Unlock this section doen.
2624 lscp_mutex_unlock(pClient->mutex);
2625
2626 return iMidiMaps;
2627 }
2628
2629
2630 /**
2631 * Getting all created MIDI instrument maps:
2632 * LIST MIDI_INSTRUMENT_MAPS
2633 *
2634 * @param pClient Pointer to client instance structure.
2635 *
2636 * @returns An array of the MIDI instrument map identifiers as positive
2637 * integers, terminated with -1 on success, NULL otherwise.
2638 */
2639 int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
2640 {
2641 const char *pszSeps = ",";
2642
2643 if (pClient == NULL)
2644 return NULL;
2645
2646 // Lock this section up.
2647 lscp_mutex_lock(pClient->mutex);
2648
2649 if (pClient->midi_maps) {
2650 lscp_isplit_destroy(pClient->midi_maps);
2651 pClient->midi_maps = NULL;
2652 }
2653
2654 if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2655 pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2656
2657 // Unlock this section down.
2658 lscp_mutex_unlock(pClient->mutex);
2659
2660 return pClient->midi_maps;
2661 }
2662
2663
2664 /**
2665 * Getting a MIDI instrument map name:
2666 * GET MIDI_INSTRUMENT_MAP INFO <midi-map>
2667 *
2668 * @param pClient Pointer to client instance structure.
2669 * @param iMidiMap MIDI instrument map number.
2670 *
2671 * @returns The MIDI instrument map name on success, NULL on failure.
2672 */
2673 const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
2674 {
2675 char szQuery[LSCP_BUFSIZ];
2676 const char *pszResult;
2677 const char *pszSeps = ":";
2678 const char *pszCrlf = "\r\n";
2679 char *pszToken;
2680 char *pch;
2681
2682 if (pClient == NULL)
2683 return NULL;
2684 if (iMidiMap < 0)
2685 return NULL;
2686
2687 // Lock this section up.
2688 lscp_mutex_lock(pClient->mutex);
2689
2690 if (pClient->midi_map_name) {
2691 free(pClient->midi_map_name);
2692 pClient->midi_map_name = NULL;
2693 }
2694
2695 sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
2696 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2697 pszResult = lscp_client_get_result(pClient);
2698 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2699 while (pszToken) {
2700 if (strcasecmp(pszToken, "NAME") == 0) {
2701 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2702 if (pszToken)
2703 lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
2704 }
2705 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2706 }
2707 }
2708
2709 // Unlock this section down.
2710 lscp_mutex_unlock(pClient->mutex);
2711
2712 return pClient->midi_map_name;
2713 }
2714
2715
2716 /**
2717 * Renaming a MIDI instrument map:
2718 * SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
2719 *
2720 * @param pClient Pointer to client instance structure.
2721 * @param iMidiMap MIDI instrument map number.
2722 * @param pszMapName MIDI instrument map name.
2723 *
2724 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2725 */
2726 lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
2727 {
2728 char szQuery[LSCP_BUFSIZ];
2729
2730 if (iMidiMap < 0)
2731 return LSCP_FAILED;
2732 if (pszMapName == NULL)
2733 return LSCP_FAILED;
2734
2735 sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
2736 iMidiMap, pszMapName);
2737
2738 return lscp_client_query(pClient, szQuery);
2739 }
2740
2741
2742 /**
2743 * Create or replace a MIDI instrumnet map entry:
2744 * MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2745 * <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
2746 *
2747 * @param pClient Pointer to client instance structure.
2748 * @param pMidiInstr MIDI instrument bank and program parameter key.
2749 * @param pszEngineName Engine name.
2750 * @param pszFileName Instrument file name.
2751 * @param iInstrIndex Instrument index number.
2752 * @param fVolume Reflects the master volume of the instrument as
2753 * a positive floating point number, where a value
2754 * less than 1.0 for attenuation, and greater than
2755 * 1.0 for amplification.
2756 * @param load_mode Instrument load life-time strategy, either
2757 * @ref LSCP_LOAD_DEFAULT, or
2758 * @ref LSCP_LOAD_ON_DEMAND, or
2759 * @ref LSCP_LOAD_ON_DEMAND_HOLD, or
2760 * @ref LSCP_LOAD_PERSISTENT.
2761 * @param pszName Instrument custom name for the map entry (optional).
2762 *
2763 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2764 */
2765 lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient,
2766 lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2767 const char *pszFileName, int iInstrIndex, float fVolume,
2768 lscp_load_mode_t load_mode, const char *pszName )
2769 {
2770 char szQuery[LSCP_BUFSIZ];
2771 struct _locale_t locale;
2772
2773 if (pMidiInstr->map < 0)
2774 return LSCP_FAILED;
2775 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2776 return LSCP_FAILED;
2777 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2778 return LSCP_FAILED;
2779 if (pszEngineName == NULL || pszFileName == NULL)
2780 return LSCP_FAILED;
2781
2782 if (fVolume < 0.0f)
2783 fVolume = 1.0f;
2784
2785 _save_and_set_c_locale(&locale);
2786 sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2787 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2788 pszEngineName, pszFileName, iInstrIndex, fVolume);
2789 _restore_locale(&locale);
2790
2791 switch (load_mode) {
2792 case LSCP_LOAD_PERSISTENT:
2793 strcat(szQuery, " PERSISTENT");
2794 break;
2795 case LSCP_LOAD_ON_DEMAND_HOLD:
2796 strcat(szQuery, " ON_DEMAND_HOLD");
2797 break;
2798 case LSCP_LOAD_ON_DEMAND:
2799 strcat(szQuery, " ON_DEMAND");
2800 break;
2801 case LSCP_LOAD_DEFAULT:
2802 default:
2803 break;
2804 }
2805
2806 if (pszName)
2807 sprintf(szQuery + strlen(szQuery), " '%s'", pszName);
2808
2809 strcat(szQuery, "\r\n");
2810
2811 return lscp_client_query(pClient, szQuery);
2812 }
2813
2814
2815 /**
2816 * Remove an entry from the MIDI instrument map:
2817 * UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2818 *
2819 * @param pClient Pointer to client instance structure.
2820 * @param pMidiInstr MIDI instrument bank and program parameter key.
2821 *
2822 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2823 */
2824 lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient,
2825 lscp_midi_instrument_t *pMidiInstr )
2826 {
2827 char szQuery[LSCP_BUFSIZ];
2828
2829 if (pMidiInstr->map < 0)
2830 return LSCP_FAILED;
2831 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2832 return LSCP_FAILED;
2833 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2834 return LSCP_FAILED;
2835
2836 sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2837 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2838
2839 return lscp_client_query(pClient, szQuery);
2840 }
2841
2842
2843 /**
2844 * Get the total count of MIDI instrument map entries:
2845 * GET MIDI_INSTRUMENTS ALL|<midi-map>
2846 *
2847 * @param pClient Pointer to client instance structure.
2848 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2849 *
2850 * @returns The current total number of MIDI instrument map entries
2851 * on success, -1 otherwise.
2852 */
2853 int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2854 {
2855 int iInstruments = -1;
2856 char szQuery[LSCP_BUFSIZ];
2857
2858 if (pClient == NULL)
2859 return -1;
2860
2861 // Lock this section up.
2862 lscp_mutex_lock(pClient->mutex);
2863
2864 strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
2865
2866 if (iMidiMap < 0)
2867 strcat(szQuery, "ALL");
2868 else
2869 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2870
2871 strcat(szQuery, "\r\n");
2872
2873 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2874 iInstruments = atoi(lscp_client_get_result(pClient));
2875
2876 // Unlock this section down.
2877 lscp_mutex_unlock(pClient->mutex);
2878
2879 return iInstruments;
2880 }
2881
2882
2883 /**
2884 * Getting indeces of all MIDI instrument map entries:
2885 * LIST MIDI_INSTRUMENTS ALL|<midi-map>
2886 *
2887 * @param pClient Pointer to client instance structure.
2888 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2889 *
2890 * @returns An array of @ref lscp_midi_instrument_t, terminated with the
2891 * {-1,-1,-1} triplet, NULL otherwise.
2892 */
2893 lscp_midi_instrument_t *lscp_list_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2894 {
2895 char szQuery[LSCP_BUFSIZ];
2896
2897 if (pClient == NULL)
2898 return NULL;
2899
2900 // Lock this section up.
2901 lscp_mutex_lock(pClient->mutex);
2902
2903 if (pClient->midi_instruments) {
2904 lscp_midi_instruments_destroy(pClient->midi_instruments);
2905 pClient->midi_instruments = NULL;
2906 }
2907
2908 strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
2909
2910 if (iMidiMap < 0)
2911 strcat(szQuery, "ALL");
2912 else
2913 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2914
2915 strcat(szQuery, "\r\n");
2916
2917 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2918 pClient->midi_instruments = lscp_midi_instruments_create(
2919 lscp_client_get_result(pClient));
2920
2921 // Unlock this section down.
2922 lscp_mutex_unlock(pClient->mutex);
2923
2924 return pClient->midi_instruments;
2925 }
2926
2927
2928 /**
2929 * Getting information about a MIDI instrument map entry:
2930 * GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2931 *
2932 * @param pClient Pointer to client instance structure.
2933 * @param pMidiInstr MIDI instrument bank and program parameter key.
2934 *
2935 * @returns A pointer to a @ref lscp_midi_instrument_info_t structure,
2936 * with all the information of the given MIDI instrument map entry,
2937 * or NULL in case of failure.
2938 */
2939 lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient,
2940 lscp_midi_instrument_t *pMidiInstr )
2941 {
2942 lscp_midi_instrument_info_t *pInstrInfo;
2943 char szQuery[LSCP_BUFSIZ];
2944 const char *pszResult;
2945 const char *pszSeps = ":";
2946 const char *pszCrlf = "\r\n";
2947 char *pszToken;
2948 char *pch;
2949 struct _locale_t locale;
2950
2951 if (pClient == NULL)
2952 return NULL;
2953 if (pMidiInstr->map < 0)
2954 return NULL;
2955 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2956 return NULL;
2957 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2958 return NULL;
2959
2960 // Lock this section up.
2961 lscp_mutex_lock(pClient->mutex);
2962
2963 _save_and_set_c_locale(&locale);
2964
2965 pInstrInfo = &(pClient->midi_instrument_info);
2966 lscp_midi_instrument_info_reset(pInstrInfo);
2967
2968 sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2969 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2970 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2971 pszResult = lscp_client_get_result(pClient);
2972 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2973 while (pszToken) {
2974 if (strcasecmp(pszToken, "NAME") == 0) {
2975 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2976 if (pszToken)
2977 lscp_unquote_dup(&(pInstrInfo->name), &pszToken);
2978 }
2979 else if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
2980 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2981 if (pszToken)
2982 lscp_unquote_dup(&(pInstrInfo->engine_name), &pszToken);
2983 }
2984 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
2985 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2986 if (pszToken)
2987 lscp_unquote_dup(&(pInstrInfo->instrument_file), &pszToken);
2988 }
2989 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
2990 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2991 if (pszToken)
2992 pInstrInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
2993 }
2994 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
2995 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2996 if (pszToken)
2997 lscp_unquote_dup(&(pInstrInfo->instrument_name), &pszToken);
2998 }
2999 else if (strcasecmp(pszToken, "LOAD_MODE") == 0) {
3000 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3001 if (pszToken) {
3002 pszToken = lscp_ltrim(pszToken);
3003 if (strcasecmp(pszToken, "ON_DEMAND") == 0)
3004 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND;
3005 else
3006 if (strcasecmp(pszToken, "ON_DEMAND_HOLD") == 0)
3007 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND_HOLD;
3008 else
3009 if (strcasecmp(pszToken, "PERSISTENT") == 0)
3010 pInstrInfo->load_mode = LSCP_LOAD_PERSISTENT;
3011 else
3012 pInstrInfo->load_mode = LSCP_LOAD_DEFAULT;
3013 }
3014 }
3015 else if (strcasecmp(pszToken, "VOLUME") == 0) {
3016 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3017 if (pszToken)
3018 pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3019 }
3020 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3021 }
3022 }
3023 else pInstrInfo = NULL;
3024
3025 _restore_locale(&locale);
3026
3027 // Unlock this section down.
3028 lscp_mutex_unlock(pClient->mutex);
3029
3030 return pInstrInfo;
3031 }
3032
3033
3034 /**
3035 * Clear the MIDI instrumnet map:
3036 * CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
3037 *
3038 * @param pClient Pointer to client instance structure.
3039 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
3040 *
3041 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3042 */
3043 lscp_status_t lscp_clear_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
3044 {
3045 char szQuery[LSCP_BUFSIZ];
3046
3047 strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
3048
3049 if (iMidiMap < 0)
3050 strcat(szQuery, "ALL");
3051 else
3052 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
3053
3054 strcat(szQuery, "\r\n");
3055
3056 return lscp_client_query(pClient, szQuery);
3057 }
3058
3059
3060 /**
3061 * Open an instrument editor application for the instrument
3062 * on the given sampler channel:
3063 * EDIT CHANNEL INSTRUMENT <sampler-channel>
3064 *
3065 * @param pClient Pointer to client instance structure.
3066 * @param iSamplerChannel Sampler Channel.
3067 *
3068 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3069 */
3070 lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3071 {
3072 char szQuery[LSCP_BUFSIZ];
3073
3074 if (iSamplerChannel < 0)
3075 return LSCP_FAILED;
3076
3077 sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3078
3079 return lscp_client_query(pClient, szQuery);
3080 }
3081
3082
3083 // end of client.c

  ViewVC Help
Powered by ViewVC