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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 114 - (show annotations) (download)
Mon Jun 7 21:40:23 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 39346 byte(s)
* New lscp_socket_herror() wraper function
  for proper gethostbyname() error messages.

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

  ViewVC Help
Powered by ViewVC