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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3664 - (show annotations) (download)
Sun Dec 22 12:53:26 2019 UTC (4 years, 3 months ago) by schoenebeck
File MIME type: text/plain
File size: 90631 byte(s)
Improved connection error handling:

* Expose actual system error codes via client interface
  instead of just -1 whenever a syscall failed.

* Added new client interface function:
    lscp_client_connection_lost();
  for checking whether client lost connection to server.

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

  ViewVC Help
Powered by ViewVC