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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC