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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 146 - (show annotations) (download)
Fri Jun 25 12:00:25 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 41772 byte(s)
* Major changes to server event protocol interface
  on attempt to comply with draft-protocol v.11.

1 // client.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 Copyright (C) 2004, 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 Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21 *****************************************************************************/
22
23 #include "common.h"
24
25 // Default timeout value (in milliseconds).
26 #define LSCP_TIMEOUT_MSECS 500
27
28
29 // Local prototypes.
30
31 static void _lscp_client_evt_proc (void *pvClient);
32
33 static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
34 static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);
35
36
37 //-------------------------------------------------------------------------
38 // Event service (datagram oriented).
39
40 static void _lscp_client_evt_proc ( void *pvClient )
41 {
42 lscp_client_t *pClient = (lscp_client_t *) pvClient;
43 char achBuffer[LSCP_BUFSIZ];
44 int cchBuffer;
45 const char *pszSeps = ":\r\n";
46 char *pszToken;
47 char *pch;
48 int cchToken;
49 lscp_event_t event;
50
51 #ifdef DEBUG
52 fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
53 #endif
54
55 while (pClient->evt.iState) {
56 // Wait for event...
57 cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
58 if (cchBuffer > 0) {
59 // Make sure received buffer it's null terminated.
60 achBuffer[cchBuffer] = (char) 0;
61 // Parse for the notification event message...
62 pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".
63 if (strcasecmp(pszToken, "NOTIFY") == 0) {
64 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
65 event = lscp_event_from_text(pszToken);
66 // And pick the rest of data...
67 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
68 cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
69 // Double-check if we're really up to it...
70 if (pClient->events & event) {
71 // Invoke the client event callback...
72 if ((*pClient->pfnCallback)(
73 pClient,
74 event,
75 pszToken,
76 cchToken,
77 pClient->pvData) != LSCP_OK) {
78 pClient->evt.iState = 0;
79 }
80 }
81 }
82 } else {
83 lscp_socket_perror("_lscp_client_evt_proc: recv");
84 pClient->evt.iState = 0;
85 }
86 }
87
88 #ifdef DEBUG
89 fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
90 #endif
91 }
92
93
94 //-------------------------------------------------------------------------
95 // Event subscription helpers.
96
97 // Open the event service socket connection.
98 static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
99 {
100 lscp_socket_t sock;
101 struct sockaddr_in addr;
102 int cAddr;
103 #if defined(WIN32)
104 int iSockOpt = (-1);
105 #endif
106
107 // Prepare the event connection socket...
108 sock = socket(AF_INET, SOCK_STREAM, 0);
109 if (sock == INVALID_SOCKET) {
110 lscp_socket_perror("_lscp_client_evt_connect: socket");
111 return LSCP_FAILED;
112 }
113
114 #if defined(WIN32)
115 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
116 lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
117 #endif
118
119 #ifdef DEBUG
120 lscp_socket_getopts("_lscp_client_evt_connect:", sock);
121 #endif
122
123 // Use same address of the command connection.
124 cAddr = sizeof(struct sockaddr_in);
125 memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
126
127 // Start the connection...
128 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
129 lscp_socket_perror("_lscp_client_evt_connect: connect");
130 closesocket(sock);
131 return LSCP_FAILED;
132 }
133
134 // Set our socket agent struct...
135 lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
136
137 // And finally the service thread...
138 return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
139 }
140
141
142 // Subscribe to a single event.
143 static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )
144 {
145 const char *pszEvent;
146 char szQuery[LSCP_BUFSIZ];
147 int cchQuery;
148
149 if (pClient == NULL)
150 return LSCP_FAILED;
151
152 // Which (single) event?
153 pszEvent = lscp_event_to_text(event);
154 if (pszEvent == NULL)
155 return LSCP_FAILED;
156
157 // Build the query string...
158 cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);
159 // Just send data, forget result...
160 if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
161 lscp_socket_perror("_lscp_client_evt_request: send");
162 return LSCP_FAILED;
163 }
164
165 // Update as naively as we can...
166 if (iSubscribe)
167 pClient->events |= event;
168 else
169 pClient->events &= ~event;
170
171 return LSCP_OK;
172 }
173
174
175 //-------------------------------------------------------------------------
176 // Client versioning teller fuunction.
177
178
179 /** Retrieve the current client library version string. */
180 const char* lscp_client_package (void) { return LSCP_PACKAGE; }
181
182 /** Retrieve the current client library version string. */
183 const char* lscp_client_version (void) { return LSCP_VERSION; }
184
185 /** Retrieve the current client library build timestamp string. */
186 const char* lscp_client_build (void) { return __DATE__ " " __TIME__; }
187
188
189 //-------------------------------------------------------------------------
190 // Client socket functions.
191
192 /**
193 * Create a client instance, estabilishing a connection to a server hostname,
194 * which must be listening on the given port. A client callback function is
195 * also supplied for server notification event handling.
196 *
197 * @param pszHost Hostname of the linuxsampler listening server.
198 * @param iPort Port number of the linuxsampler listening server.
199 * @param pfnCallback Callback function to receive event notifications.
200 * @param pvData User context opaque data, that will be passed
201 * to the callback function.
202 *
203 * @returns The new client instance pointer if successfull, which shall be
204 * used on all subsequent client calls, NULL otherwise.
205 */
206 lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )
207 {
208 lscp_client_t *pClient;
209 struct hostent *pHost;
210 lscp_socket_t sock;
211 struct sockaddr_in addr;
212 int cAddr;
213 #if defined(WIN32)
214 int iSockOpt = (-1);
215 #endif
216
217 if (pfnCallback == NULL) {
218 fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
219 return NULL;
220 }
221
222 pHost = gethostbyname(pszHost);
223 if (pHost == NULL) {
224 lscp_socket_herror("lscp_client_create: gethostbyname");
225 return NULL;
226 }
227
228 // Allocate client descriptor...
229
230 pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
231 if (pClient == NULL) {
232 fprintf(stderr, "lscp_client_create: Out of memory.\n");
233 return NULL;
234 }
235 memset(pClient, 0, sizeof(lscp_client_t));
236
237 pClient->pfnCallback = pfnCallback;
238 pClient->pvData = pvData;
239
240 #ifdef DEBUG
241 fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);
242 #endif
243
244 // Prepare the command connection socket...
245
246 sock = socket(AF_INET, SOCK_STREAM, 0);
247 if (sock == INVALID_SOCKET) {
248 lscp_socket_perror("lscp_client_create: cmd: socket");
249 free(pClient);
250 return NULL;
251 }
252
253 #if defined(WIN32)
254 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
255 lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
256 #endif
257
258 #ifdef DEBUG
259 lscp_socket_getopts("lscp_client_create: cmd", sock);
260 #endif
261
262 cAddr = sizeof(struct sockaddr_in);
263 memset((char *) &addr, 0, cAddr);
264 addr.sin_family = pHost->h_addrtype;
265 memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
266 addr.sin_port = htons((short) iPort);
267
268 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
269 lscp_socket_perror("lscp_client_create: cmd: connect");
270 closesocket(sock);
271 free(pClient);
272 return NULL;
273 }
274
275 // Initialize the command socket agent struct...
276 lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
277
278 #ifdef DEBUG
279 fprintf(stderr, "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->cmd.sock, inet_ntoa(pClient->cmd.addr.sin_addr), ntohs(pClient->cmd.addr.sin_port));
280 #endif
281
282 // Initialize the event service socket struct...
283 lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
284 // No events subscribed, yet.
285 pClient->events = LSCP_EVENT_NONE;
286 // Initialize cached members.
287 pClient->audio_drivers = NULL;
288 pClient->midi_drivers = NULL;
289 pClient->audio_devices = NULL;
290 pClient->midi_devices = NULL;
291 pClient->engines = NULL;
292 pClient->channels = NULL;
293 lscp_driver_info_init(&(pClient->audio_info));
294 lscp_driver_info_init(&(pClient->midi_info));
295 lscp_engine_info_init(&(pClient->engine_info));
296 lscp_channel_info_init(&(pClient->channel_info));
297 // Initialize error stuff.
298 pClient->pszResult = NULL;
299 pClient->iErrno = -1;
300 // Stream usage stuff.
301 pClient->buffer_fill = NULL;
302 pClient->iStreamCount = 0;
303 // Default timeout value.
304 pClient->iTimeout = LSCP_TIMEOUT_MSECS;
305
306 // Initialize the transaction mutex.
307 lscp_mutex_init(pClient->mutex);
308
309 // Finally we've some success...
310 return pClient;
311 }
312
313
314 /**
315 * Wait for a client instance to terminate graciously.
316 *
317 * @param pClient Pointer to client instance structure.
318 */
319 lscp_status_t lscp_client_join ( lscp_client_t *pClient )
320 {
321 if (pClient == NULL)
322 return LSCP_FAILED;
323
324 #ifdef DEBUG
325 fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
326 #endif
327
328 // lscp_socket_agent_join(&(pClient->evt));
329 lscp_socket_agent_join(&(pClient->cmd));
330
331 return LSCP_OK;
332 }
333
334
335 /**
336 * Terminate and destroy a client instance.
337 *
338 * @param pClient Pointer to client instance structure.
339 *
340 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
341 */
342 lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
343 {
344 if (pClient == NULL)
345 return LSCP_FAILED;
346
347 #ifdef DEBUG
348 fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
349 #endif
350
351 // Lock this section up.
352 lscp_mutex_lock(pClient->mutex);
353
354 // Free up all cached members.
355 lscp_channel_info_reset(&(pClient->channel_info));
356 lscp_engine_info_reset(&(pClient->engine_info));
357 lscp_driver_info_reset(&(pClient->midi_info));
358 lscp_driver_info_reset(&(pClient->audio_info));
359 // Free available engine table.
360 lscp_szsplit_destroy(pClient->audio_drivers);
361 lscp_szsplit_destroy(pClient->midi_drivers);
362 lscp_isplit_destroy(pClient->audio_devices);
363 lscp_isplit_destroy(pClient->midi_devices);
364 lscp_szsplit_destroy(pClient->engines);
365 lscp_isplit_destroy(pClient->channels);
366 // Make them null.
367 pClient->audio_drivers = NULL;
368 pClient->midi_drivers = NULL;
369 pClient->engines = NULL;
370 // Free result error stuff.
371 lscp_client_set_result(pClient, NULL, 0);
372 // Frre stream usage stuff.
373 if (pClient->buffer_fill)
374 free(pClient->buffer_fill);
375 pClient->buffer_fill = NULL;
376 pClient->iStreamCount = 0;
377 pClient->iTimeout = 0;
378
379 // Free socket agents.
380 lscp_socket_agent_free(&(pClient->evt));
381 lscp_socket_agent_free(&(pClient->cmd));
382
383 // Last but not least, free good ol'transaction mutex.
384 lscp_mutex_unlock(pClient->mutex);
385 lscp_mutex_destroy(pClient->mutex);
386
387 free(pClient);
388
389 return LSCP_OK;
390 }
391
392
393 /**
394 * Set the client transaction timeout interval.
395 *
396 * @param pClient Pointer to client instance structure.
397 * @param iTimeout Transaction timeout in milliseconds.
398 *
399 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
400 */
401 lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
402 {
403 if (pClient == NULL)
404 return LSCP_FAILED;
405 if (iTimeout < 0)
406 return LSCP_FAILED;
407
408 pClient->iTimeout = iTimeout;
409 return LSCP_OK;
410 }
411
412
413 /**
414 * Get the client transaction timeout interval.
415 *
416 * @param pClient Pointer to client instance structure.
417 *
418 * @returns The current timeout value milliseconds, -1 in case of failure.
419 */
420 int lscp_client_get_timeout ( lscp_client_t *pClient )
421 {
422 if (pClient == NULL)
423 return -1;
424
425 return pClient->iTimeout;
426 }
427
428
429 //-------------------------------------------------------------------------
430 // Client common protocol functions.
431
432 /**
433 * Submit a command query line string to the server. The query string
434 * must be cr/lf and null terminated. Besides the return code, the
435 * specific server response to the command request is made available
436 * by the @ref lscp_client_get_result and @ref lscp_client_get_errno
437 * function calls.
438 *
439 * @param pClient Pointer to client instance structure.
440 * @param pszQuery Command request line to be sent to server,
441 * must be cr/lf and null terminated.
442 *
443 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
444 */
445 lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
446 {
447 lscp_status_t ret;
448
449 // Lock this section up.
450 lscp_mutex_lock(pClient->mutex);
451
452 // Just make the now guarded call.
453 ret = lscp_client_call(pClient, pszQuery);
454
455 // Unlock this section down.
456 lscp_mutex_unlock(pClient->mutex);
457
458 return ret;
459 }
460
461 /**
462 * Get the last received result string. In case of error or warning,
463 * this is the text of the error or warning message issued.
464 *
465 * @param pClient Pointer to client instance structure.
466 *
467 * @returns A pointer to the literal null-terminated result string as
468 * of the last command request.
469 */
470 const char *lscp_client_get_result ( lscp_client_t *pClient )
471 {
472 if (pClient == NULL)
473 return NULL;
474
475 return pClient->pszResult;
476 }
477
478
479 /**
480 * Get the last error/warning number received.
481 *
482 * @param pClient Pointer to client instance structure.
483 *
484 * @returns The numerical value of the last error or warning
485 * response code received.
486 */
487 int lscp_client_get_errno ( lscp_client_t *pClient )
488 {
489 if (pClient == NULL)
490 return -1;
491
492 return pClient->iErrno;
493 }
494
495
496 //-------------------------------------------------------------------------
497 // Client registration protocol functions.
498
499 /**
500 * Register frontend for receiving event messages:
501 * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
502 * | CHANNEL_INFO | MISCELLANEOUS
503 *
504 * @param pClient Pointer to client instance structure.
505 * @param events Bit-wise OR'ed event flags to subscribe.
506 *
507 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
508 */
509 lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
510 {
511 lscp_status_t ret = LSCP_FAILED;
512
513 if (pClient == NULL)
514 return LSCP_FAILED;
515
516 // Lock this section up.
517 lscp_mutex_lock(pClient->mutex);
518
519 // If applicable, start the alternate connection...
520 if (pClient->events == LSCP_EVENT_NONE)
521 ret = _lscp_client_evt_connect(pClient);
522
523 // Send the subscription commands.
524 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS))
525 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNELS);
526 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
527 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
528 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
529 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
530 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
531 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
532 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
533 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
534 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
535 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
536
537 // Unlock this section down.
538 lscp_mutex_unlock(pClient->mutex);
539
540 return ret;
541 }
542
543
544 /**
545 * Deregister frontend from receiving UDP event messages anymore:
546 * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
547 * | CHANNEL_INFO | MISCELLANEOUS
548 *
549 * @param pClient Pointer to client instance structure.
550 * @param events Bit-wise OR'ed event flags to unsubscribe.
551 *
552 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
553 */
554 lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
555 {
556 lscp_status_t ret = LSCP_OK;
557
558 if (pClient == NULL)
559 return LSCP_FAILED;
560
561 // Lock this section up.
562 lscp_mutex_lock(pClient->mutex);
563
564 // Send the unsubscription commands.
565 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS))
566 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNELS);
567 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
568 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
569 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
570 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
571 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
572 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
573 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
574 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
575 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
576 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
577
578 // If necessary, close the alternate connection...
579 if (pClient->events == LSCP_EVENT_NONE)
580 lscp_socket_agent_free(&(pClient->evt));
581
582 // Unlock this section down.
583 lscp_mutex_unlock(pClient->mutex);
584
585 return ret;
586 }
587
588
589 //-------------------------------------------------------------------------
590 // Client command protocol functions.
591
592 /**
593 * Loading an instrument:
594 * LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
595 *
596 * @param pClient Pointer to client instance structure.
597 * @param pszFileName Instrument file name.
598 * @param iInstrIndex Instrument index number.
599 * @param iSamplerChannel Sampler Channel.
600 *
601 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
602 */
603 lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
604 {
605 char szQuery[LSCP_BUFSIZ];
606
607 if (pszFileName == NULL || iSamplerChannel < 0)
608 return LSCP_FAILED;
609
610 sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
611 return lscp_client_query(pClient, szQuery);
612 }
613
614
615 /**
616 * Loading an instrument in the background (non modal):
617 * LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
618 *
619 * @param pClient Pointer to client instance structure.
620 * @param pszFileName Instrument file name.
621 * @param iInstrIndex Instrument index number.
622 * @param iSamplerChannel Sampler Channel.
623 *
624 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
625 */
626 lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
627 {
628 char szQuery[LSCP_BUFSIZ];
629
630 if (pszFileName == NULL || iSamplerChannel < 0)
631 return LSCP_FAILED;
632
633 sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
634 return lscp_client_query(pClient, szQuery);
635 }
636
637
638 /**
639 * Loading a sampler engine:
640 * LOAD ENGINE <engine-name> <sampler-channel>
641 *
642 * @param pClient Pointer to client instance structure.
643 * @param pszEngineName Engine name.
644 * @param iSamplerChannel Sampler channel number.
645 *
646 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
647 */
648 lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
649 {
650 char szQuery[LSCP_BUFSIZ];
651
652 if (pszEngineName == NULL || iSamplerChannel < 0)
653 return LSCP_FAILED;
654
655 sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);
656 return lscp_client_query(pClient, szQuery);
657 }
658
659
660 /**
661 * Current number of sampler channels:
662 * GET CHANNELS
663 *
664 * @param pClient Pointer to client instance structure.
665 *
666 * @returns The current total number of sampler channels on success,
667 * -1 otherwise.
668 */
669 int lscp_get_channels ( lscp_client_t *pClient )
670 {
671 int iChannels = -1;
672
673 // Lock this section up.
674 lscp_mutex_lock(pClient->mutex);
675
676 if (lscp_client_call(pClient, "GET CHANNELS\r\n") == LSCP_OK)
677 iChannels = atoi(lscp_client_get_result(pClient));
678
679 // Unlock this section doen.
680 lscp_mutex_unlock(pClient->mutex);
681
682 return iChannels;
683 }
684
685
686 /**
687 * List current sampler channels number identifiers:
688 * LIST CHANNELS
689 *
690 * @param pClient Pointer to client instance structure.
691 *
692 * @returns An array of the sampler channels identifiers as positive integers,
693 * terminated with -1 on success, NULL otherwise.
694 */
695 int *lscp_list_channels ( lscp_client_t *pClient )
696 {
697 const char *pszSeps = ",";
698
699 if (pClient == NULL)
700 return NULL;
701
702 // Lock this section up.
703 lscp_mutex_lock(pClient->mutex);
704
705 if (pClient->channels) {
706 lscp_isplit_destroy(pClient->channels);
707 pClient->channels = NULL;
708 }
709
710 if (lscp_client_call(pClient, "LIST CHANNELS\r\n") == LSCP_OK)
711 pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
712
713 // Unlock this section down.
714 lscp_mutex_unlock(pClient->mutex);
715
716 return pClient->channels;
717 }
718
719
720 /**
721 * Adding a new sampler channel:
722 * ADD CHANNEL
723 *
724 * @param pClient Pointer to client instance structure.
725 *
726 * @returns The new sampler channel number identifier,
727 * or -1 in case of failure.
728 */
729 int lscp_add_channel ( lscp_client_t *pClient )
730 {
731 int iSamplerChannel = -1;
732
733 // Lock this section up.
734 lscp_mutex_lock(pClient->mutex);
735
736 if (lscp_client_call(pClient, "ADD CHANNEL\r\n") == LSCP_OK)
737 iSamplerChannel = atoi(lscp_client_get_result(pClient));
738
739 // Unlock this section down.
740 lscp_mutex_unlock(pClient->mutex);
741
742 return iSamplerChannel;
743 }
744
745
746 /**
747 * Removing a sampler channel:
748 * REMOVE CHANNEL <sampler-channel>
749 *
750 * @param pClient Pointer to client instance structure.
751 * @param iSamplerChannel Sampler channel number.
752 *
753 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
754 */
755 lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
756 {
757 char szQuery[LSCP_BUFSIZ];
758
759 if (iSamplerChannel < 0)
760 return LSCP_FAILED;
761
762 sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
763 return lscp_client_query(pClient, szQuery);
764 }
765
766
767 /**
768 * Getting all available engines:
769 * GET AVAILABLE_ENGINES
770 *
771 * @param pClient Pointer to client instance structure.
772 *
773 * @returns A NULL terminated array of engine name strings,
774 * or NULL in case of failure.
775 */
776 const char **lscp_get_available_engines ( lscp_client_t *pClient )
777 {
778 const char *pszSeps = ",";
779
780 // Lock this section up.
781 lscp_mutex_lock(pClient->mutex);
782
783 if (pClient->engines) {
784 lscp_szsplit_destroy(pClient->engines);
785 pClient->engines = NULL;
786 }
787
788 if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n") == LSCP_OK)
789 pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
790
791 // Unlock this section down.
792 lscp_mutex_unlock(pClient->mutex);
793
794 return (const char **) pClient->engines;
795 }
796
797
798 /**
799 * Getting information about an engine.
800 * GET ENGINE INFO <engine-name>
801 *
802 * @param pClient Pointer to client instance structure.
803 * @param pszEngineName Engine name.
804 *
805 * @returns A pointer to a @ref lscp_engine_info_t structure, with all the
806 * information of the given sampler engine, or NULL in case of failure.
807 */
808 lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )
809 {
810 lscp_engine_info_t *pEngineInfo;
811 char szQuery[LSCP_BUFSIZ];
812 const char *pszResult;
813 const char *pszSeps = ":";
814 const char *pszCrlf = "\r\n";
815 char *pszToken;
816 char *pch;
817
818 if (pszEngineName == NULL)
819 return NULL;
820
821 // Lock this section up.
822 lscp_mutex_lock(pClient->mutex);
823
824 pEngineInfo = &(pClient->engine_info);
825 lscp_engine_info_reset(pEngineInfo);
826
827 sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
828 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
829 pszResult = lscp_client_get_result(pClient);
830 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
831 while (pszToken) {
832 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
833 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
834 if (pszToken)
835 pEngineInfo->description = lscp_unquote(&pszToken, 1);
836 }
837 else if (strcasecmp(pszToken, "VERSION") == 0) {
838 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
839 if (pszToken)
840 pEngineInfo->version = lscp_unquote(&pszToken, 1);
841 }
842 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
843 }
844 }
845 else pEngineInfo = NULL;
846
847 // Unlock this section down.
848 lscp_mutex_unlock(pClient->mutex);
849
850 return pEngineInfo;
851 }
852
853
854 /**
855 * Getting sampler channel informations:
856 * GET CHANNEL INFO <sampler-channel>
857 *
858 * @param pClient Pointer to client instance structure.
859 * @param iSamplerChannel Sampler channel number.
860 *
861 * @returns A pointer to a @ref lscp_channel_info_t structure, with all the
862 * information of the given sampler channel, or NULL in case of failure.
863 */
864 lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
865 {
866 lscp_channel_info_t *pChannelInfo;
867 char szQuery[LSCP_BUFSIZ];
868 const char *pszResult;
869 const char *pszSeps = ":";
870 const char *pszCrlf = "\r\n";
871 char *pszToken;
872 char *pch;
873
874 if (iSamplerChannel < 0)
875 return NULL;
876
877 // Lock this section up.
878 lscp_mutex_lock(pClient->mutex);
879
880 pChannelInfo = &(pClient->channel_info);
881 lscp_channel_info_reset(pChannelInfo);
882
883 sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
884 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
885 pszResult = lscp_client_get_result(pClient);
886 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
887 while (pszToken) {
888 if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
889 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
890 if (pszToken)
891 pChannelInfo->engine_name = lscp_unquote(&pszToken, 1);
892 }
893 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
894 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
895 if (pszToken)
896 pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
897 }
898 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
899 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
900 if (pszToken)
901 pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
902 }
903 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
904 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
905 if (pszToken)
906 pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");
907 }
908 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
909 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
910 if (pszToken)
911 pChannelInfo->instrument_file = lscp_unquote(&pszToken, 1);
912 }
913 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
914 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
915 if (pszToken)
916 pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
917 }
918 else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
919 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
920 if (pszToken)
921 pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
922 }
923 else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
924 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
925 if (pszToken)
926 pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
927 }
928 else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
929 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
930 if (pszToken)
931 pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
932 }
933 else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
934 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
935 if (pszToken)
936 pChannelInfo->midi_channel = atoi(lscp_ltrim(pszToken));
937 }
938 else if (strcasecmp(pszToken, "VOLUME") == 0) {
939 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
940 if (pszToken)
941 pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));
942 }
943 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
944 }
945 }
946 else pChannelInfo = NULL;
947
948 // Unlock this section up.
949 lscp_mutex_unlock(pClient->mutex);
950
951 return pChannelInfo;
952 }
953
954
955 /**
956 * Current number of active voices:
957 * GET CHANNEL VOICE_COUNT <sampler-channel>
958 *
959 * @param pClient Pointer to client instance structure.
960 * @param iSamplerChannel Sampler channel number.
961 *
962 * @returns The number of voices currently active, -1 in case of failure.
963 */
964 int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
965 {
966 char szQuery[LSCP_BUFSIZ];
967 int iVoiceCount = -1;
968
969 if (iSamplerChannel < 0)
970 return iVoiceCount;
971
972 // Lock this section up.
973 lscp_mutex_lock(pClient->mutex);
974
975 sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
976 if (lscp_client_call(pClient, szQuery) == LSCP_OK)
977 iVoiceCount = atoi(lscp_client_get_result(pClient));
978
979 // Unlock this section down.
980 lscp_mutex_unlock(pClient->mutex);
981
982 return iVoiceCount;
983 }
984
985
986 /**
987 * Current number of active disk streams:
988 * GET CHANNEL STREAM_COUNT <sampler-channel>
989 *
990 * @returns The number of active disk streams on success, -1 otherwise.
991 */
992 int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
993 {
994 char szQuery[LSCP_BUFSIZ];
995 int iStreamCount = -1;
996
997 if (iSamplerChannel < 0)
998 return iStreamCount;
999
1000 // Lock this section up.
1001 lscp_mutex_lock(pClient->mutex);
1002
1003 sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1004 if (lscp_client_call(pClient, szQuery) == LSCP_OK)
1005 iStreamCount = atoi(lscp_client_get_result(pClient));
1006
1007 // Unlock this section down.
1008 lscp_mutex_unlock(pClient->mutex);
1009
1010 return iStreamCount;
1011 }
1012
1013
1014 /**
1015 * Current fill state of disk stream buffers:
1016 * GET CHANNEL BUFFER_FILL {BYTES|PERCENTAGE} <sampler-channel>
1017 *
1018 * @param pClient Pointer to client instance structure.
1019 * @param usage_type Usage type to be returned, either
1020 * @ref LSCP_USAGE_BYTES, or
1021 * @ref LSCP_USAGE_PERCENTAGE.
1022 * @param iSamplerChannel Sampler channel number.
1023 *
1024 * @returns A pointer to a @ref lscp_buffer_fill_t structure, with the
1025 * information of the current disk stream buffer fill usage, for the given
1026 * sampler channel, or NULL in case of failure.
1027 */
1028 lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )
1029 {
1030 lscp_buffer_fill_t *pBufferFill;
1031 char szQuery[LSCP_BUFSIZ];
1032 int iStreamCount;
1033 const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1034 const char *pszResult;
1035 const char *pszSeps = "[]%,";
1036 char *pszToken;
1037 char *pch;
1038 int iStream;
1039
1040 // Retrieve a channel stream estimation.
1041 iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1042 if (pClient->iStreamCount < 0)
1043 return NULL;
1044
1045 // Lock this section up.
1046 lscp_mutex_lock(pClient->mutex);
1047
1048 // Check if we need to reallocate the stream usage array.
1049 if (pClient->iStreamCount != iStreamCount) {
1050 if (pClient->buffer_fill)
1051 free(pClient->buffer_fill);
1052 if (iStreamCount > 0)
1053 pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1054 else
1055 pClient->buffer_fill = NULL;
1056 pClient->iStreamCount = iStreamCount;
1057 }
1058
1059 // Get buffer fill usage...
1060 pBufferFill = pClient->buffer_fill;
1061 if (pBufferFill && iStreamCount > 0) {
1062 iStream = 0;
1063 pBufferFill = pClient->buffer_fill;
1064 sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1065 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
1066 pszResult = lscp_client_get_result(pClient);
1067 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1068 while (pszToken && iStream < pClient->iStreamCount) {
1069 if (*pszToken) {
1070 pBufferFill[iStream].stream_id = atol(pszToken);
1071 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1072 if (pszToken == NULL)
1073 break;
1074 pBufferFill[iStream].stream_usage = atol(pszToken);
1075 iStream++;
1076 }
1077 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1078 }
1079 } // Reset the usage, whatever it was before.
1080 else while (iStream < pClient->iStreamCount)
1081 pBufferFill[iStream++].stream_usage = 0;
1082 }
1083
1084 // Unlock this section down.
1085 lscp_mutex_unlock(pClient->mutex);
1086
1087 return pBufferFill;
1088 }
1089
1090
1091 /**
1092 * Setting audio output type:
1093 * SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
1094 *
1095 * @param pClient Pointer to client instance structure.
1096 * @param iSamplerChannel Sampler channel number.
1097 * @param pszAudioDriver Audio output driver type (e.g. "ALSA" or "JACK").
1098 */
1099 lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )
1100 {
1101 char szQuery[LSCP_BUFSIZ];
1102
1103 if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1104 return LSCP_FAILED;
1105
1106 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);
1107 return lscp_client_query(pClient, szQuery);
1108 }
1109
1110
1111 /**
1112 * Setting audio output device:
1113 * SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1114 *
1115 * @param pClient Pointer to client instance structure.
1116 * @param iSamplerChannel Sampler channel number.
1117 * @param iAudioDevice Audio output device number identifier.
1118 */
1119 lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )
1120 {
1121 char szQuery[LSCP_BUFSIZ];
1122
1123 if (iSamplerChannel < 0 || iAudioDevice < 0)
1124 return LSCP_FAILED;
1125
1126 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);
1127 return lscp_client_query(pClient, szQuery);
1128 }
1129
1130
1131 /**
1132 * Setting audio output channel:
1133 * SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-output-chan> <audio-input-chan>
1134 *
1135 * @param pClient Pointer to client instance structure.
1136 * @param iSamplerChannel Sampler channel number.
1137 * @param iAudioOut Audio output device channel to be routed from.
1138 * @param iAudioIn Audio output device channel to be routed into.
1139 *
1140 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1141 */
1142 lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )
1143 {
1144 char szQuery[LSCP_BUFSIZ];
1145
1146 if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1147 return LSCP_FAILED;
1148
1149 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNELS %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);
1150 return lscp_client_query(pClient, szQuery);
1151 }
1152
1153
1154 /**
1155 * Setting MIDI input type:
1156 * SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
1157 *
1158 * @param pClient Pointer to client instance structure.
1159 * @param iSamplerChannel Sampler channel number.
1160 * @param pszMidiDriver MIDI input driver type (e.g. "ALSA").
1161 *
1162 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1163 */
1164 lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )
1165 {
1166 char szQuery[LSCP_BUFSIZ];
1167
1168 if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1169 return LSCP_FAILED;
1170
1171 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);
1172 return lscp_client_query(pClient, szQuery);
1173 }
1174
1175
1176 /**
1177 * Setting MIDI input device:
1178 * SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1179 *
1180 * @param pClient Pointer to client instance structure.
1181 * @param iSamplerChannel Sampler channel number.
1182 * @param iMidiDevice MIDI input device number identifier.
1183 */
1184 lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )
1185 {
1186 char szQuery[LSCP_BUFSIZ];
1187
1188 if (iSamplerChannel < 0 || iMidiDevice < 0)
1189 return LSCP_FAILED;
1190
1191 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);
1192 return lscp_client_query(pClient, szQuery);
1193 }
1194
1195
1196 /**
1197 * Setting MIDI input port:
1198 * SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
1199 *
1200 * @param pClient Pointer to client instance structure.
1201 * @param iSamplerChannel Sampler channel number.
1202 * @param iMidiPort MIDI input driver virtual port number.
1203 *
1204 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1205 */
1206 lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )
1207 {
1208 char szQuery[LSCP_BUFSIZ];
1209
1210 if (iSamplerChannel < 0 || iMidiPort < 0)
1211 return LSCP_FAILED;
1212
1213 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);
1214 return lscp_client_query(pClient, szQuery);
1215 }
1216
1217
1218 /**
1219 * Setting MIDI input channel:
1220 * SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
1221 *
1222 * @param pClient Pointer to client instance structure.
1223 * @param iSamplerChannel Sampler channel number.
1224 * @param iMidiChannel MIDI channel number to listen (1-16) or
1225 * zero (0) to listen on all channels.
1226 *
1227 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1228 */
1229 lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )
1230 {
1231 char szQuery[LSCP_BUFSIZ];
1232
1233 if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1234 return LSCP_FAILED;
1235
1236 if (iMidiChannel > 0)
1237 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);
1238 else
1239 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);
1240 return lscp_client_query(pClient, szQuery);
1241 }
1242
1243
1244 /**
1245 * Setting channel volume:
1246 * SET CHANNEL VOLUME <sampler-channel> <volume>
1247 *
1248 * @param pClient Pointer to client instance structure.
1249 * @param iSamplerChannel Sampler channel number.
1250 * @param fVolume Sampler channel volume as a positive floating point
1251 * number, where a value less than 1.0 for attenuation,
1252 * and greater than 1.0 for amplification.
1253 *
1254 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1255 */
1256 lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )
1257 {
1258 char szQuery[LSCP_BUFSIZ];
1259
1260 if (iSamplerChannel < 0 || fVolume < 0.0)
1261 return LSCP_FAILED;
1262
1263 sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);
1264 return lscp_client_query(pClient, szQuery);
1265 }
1266
1267
1268 /**
1269 * Resetting a sampler channel:
1270 * RESET CHANNEL <sampler-channel>
1271 *
1272 * @param pClient Pointer to client instance structure.
1273 * @param iSamplerChannel Sampler channel number.
1274 *
1275 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1276 */
1277 lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1278 {
1279 char szQuery[LSCP_BUFSIZ];
1280
1281 if (iSamplerChannel < 0)
1282 return LSCP_FAILED;
1283
1284 sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1285 return lscp_client_query(pClient, szQuery);
1286 }
1287
1288
1289 // end of client.c

  ViewVC Help
Powered by ViewVC