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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 163 - (show annotations) (download)
Wed Jun 30 15:16:03 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 41996 byte(s)
Driver parameter info wrapper implementation.

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_param_info_init(&(pClient->audio_param_info));
296 lscp_param_info_init(&(pClient->midi_param_info));
297 lscp_engine_info_init(&(pClient->engine_info));
298 lscp_channel_info_init(&(pClient->channel_info));
299 // Initialize error stuff.
300 pClient->pszResult = NULL;
301 pClient->iErrno = -1;
302 // Stream usage stuff.
303 pClient->buffer_fill = NULL;
304 pClient->iStreamCount = 0;
305 // Default timeout value.
306 pClient->iTimeout = LSCP_TIMEOUT_MSECS;
307
308 // Initialize the transaction mutex.
309 lscp_mutex_init(pClient->mutex);
310
311 // Finally we've some success...
312 return pClient;
313 }
314
315
316 /**
317 * Wait for a client instance to terminate graciously.
318 *
319 * @param pClient Pointer to client instance structure.
320 */
321 lscp_status_t lscp_client_join ( lscp_client_t *pClient )
322 {
323 if (pClient == NULL)
324 return LSCP_FAILED;
325
326 #ifdef DEBUG
327 fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
328 #endif
329
330 // lscp_socket_agent_join(&(pClient->evt));
331 lscp_socket_agent_join(&(pClient->cmd));
332
333 return LSCP_OK;
334 }
335
336
337 /**
338 * Terminate and destroy a client instance.
339 *
340 * @param pClient Pointer to client instance structure.
341 *
342 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
343 */
344 lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
345 {
346 if (pClient == NULL)
347 return LSCP_FAILED;
348
349 #ifdef DEBUG
350 fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
351 #endif
352
353 // Lock this section up.
354 lscp_mutex_lock(pClient->mutex);
355
356 // Free up all cached members.
357 lscp_channel_info_reset(&(pClient->channel_info));
358 lscp_engine_info_reset(&(pClient->engine_info));
359 lscp_param_info_reset(&(pClient->midi_param_info));
360 lscp_param_info_reset(&(pClient->audio_param_info));
361 lscp_driver_info_reset(&(pClient->midi_info));
362 lscp_driver_info_reset(&(pClient->audio_info));
363 // Free available engine table.
364 lscp_szsplit_destroy(pClient->audio_drivers);
365 lscp_szsplit_destroy(pClient->midi_drivers);
366 lscp_isplit_destroy(pClient->audio_devices);
367 lscp_isplit_destroy(pClient->midi_devices);
368 lscp_szsplit_destroy(pClient->engines);
369 lscp_isplit_destroy(pClient->channels);
370 // Make them null.
371 pClient->audio_drivers = NULL;
372 pClient->midi_drivers = NULL;
373 pClient->engines = NULL;
374 // Free result error stuff.
375 lscp_client_set_result(pClient, NULL, 0);
376 // Frre stream usage stuff.
377 if (pClient->buffer_fill)
378 free(pClient->buffer_fill);
379 pClient->buffer_fill = NULL;
380 pClient->iStreamCount = 0;
381 pClient->iTimeout = 0;
382
383 // Free socket agents.
384 lscp_socket_agent_free(&(pClient->evt));
385 lscp_socket_agent_free(&(pClient->cmd));
386
387 // Last but not least, free good ol'transaction mutex.
388 lscp_mutex_unlock(pClient->mutex);
389 lscp_mutex_destroy(pClient->mutex);
390
391 free(pClient);
392
393 return LSCP_OK;
394 }
395
396
397 /**
398 * Set the client transaction timeout interval.
399 *
400 * @param pClient Pointer to client instance structure.
401 * @param iTimeout Transaction timeout in milliseconds.
402 *
403 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
404 */
405 lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
406 {
407 if (pClient == NULL)
408 return LSCP_FAILED;
409 if (iTimeout < 0)
410 return LSCP_FAILED;
411
412 pClient->iTimeout = iTimeout;
413 return LSCP_OK;
414 }
415
416
417 /**
418 * Get the client transaction timeout interval.
419 *
420 * @param pClient Pointer to client instance structure.
421 *
422 * @returns The current timeout value milliseconds, -1 in case of failure.
423 */
424 int lscp_client_get_timeout ( lscp_client_t *pClient )
425 {
426 if (pClient == NULL)
427 return -1;
428
429 return pClient->iTimeout;
430 }
431
432
433 //-------------------------------------------------------------------------
434 // Client common protocol functions.
435
436 /**
437 * Submit a command query line string to the server. The query string
438 * must be cr/lf and null terminated. Besides the return code, the
439 * specific server response to the command request is made available
440 * by the @ref lscp_client_get_result and @ref lscp_client_get_errno
441 * function calls.
442 *
443 * @param pClient Pointer to client instance structure.
444 * @param pszQuery Command request line to be sent to server,
445 * must be cr/lf and null terminated.
446 *
447 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
448 */
449 lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
450 {
451 lscp_status_t ret;
452
453 // Lock this section up.
454 lscp_mutex_lock(pClient->mutex);
455
456 // Just make the now guarded call.
457 ret = lscp_client_call(pClient, pszQuery);
458
459 // Unlock this section down.
460 lscp_mutex_unlock(pClient->mutex);
461
462 return ret;
463 }
464
465 /**
466 * Get the last received result string. In case of error or warning,
467 * this is the text of the error or warning message issued.
468 *
469 * @param pClient Pointer to client instance structure.
470 *
471 * @returns A pointer to the literal null-terminated result string as
472 * of the last command request.
473 */
474 const char *lscp_client_get_result ( lscp_client_t *pClient )
475 {
476 if (pClient == NULL)
477 return NULL;
478
479 return pClient->pszResult;
480 }
481
482
483 /**
484 * Get the last error/warning number received.
485 *
486 * @param pClient Pointer to client instance structure.
487 *
488 * @returns The numerical value of the last error or warning
489 * response code received.
490 */
491 int lscp_client_get_errno ( lscp_client_t *pClient )
492 {
493 if (pClient == NULL)
494 return -1;
495
496 return pClient->iErrno;
497 }
498
499
500 //-------------------------------------------------------------------------
501 // Client registration protocol functions.
502
503 /**
504 * Register frontend for receiving event messages:
505 * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
506 * | CHANNEL_INFO | MISCELLANEOUS
507 *
508 * @param pClient Pointer to client instance structure.
509 * @param events Bit-wise OR'ed event flags to subscribe.
510 *
511 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
512 */
513 lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
514 {
515 lscp_status_t ret = LSCP_FAILED;
516
517 if (pClient == NULL)
518 return LSCP_FAILED;
519
520 // Lock this section up.
521 lscp_mutex_lock(pClient->mutex);
522
523 // If applicable, start the alternate connection...
524 if (pClient->events == LSCP_EVENT_NONE)
525 ret = _lscp_client_evt_connect(pClient);
526
527 // Send the subscription commands.
528 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS))
529 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNELS);
530 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
531 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
532 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
533 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
534 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
535 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
536 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
537 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
538 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
539 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
540
541 // Unlock this section down.
542 lscp_mutex_unlock(pClient->mutex);
543
544 return ret;
545 }
546
547
548 /**
549 * Deregister frontend from receiving UDP event messages anymore:
550 * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
551 * | CHANNEL_INFO | MISCELLANEOUS
552 *
553 * @param pClient Pointer to client instance structure.
554 * @param events Bit-wise OR'ed event flags to unsubscribe.
555 *
556 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
557 */
558 lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
559 {
560 lscp_status_t ret = LSCP_OK;
561
562 if (pClient == NULL)
563 return LSCP_FAILED;
564
565 // Lock this section up.
566 lscp_mutex_lock(pClient->mutex);
567
568 // Send the unsubscription commands.
569 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS))
570 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNELS);
571 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
572 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
573 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
574 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
575 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
576 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
577 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
578 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
579 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
580 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
581
582 // If necessary, close the alternate connection...
583 if (pClient->events == LSCP_EVENT_NONE)
584 lscp_socket_agent_free(&(pClient->evt));
585
586 // Unlock this section down.
587 lscp_mutex_unlock(pClient->mutex);
588
589 return ret;
590 }
591
592
593 //-------------------------------------------------------------------------
594 // Client command protocol functions.
595
596 /**
597 * Loading an instrument:
598 * LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
599 *
600 * @param pClient Pointer to client instance structure.
601 * @param pszFileName Instrument file name.
602 * @param iInstrIndex Instrument index number.
603 * @param iSamplerChannel Sampler Channel.
604 *
605 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
606 */
607 lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
608 {
609 char szQuery[LSCP_BUFSIZ];
610
611 if (pszFileName == NULL || iSamplerChannel < 0)
612 return LSCP_FAILED;
613
614 sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
615 return lscp_client_query(pClient, szQuery);
616 }
617
618
619 /**
620 * Loading an instrument in the background (non modal):
621 * LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
622 *
623 * @param pClient Pointer to client instance structure.
624 * @param pszFileName Instrument file name.
625 * @param iInstrIndex Instrument index number.
626 * @param iSamplerChannel Sampler Channel.
627 *
628 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
629 */
630 lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
631 {
632 char szQuery[LSCP_BUFSIZ];
633
634 if (pszFileName == NULL || iSamplerChannel < 0)
635 return LSCP_FAILED;
636
637 sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
638 return lscp_client_query(pClient, szQuery);
639 }
640
641
642 /**
643 * Loading a sampler engine:
644 * LOAD ENGINE <engine-name> <sampler-channel>
645 *
646 * @param pClient Pointer to client instance structure.
647 * @param pszEngineName Engine name.
648 * @param iSamplerChannel Sampler channel number.
649 *
650 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
651 */
652 lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
653 {
654 char szQuery[LSCP_BUFSIZ];
655
656 if (pszEngineName == NULL || iSamplerChannel < 0)
657 return LSCP_FAILED;
658
659 sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);
660 return lscp_client_query(pClient, szQuery);
661 }
662
663
664 /**
665 * Current number of sampler channels:
666 * GET CHANNELS
667 *
668 * @param pClient Pointer to client instance structure.
669 *
670 * @returns The current total number of sampler channels on success,
671 * -1 otherwise.
672 */
673 int lscp_get_channels ( lscp_client_t *pClient )
674 {
675 int iChannels = -1;
676
677 // Lock this section up.
678 lscp_mutex_lock(pClient->mutex);
679
680 if (lscp_client_call(pClient, "GET CHANNELS\r\n") == LSCP_OK)
681 iChannels = atoi(lscp_client_get_result(pClient));
682
683 // Unlock this section doen.
684 lscp_mutex_unlock(pClient->mutex);
685
686 return iChannels;
687 }
688
689
690 /**
691 * List current sampler channels number identifiers:
692 * LIST CHANNELS
693 *
694 * @param pClient Pointer to client instance structure.
695 *
696 * @returns An array of the sampler channels identifiers as positive integers,
697 * terminated with -1 on success, NULL otherwise.
698 */
699 int *lscp_list_channels ( lscp_client_t *pClient )
700 {
701 const char *pszSeps = ",";
702
703 if (pClient == NULL)
704 return NULL;
705
706 // Lock this section up.
707 lscp_mutex_lock(pClient->mutex);
708
709 if (pClient->channels) {
710 lscp_isplit_destroy(pClient->channels);
711 pClient->channels = NULL;
712 }
713
714 if (lscp_client_call(pClient, "LIST CHANNELS\r\n") == LSCP_OK)
715 pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
716
717 // Unlock this section down.
718 lscp_mutex_unlock(pClient->mutex);
719
720 return pClient->channels;
721 }
722
723
724 /**
725 * Adding a new sampler channel:
726 * ADD CHANNEL
727 *
728 * @param pClient Pointer to client instance structure.
729 *
730 * @returns The new sampler channel number identifier,
731 * or -1 in case of failure.
732 */
733 int lscp_add_channel ( lscp_client_t *pClient )
734 {
735 int iSamplerChannel = -1;
736
737 // Lock this section up.
738 lscp_mutex_lock(pClient->mutex);
739
740 if (lscp_client_call(pClient, "ADD CHANNEL\r\n") == LSCP_OK)
741 iSamplerChannel = atoi(lscp_client_get_result(pClient));
742
743 // Unlock this section down.
744 lscp_mutex_unlock(pClient->mutex);
745
746 return iSamplerChannel;
747 }
748
749
750 /**
751 * Removing a sampler channel:
752 * REMOVE CHANNEL <sampler-channel>
753 *
754 * @param pClient Pointer to client instance structure.
755 * @param iSamplerChannel Sampler channel number.
756 *
757 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
758 */
759 lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
760 {
761 char szQuery[LSCP_BUFSIZ];
762
763 if (iSamplerChannel < 0)
764 return LSCP_FAILED;
765
766 sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
767 return lscp_client_query(pClient, szQuery);
768 }
769
770
771 /**
772 * Getting all available engines:
773 * GET AVAILABLE_ENGINES
774 *
775 * @param pClient Pointer to client instance structure.
776 *
777 * @returns A NULL terminated array of engine name strings,
778 * or NULL in case of failure.
779 */
780 const char **lscp_get_available_engines ( lscp_client_t *pClient )
781 {
782 const char *pszSeps = ",";
783
784 // Lock this section up.
785 lscp_mutex_lock(pClient->mutex);
786
787 if (pClient->engines) {
788 lscp_szsplit_destroy(pClient->engines);
789 pClient->engines = NULL;
790 }
791
792 if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n") == LSCP_OK)
793 pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
794
795 // Unlock this section down.
796 lscp_mutex_unlock(pClient->mutex);
797
798 return (const char **) pClient->engines;
799 }
800
801
802 /**
803 * Getting information about an engine.
804 * GET ENGINE INFO <engine-name>
805 *
806 * @param pClient Pointer to client instance structure.
807 * @param pszEngineName Engine name.
808 *
809 * @returns A pointer to a @ref lscp_engine_info_t structure, with all the
810 * information of the given sampler engine, or NULL in case of failure.
811 */
812 lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )
813 {
814 lscp_engine_info_t *pEngineInfo;
815 char szQuery[LSCP_BUFSIZ];
816 const char *pszResult;
817 const char *pszSeps = ":";
818 const char *pszCrlf = "\r\n";
819 char *pszToken;
820 char *pch;
821
822 if (pszEngineName == NULL)
823 return NULL;
824
825 // Lock this section up.
826 lscp_mutex_lock(pClient->mutex);
827
828 pEngineInfo = &(pClient->engine_info);
829 lscp_engine_info_reset(pEngineInfo);
830
831 sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
832 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
833 pszResult = lscp_client_get_result(pClient);
834 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
835 while (pszToken) {
836 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
837 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
838 if (pszToken)
839 pEngineInfo->description = lscp_unquote(&pszToken, 1);
840 }
841 else if (strcasecmp(pszToken, "VERSION") == 0) {
842 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
843 if (pszToken)
844 pEngineInfo->version = lscp_unquote(&pszToken, 1);
845 }
846 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
847 }
848 }
849 else pEngineInfo = NULL;
850
851 // Unlock this section down.
852 lscp_mutex_unlock(pClient->mutex);
853
854 return pEngineInfo;
855 }
856
857
858 /**
859 * Getting sampler channel informations:
860 * GET CHANNEL INFO <sampler-channel>
861 *
862 * @param pClient Pointer to client instance structure.
863 * @param iSamplerChannel Sampler channel number.
864 *
865 * @returns A pointer to a @ref lscp_channel_info_t structure, with all the
866 * information of the given sampler channel, or NULL in case of failure.
867 */
868 lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
869 {
870 lscp_channel_info_t *pChannelInfo;
871 char szQuery[LSCP_BUFSIZ];
872 const char *pszResult;
873 const char *pszSeps = ":";
874 const char *pszCrlf = "\r\n";
875 char *pszToken;
876 char *pch;
877
878 if (iSamplerChannel < 0)
879 return NULL;
880
881 // Lock this section up.
882 lscp_mutex_lock(pClient->mutex);
883
884 pChannelInfo = &(pClient->channel_info);
885 lscp_channel_info_reset(pChannelInfo);
886
887 sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
888 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
889 pszResult = lscp_client_get_result(pClient);
890 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
891 while (pszToken) {
892 if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
893 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
894 if (pszToken)
895 pChannelInfo->engine_name = lscp_unquote(&pszToken, 1);
896 }
897 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
898 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
899 if (pszToken)
900 pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
901 }
902 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
903 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
904 if (pszToken)
905 pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
906 }
907 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
908 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
909 if (pszToken)
910 pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");
911 }
912 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
913 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
914 if (pszToken)
915 pChannelInfo->instrument_file = lscp_unquote(&pszToken, 1);
916 }
917 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
918 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
919 if (pszToken)
920 pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
921 }
922 else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
923 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
924 if (pszToken)
925 pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
926 }
927 else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
928 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
929 if (pszToken)
930 pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
931 }
932 else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
933 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
934 if (pszToken)
935 pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
936 }
937 else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
938 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
939 if (pszToken)
940 pChannelInfo->midi_channel = atoi(lscp_ltrim(pszToken));
941 }
942 else if (strcasecmp(pszToken, "VOLUME") == 0) {
943 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
944 if (pszToken)
945 pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));
946 }
947 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
948 }
949 }
950 else pChannelInfo = NULL;
951
952 // Unlock this section up.
953 lscp_mutex_unlock(pClient->mutex);
954
955 return pChannelInfo;
956 }
957
958
959 /**
960 * Current number of active voices:
961 * GET CHANNEL VOICE_COUNT <sampler-channel>
962 *
963 * @param pClient Pointer to client instance structure.
964 * @param iSamplerChannel Sampler channel number.
965 *
966 * @returns The number of voices currently active, -1 in case of failure.
967 */
968 int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
969 {
970 char szQuery[LSCP_BUFSIZ];
971 int iVoiceCount = -1;
972
973 if (iSamplerChannel < 0)
974 return iVoiceCount;
975
976 // Lock this section up.
977 lscp_mutex_lock(pClient->mutex);
978
979 sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
980 if (lscp_client_call(pClient, szQuery) == LSCP_OK)
981 iVoiceCount = atoi(lscp_client_get_result(pClient));
982
983 // Unlock this section down.
984 lscp_mutex_unlock(pClient->mutex);
985
986 return iVoiceCount;
987 }
988
989
990 /**
991 * Current number of active disk streams:
992 * GET CHANNEL STREAM_COUNT <sampler-channel>
993 *
994 * @returns The number of active disk streams on success, -1 otherwise.
995 */
996 int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
997 {
998 char szQuery[LSCP_BUFSIZ];
999 int iStreamCount = -1;
1000
1001 if (iSamplerChannel < 0)
1002 return iStreamCount;
1003
1004 // Lock this section up.
1005 lscp_mutex_lock(pClient->mutex);
1006
1007 sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1008 if (lscp_client_call(pClient, szQuery) == LSCP_OK)
1009 iStreamCount = atoi(lscp_client_get_result(pClient));
1010
1011 // Unlock this section down.
1012 lscp_mutex_unlock(pClient->mutex);
1013
1014 return iStreamCount;
1015 }
1016
1017
1018 /**
1019 * Current fill state of disk stream buffers:
1020 * GET CHANNEL BUFFER_FILL {BYTES|PERCENTAGE} <sampler-channel>
1021 *
1022 * @param pClient Pointer to client instance structure.
1023 * @param usage_type Usage type to be returned, either
1024 * @ref LSCP_USAGE_BYTES, or
1025 * @ref LSCP_USAGE_PERCENTAGE.
1026 * @param iSamplerChannel Sampler channel number.
1027 *
1028 * @returns A pointer to a @ref lscp_buffer_fill_t structure, with the
1029 * information of the current disk stream buffer fill usage, for the given
1030 * sampler channel, or NULL in case of failure.
1031 */
1032 lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )
1033 {
1034 lscp_buffer_fill_t *pBufferFill;
1035 char szQuery[LSCP_BUFSIZ];
1036 int iStreamCount;
1037 const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1038 const char *pszResult;
1039 const char *pszSeps = "[]%,";
1040 char *pszToken;
1041 char *pch;
1042 int iStream;
1043
1044 // Retrieve a channel stream estimation.
1045 iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1046 if (pClient->iStreamCount < 0)
1047 return NULL;
1048
1049 // Lock this section up.
1050 lscp_mutex_lock(pClient->mutex);
1051
1052 // Check if we need to reallocate the stream usage array.
1053 if (pClient->iStreamCount != iStreamCount) {
1054 if (pClient->buffer_fill)
1055 free(pClient->buffer_fill);
1056 if (iStreamCount > 0)
1057 pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1058 else
1059 pClient->buffer_fill = NULL;
1060 pClient->iStreamCount = iStreamCount;
1061 }
1062
1063 // Get buffer fill usage...
1064 pBufferFill = pClient->buffer_fill;
1065 if (pBufferFill && iStreamCount > 0) {
1066 iStream = 0;
1067 pBufferFill = pClient->buffer_fill;
1068 sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1069 if (lscp_client_call(pClient, szQuery) == LSCP_OK) {
1070 pszResult = lscp_client_get_result(pClient);
1071 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1072 while (pszToken && iStream < pClient->iStreamCount) {
1073 if (*pszToken) {
1074 pBufferFill[iStream].stream_id = atol(pszToken);
1075 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1076 if (pszToken == NULL)
1077 break;
1078 pBufferFill[iStream].stream_usage = atol(pszToken);
1079 iStream++;
1080 }
1081 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1082 }
1083 } // Reset the usage, whatever it was before.
1084 else while (iStream < pClient->iStreamCount)
1085 pBufferFill[iStream++].stream_usage = 0;
1086 }
1087
1088 // Unlock this section down.
1089 lscp_mutex_unlock(pClient->mutex);
1090
1091 return pBufferFill;
1092 }
1093
1094
1095 /**
1096 * Setting audio output type:
1097 * SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
1098 *
1099 * @param pClient Pointer to client instance structure.
1100 * @param iSamplerChannel Sampler channel number.
1101 * @param pszAudioDriver Audio output driver type (e.g. "ALSA" or "JACK").
1102 */
1103 lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )
1104 {
1105 char szQuery[LSCP_BUFSIZ];
1106
1107 if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1108 return LSCP_FAILED;
1109
1110 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);
1111 return lscp_client_query(pClient, szQuery);
1112 }
1113
1114
1115 /**
1116 * Setting audio output device:
1117 * SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1118 *
1119 * @param pClient Pointer to client instance structure.
1120 * @param iSamplerChannel Sampler channel number.
1121 * @param iAudioDevice Audio output device number identifier.
1122 */
1123 lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )
1124 {
1125 char szQuery[LSCP_BUFSIZ];
1126
1127 if (iSamplerChannel < 0 || iAudioDevice < 0)
1128 return LSCP_FAILED;
1129
1130 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);
1131 return lscp_client_query(pClient, szQuery);
1132 }
1133
1134
1135 /**
1136 * Setting audio output channel:
1137 * SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-output-chan> <audio-input-chan>
1138 *
1139 * @param pClient Pointer to client instance structure.
1140 * @param iSamplerChannel Sampler channel number.
1141 * @param iAudioOut Audio output device channel to be routed from.
1142 * @param iAudioIn Audio output device channel to be routed into.
1143 *
1144 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1145 */
1146 lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )
1147 {
1148 char szQuery[LSCP_BUFSIZ];
1149
1150 if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1151 return LSCP_FAILED;
1152
1153 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNELS %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);
1154 return lscp_client_query(pClient, szQuery);
1155 }
1156
1157
1158 /**
1159 * Setting MIDI input type:
1160 * SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
1161 *
1162 * @param pClient Pointer to client instance structure.
1163 * @param iSamplerChannel Sampler channel number.
1164 * @param pszMidiDriver MIDI input driver type (e.g. "ALSA").
1165 *
1166 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1167 */
1168 lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )
1169 {
1170 char szQuery[LSCP_BUFSIZ];
1171
1172 if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1173 return LSCP_FAILED;
1174
1175 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);
1176 return lscp_client_query(pClient, szQuery);
1177 }
1178
1179
1180 /**
1181 * Setting MIDI input device:
1182 * SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1183 *
1184 * @param pClient Pointer to client instance structure.
1185 * @param iSamplerChannel Sampler channel number.
1186 * @param iMidiDevice MIDI input device number identifier.
1187 */
1188 lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )
1189 {
1190 char szQuery[LSCP_BUFSIZ];
1191
1192 if (iSamplerChannel < 0 || iMidiDevice < 0)
1193 return LSCP_FAILED;
1194
1195 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);
1196 return lscp_client_query(pClient, szQuery);
1197 }
1198
1199
1200 /**
1201 * Setting MIDI input port:
1202 * SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
1203 *
1204 * @param pClient Pointer to client instance structure.
1205 * @param iSamplerChannel Sampler channel number.
1206 * @param iMidiPort MIDI input driver virtual port number.
1207 *
1208 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1209 */
1210 lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )
1211 {
1212 char szQuery[LSCP_BUFSIZ];
1213
1214 if (iSamplerChannel < 0 || iMidiPort < 0)
1215 return LSCP_FAILED;
1216
1217 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);
1218 return lscp_client_query(pClient, szQuery);
1219 }
1220
1221
1222 /**
1223 * Setting MIDI input channel:
1224 * SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
1225 *
1226 * @param pClient Pointer to client instance structure.
1227 * @param iSamplerChannel Sampler channel number.
1228 * @param iMidiChannel MIDI channel number to listen (1-16) or
1229 * zero (0) to listen on all channels.
1230 *
1231 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1232 */
1233 lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )
1234 {
1235 char szQuery[LSCP_BUFSIZ];
1236
1237 if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1238 return LSCP_FAILED;
1239
1240 if (iMidiChannel > 0)
1241 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);
1242 else
1243 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);
1244 return lscp_client_query(pClient, szQuery);
1245 }
1246
1247
1248 /**
1249 * Setting channel volume:
1250 * SET CHANNEL VOLUME <sampler-channel> <volume>
1251 *
1252 * @param pClient Pointer to client instance structure.
1253 * @param iSamplerChannel Sampler channel number.
1254 * @param fVolume Sampler channel volume as a positive floating point
1255 * number, where a value less than 1.0 for attenuation,
1256 * and greater than 1.0 for amplification.
1257 *
1258 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1259 */
1260 lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )
1261 {
1262 char szQuery[LSCP_BUFSIZ];
1263
1264 if (iSamplerChannel < 0 || fVolume < 0.0)
1265 return LSCP_FAILED;
1266
1267 sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);
1268 return lscp_client_query(pClient, szQuery);
1269 }
1270
1271
1272 /**
1273 * Resetting a sampler channel:
1274 * RESET CHANNEL <sampler-channel>
1275 *
1276 * @param pClient Pointer to client instance structure.
1277 * @param iSamplerChannel Sampler channel number.
1278 *
1279 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1280 */
1281 lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1282 {
1283 char szQuery[LSCP_BUFSIZ];
1284
1285 if (iSamplerChannel < 0)
1286 return LSCP_FAILED;
1287
1288 sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1289 return lscp_client_query(pClient, szQuery);
1290 }
1291
1292
1293 // end of client.c

  ViewVC Help
Powered by ViewVC