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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC