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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 132 - (show annotations) (download)
Fri Jun 18 14:19:19 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 38352 byte(s)
* Overall mutexing of client command calls;
  preparation of forthcoming v.09 LSCP document draft.

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

  ViewVC Help
Powered by ViewVC