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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 975 - (show annotations) (download)
Sun Dec 17 00:59:40 2006 UTC (17 years, 3 months ago) by capela
File MIME type: text/plain
File size: 65643 byte(s)
* MIDI instrument mapping, second round, according to
  LSCP 1.2 draft document as of December 15, 2006.

* New client interface functions:
     lscp_set_channel_midi_map();
     lscp_add_midi_instrument_map();
     lscp_remove_midi_instrument_map();
     lscp_get_midi_instrument_maps();
     lscp_list_midi_instrument_maps();
     lscp_get_midi_instrument_map_name();
     lscp_set_midi_instrument_map_name();

1 // client.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 *****************************************************************************/
22
23 #include "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
44 fd_set fds; // File descriptor list for select().
45 int fd, fdmax; // Maximum file descriptor number.
46 struct timeval tv; // For specifying a timeout value.
47 int iSelect; // Holds select return status.
48 int iTimeout;
49
50 char achBuffer[LSCP_BUFSIZ];
51 int cchBuffer;
52 const char *pszSeps = ":\r\n";
53 char * pszToken;
54 char * pch;
55 int cchToken;
56 lscp_event_t event;
57
58 #ifdef DEBUG
59 fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
60 #endif
61
62 while (pClient->evt.iState) {
63
64 // Prepare for waiting on select...
65 fd = (int) pClient->evt.sock;
66 FD_ZERO(&fds);
67 FD_SET((unsigned int) fd, &fds);
68 fdmax = fd;
69
70 // Use the timeout (x10) select feature ...
71 iTimeout = 10 * pClient->iTimeout;
72 if (iTimeout >= 1000) {
73 tv.tv_sec = iTimeout / 1000;
74 iTimeout -= tv.tv_sec * 1000;
75 }
76 else tv.tv_sec = 0;
77 tv.tv_usec = iTimeout * 1000;
78
79 // Wait for event...
80 iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
81 if (iSelect > 0 && FD_ISSET(fd, &fds)) {
82 // May recv now...
83 cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
84 if (cchBuffer > 0) {
85 // Make sure received buffer it's null terminated.
86 achBuffer[cchBuffer] = (char) 0;
87 // Parse for the notification event message...
88 pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".
89 if (strcasecmp(pszToken, "NOTIFY") == 0) {
90 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
91 event = lscp_event_from_text(pszToken);
92 // And pick the rest of data...
93 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
94 cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
95 // Double-check if we're really up to it...
96 if (pClient->events & event) {
97 // Invoke the client event callback...
98 if ((*pClient->pfnCallback)(
99 pClient,
100 event,
101 pszToken,
102 cchToken,
103 pClient->pvData) != LSCP_OK) {
104 pClient->evt.iState = 0;
105 }
106 }
107 }
108 } else {
109 lscp_socket_perror("_lscp_client_evt_proc: recv");
110 pClient->evt.iState = 0;
111 }
112 } // Check if select has in error.
113 else if (iSelect < 0) {
114 lscp_socket_perror("_lscp_client_evt_proc: select");
115 pClient->evt.iState = 0;
116 }
117
118 // Finally, always signal the event.
119 lscp_cond_signal(pClient->cond);
120 }
121
122 #ifdef DEBUG
123 fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
124 #endif
125 }
126
127
128 //-------------------------------------------------------------------------
129 // Event subscription helpers.
130
131 // Open the event service socket connection.
132 static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
133 {
134 lscp_socket_t sock;
135 struct sockaddr_in addr;
136 int cAddr;
137 #if defined(WIN32)
138 int iSockOpt = (-1);
139 #endif
140
141 // Prepare the event connection socket...
142 sock = socket(AF_INET, SOCK_STREAM, 0);
143 if (sock == INVALID_SOCKET) {
144 lscp_socket_perror("_lscp_client_evt_connect: socket");
145 return LSCP_FAILED;
146 }
147
148 #if defined(WIN32)
149 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
150 lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
151 #endif
152
153 #ifdef DEBUG
154 lscp_socket_getopts("_lscp_client_evt_connect:", sock);
155 #endif
156
157 // Use same address of the command connection.
158 cAddr = sizeof(struct sockaddr_in);
159 memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
160
161 // Start the connection...
162 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
163 lscp_socket_perror("_lscp_client_evt_connect: connect");
164 closesocket(sock);
165 return LSCP_FAILED;
166 }
167
168 // Set our socket agent struct...
169 lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
170
171 // And finally the service thread...
172 return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
173 }
174
175
176 // Subscribe to a single event.
177 static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )
178 {
179 const char *pszEvent;
180 char szQuery[LSCP_BUFSIZ];
181 int cchQuery;
182
183 if (pClient == NULL)
184 return LSCP_FAILED;
185
186 // Which (single) event?
187 pszEvent = lscp_event_to_text(event);
188 if (pszEvent == NULL)
189 return LSCP_FAILED;
190
191 // Build the query string...
192 cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);
193 // Just send data, forget result...
194 if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
195 lscp_socket_perror("_lscp_client_evt_request: send");
196 return LSCP_FAILED;
197 }
198
199 // Wait on response.
200 lscp_cond_wait(pClient->cond, pClient->mutex);
201
202 // Update as naively as we can...
203 if (iSubscribe)
204 pClient->events |= event;
205 else
206 pClient->events &= ~event;
207
208 return LSCP_OK;
209 }
210
211
212 //-------------------------------------------------------------------------
213 // Client versioning teller fuunction.
214
215
216 /** Retrieve the current client library version string. */
217 const char* lscp_client_package (void) { return LSCP_PACKAGE; }
218
219 /** Retrieve the current client library version string. */
220 const char* lscp_client_version (void) { return LSCP_VERSION; }
221
222 /** Retrieve the current client library build timestamp string. */
223 const char* lscp_client_build (void) { return __DATE__ " " __TIME__; }
224
225
226 //-------------------------------------------------------------------------
227 // Client socket functions.
228
229 /**
230 * Create a client instance, estabilishing a connection to a server hostname,
231 * which must be listening on the given port. A client callback function is
232 * also supplied for server notification event handling.
233 *
234 * @param pszHost Hostname of the linuxsampler listening server.
235 * @param iPort Port number of the linuxsampler listening server.
236 * @param pfnCallback Callback function to receive event notifications.
237 * @param pvData User context opaque data, that will be passed
238 * to the callback function.
239 *
240 * @returns The new client instance pointer if successfull, which shall be
241 * used on all subsequent client calls, NULL otherwise.
242 */
243 lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )
244 {
245 lscp_client_t *pClient;
246 struct hostent *pHost;
247 lscp_socket_t sock;
248 struct sockaddr_in addr;
249 int cAddr;
250 #if defined(WIN32)
251 int iSockOpt = (-1);
252 #endif
253
254 if (pfnCallback == NULL) {
255 fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
256 return NULL;
257 }
258
259 pHost = gethostbyname(pszHost);
260 if (pHost == NULL) {
261 lscp_socket_herror("lscp_client_create: gethostbyname");
262 return NULL;
263 }
264
265 // Allocate client descriptor...
266
267 pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
268 if (pClient == NULL) {
269 fprintf(stderr, "lscp_client_create: Out of memory.\n");
270 return NULL;
271 }
272 memset(pClient, 0, sizeof(lscp_client_t));
273
274 pClient->pfnCallback = pfnCallback;
275 pClient->pvData = pvData;
276
277 #ifdef DEBUG
278 fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);
279 #endif
280
281 // Prepare the command connection socket...
282
283 sock = socket(AF_INET, SOCK_STREAM, 0);
284 if (sock == INVALID_SOCKET) {
285 lscp_socket_perror("lscp_client_create: cmd: socket");
286 free(pClient);
287 return NULL;
288 }
289
290 #if defined(WIN32)
291 if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
292 lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
293 #endif
294
295 #ifdef DEBUG
296 lscp_socket_getopts("lscp_client_create: cmd", sock);
297 #endif
298
299 cAddr = sizeof(struct sockaddr_in);
300 memset((char *) &addr, 0, cAddr);
301 addr.sin_family = pHost->h_addrtype;
302 memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
303 addr.sin_port = htons((short) iPort);
304
305 if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
306 lscp_socket_perror("lscp_client_create: cmd: connect");
307 closesocket(sock);
308 free(pClient);
309 return NULL;
310 }
311
312 // Initialize the command socket agent struct...
313 lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
314
315 #ifdef DEBUG
316 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));
317 #endif
318
319 // Initialize the event service socket struct...
320 lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
321 // No events subscribed, yet.
322 pClient->events = LSCP_EVENT_NONE;
323 // Initialize cached members.
324 pClient->audio_drivers = NULL;
325 pClient->midi_drivers = NULL;
326 pClient->audio_devices = NULL;
327 pClient->midi_devices = NULL;
328 pClient->engines = NULL;
329 pClient->channels = NULL;
330 pClient->midi_instruments = NULL;
331 pClient->midi_maps = NULL;
332 pClient->midi_map_name = NULL;
333 lscp_driver_info_init(&(pClient->audio_driver_info));
334 lscp_driver_info_init(&(pClient->midi_driver_info));
335 lscp_device_info_init(&(pClient->audio_device_info));
336 lscp_device_info_init(&(pClient->midi_device_info));
337 lscp_param_info_init(&(pClient->audio_param_info));
338 lscp_param_info_init(&(pClient->midi_param_info));
339 lscp_device_port_info_init(&(pClient->audio_channel_info));
340 lscp_device_port_info_init(&(pClient->midi_port_info));
341 lscp_param_info_init(&(pClient->audio_channel_param_info));
342 lscp_param_info_init(&(pClient->midi_port_param_info));
343 lscp_server_info_init(&(pClient->server_info));
344 lscp_engine_info_init(&(pClient->engine_info));
345 lscp_channel_info_init(&(pClient->channel_info));
346 lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
347 // Initialize error stuff.
348 pClient->pszResult = NULL;
349 pClient->iErrno = -1;
350 // Stream usage stuff.
351 pClient->buffer_fill = NULL;
352 pClient->iStreamCount = 0;
353 // Default timeout value.
354 pClient->iTimeout = LSCP_TIMEOUT_MSECS;
355 pClient->iTimeoutCount = 0;
356
357 // Initialize the transaction mutex.
358 lscp_mutex_init(pClient->mutex);
359 lscp_cond_init(pClient->cond);
360
361 // Finally we've some success...
362 return pClient;
363 }
364
365
366 /**
367 * Wait for a client instance to terminate graciously.
368 *
369 * @param pClient Pointer to client instance structure.
370 */
371 lscp_status_t lscp_client_join ( lscp_client_t *pClient )
372 {
373 if (pClient == NULL)
374 return LSCP_FAILED;
375
376 #ifdef DEBUG
377 fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
378 #endif
379
380 // lscp_socket_agent_join(&(pClient->evt));
381 lscp_socket_agent_join(&(pClient->cmd));
382
383 return LSCP_OK;
384 }
385
386
387 /**
388 * Terminate and destroy a client instance.
389 *
390 * @param pClient Pointer to client instance structure.
391 *
392 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
393 */
394 lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
395 {
396 if (pClient == NULL)
397 return LSCP_FAILED;
398
399 #ifdef DEBUG
400 fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
401 #endif
402
403 // Lock this section up.
404 lscp_mutex_lock(pClient->mutex);
405
406 // Free up all cached members.
407 lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
408 lscp_channel_info_free(&(pClient->channel_info));
409 lscp_engine_info_free(&(pClient->engine_info));
410 lscp_server_info_free(&(pClient->server_info));
411 lscp_param_info_free(&(pClient->midi_port_param_info));
412 lscp_param_info_free(&(pClient->audio_channel_param_info));
413 lscp_device_port_info_free(&(pClient->midi_port_info));
414 lscp_device_port_info_free(&(pClient->audio_channel_info));
415 lscp_param_info_free(&(pClient->midi_param_info));
416 lscp_param_info_free(&(pClient->audio_param_info));
417 lscp_device_info_free(&(pClient->midi_device_info));
418 lscp_device_info_free(&(pClient->audio_device_info));
419 lscp_driver_info_free(&(pClient->midi_driver_info));
420 lscp_driver_info_free(&(pClient->audio_driver_info));
421 // Free available engine table.
422 lscp_szsplit_destroy(pClient->audio_drivers);
423 lscp_szsplit_destroy(pClient->midi_drivers);
424 lscp_isplit_destroy(pClient->audio_devices);
425 lscp_isplit_destroy(pClient->midi_devices);
426 lscp_szsplit_destroy(pClient->engines);
427 lscp_isplit_destroy(pClient->channels);
428 lscp_midi_instruments_destroy(pClient->midi_instruments);
429 lscp_isplit_destroy(pClient->midi_maps);
430 if (pClient->midi_map_name)
431 free(pClient->midi_map_name);
432 // Make them null.
433 pClient->audio_drivers = NULL;
434 pClient->midi_drivers = NULL;
435 pClient->audio_devices = NULL;
436 pClient->midi_devices = NULL;
437 pClient->engines = NULL;
438 pClient->channels = NULL;
439 pClient->midi_instruments = NULL;
440 pClient->midi_maps = NULL;
441 pClient->midi_map_name = NULL;
442 // Free result error stuff.
443 lscp_client_set_result(pClient, NULL, 0);
444 // Free stream usage stuff.
445 if (pClient->buffer_fill)
446 free(pClient->buffer_fill);
447 pClient->buffer_fill = NULL;
448 pClient->iStreamCount = 0;
449 pClient->iTimeout = 0;
450
451 // Free socket agents.
452 lscp_socket_agent_free(&(pClient->evt));
453 lscp_socket_agent_free(&(pClient->cmd));
454
455 // Last but not least, free good ol'transaction mutex.
456 lscp_mutex_unlock(pClient->mutex);
457 lscp_mutex_destroy(pClient->mutex);
458 lscp_cond_destroy(pClient->cond);
459
460 free(pClient);
461
462 return LSCP_OK;
463 }
464
465
466 /**
467 * Set the client transaction timeout interval.
468 *
469 * @param pClient Pointer to client instance structure.
470 * @param iTimeout Transaction timeout in milliseconds.
471 *
472 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
473 */
474 lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
475 {
476 if (pClient == NULL)
477 return LSCP_FAILED;
478 if (iTimeout < 0)
479 return LSCP_FAILED;
480
481 pClient->iTimeout = iTimeout;
482 return LSCP_OK;
483 }
484
485
486 /**
487 * Get the client transaction timeout interval.
488 *
489 * @param pClient Pointer to client instance structure.
490 *
491 * @returns The current timeout value milliseconds, -1 in case of failure.
492 */
493 int lscp_client_get_timeout ( lscp_client_t *pClient )
494 {
495 if (pClient == NULL)
496 return -1;
497
498 return pClient->iTimeout;
499 }
500
501
502 //-------------------------------------------------------------------------
503 // Client common protocol functions.
504
505 /**
506 * Submit a command query line string to the server. The query string
507 * must be cr/lf and null terminated. Besides the return code, the
508 * specific server response to the command request is made available
509 * by the @ref lscp_client_get_result and @ref lscp_client_get_errno
510 * function calls.
511 *
512 * @param pClient Pointer to client instance structure.
513 * @param pszQuery Command request line to be sent to server,
514 * must be cr/lf and null terminated.
515 *
516 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
517 */
518 lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
519 {
520 lscp_status_t ret;
521
522 if (pClient == NULL)
523 return LSCP_FAILED;
524
525 // Lock this section up.
526 lscp_mutex_lock(pClient->mutex);
527
528 // Just make the now guarded call.
529 ret = lscp_client_call(pClient, pszQuery, 0);
530
531 // Unlock this section down.
532 lscp_mutex_unlock(pClient->mutex);
533
534 return ret;
535 }
536
537 /**
538 * Get the last received result string. In case of error or warning,
539 * this is the text of the error or warning message issued.
540 *
541 * @param pClient Pointer to client instance structure.
542 *
543 * @returns A pointer to the literal null-terminated result string as
544 * of the last command request.
545 */
546 const char *lscp_client_get_result ( lscp_client_t *pClient )
547 {
548 if (pClient == NULL)
549 return NULL;
550
551 return pClient->pszResult;
552 }
553
554
555 /**
556 * Get the last error/warning number received.
557 *
558 * @param pClient Pointer to client instance structure.
559 *
560 * @returns The numerical value of the last error or warning
561 * response code received.
562 */
563 int lscp_client_get_errno ( lscp_client_t *pClient )
564 {
565 if (pClient == NULL)
566 return -1;
567
568 return pClient->iErrno;
569 }
570
571
572 //-------------------------------------------------------------------------
573 // Client registration protocol functions.
574
575 /**
576 * Register frontend for receiving event messages:
577 * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
578 * | CHANNEL_INFO | MISCELLANEOUS
579 *
580 * @param pClient Pointer to client instance structure.
581 * @param events Bit-wise OR'ed event flags to subscribe.
582 *
583 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
584 */
585 lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
586 {
587 lscp_status_t ret = LSCP_FAILED;
588
589 if (pClient == NULL)
590 return LSCP_FAILED;
591
592 // Lock this section up.
593 lscp_mutex_lock(pClient->mutex);
594
595 // If applicable, start the alternate connection...
596 if (pClient->events == LSCP_EVENT_NONE)
597 ret = _lscp_client_evt_connect(pClient);
598
599 // Send the subscription commands.
600 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
601 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);
602 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
603 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
604 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
605 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
606 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
607 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
608 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
609 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
610 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
611 ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
612
613 // Unlock this section down.
614 lscp_mutex_unlock(pClient->mutex);
615
616 return ret;
617 }
618
619
620 /**
621 * Deregister frontend from receiving UDP event messages anymore:
622 * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL
623 * | CHANNEL_INFO | MISCELLANEOUS
624 *
625 * @param pClient Pointer to client instance structure.
626 * @param events Bit-wise OR'ed event flags to unsubscribe.
627 *
628 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
629 */
630 lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
631 {
632 lscp_status_t ret = LSCP_OK;
633
634 if (pClient == NULL)
635 return LSCP_FAILED;
636
637 // Lock this section up.
638 lscp_mutex_lock(pClient->mutex);
639
640 // Send the unsubscription commands.
641 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
642 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT);
643 if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
644 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
645 if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
646 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
647 if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
648 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
649 if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
650 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
651 if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
652 ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
653
654 // If necessary, close the alternate connection...
655 if (pClient->events == LSCP_EVENT_NONE)
656 lscp_socket_agent_free(&(pClient->evt));
657
658 // Unlock this section down.
659 lscp_mutex_unlock(pClient->mutex);
660
661 return ret;
662 }
663
664
665 /**
666 * Getting current subscribed events.
667 *
668 * @param pClient Pointer to client instance structure.
669 *
670 * @returns The current subscrived bit-wise OR'ed event flags.
671 */
672 lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )
673 {
674 if (pClient == NULL)
675 return LSCP_EVENT_NONE;
676
677 return pClient->events;
678 }
679
680
681 //-------------------------------------------------------------------------
682 // Client command protocol functions.
683
684 /**
685 * Loading an instrument:
686 * LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
687 *
688 * @param pClient Pointer to client instance structure.
689 * @param pszFileName Instrument file name.
690 * @param iInstrIndex Instrument index number.
691 * @param iSamplerChannel Sampler Channel.
692 *
693 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
694 */
695 lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
696 {
697 char szQuery[LSCP_BUFSIZ];
698
699 if (pszFileName == NULL || iSamplerChannel < 0)
700 return LSCP_FAILED;
701
702 sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
703 return lscp_client_query(pClient, szQuery);
704 }
705
706
707 /**
708 * Loading an instrument in the background (non modal):
709 * LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
710 *
711 * @param pClient Pointer to client instance structure.
712 * @param pszFileName Instrument file name.
713 * @param iInstrIndex Instrument index number.
714 * @param iSamplerChannel Sampler Channel.
715 *
716 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
717 */
718 lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )
719 {
720 char szQuery[LSCP_BUFSIZ];
721
722 if (pszFileName == NULL || iSamplerChannel < 0)
723 return LSCP_FAILED;
724
725 sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);
726 return lscp_client_query(pClient, szQuery);
727 }
728
729
730 /**
731 * Loading a sampler engine:
732 * LOAD ENGINE <engine-name> <sampler-channel>
733 *
734 * @param pClient Pointer to client instance structure.
735 * @param pszEngineName Engine name.
736 * @param iSamplerChannel Sampler channel number.
737 *
738 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
739 */
740 lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
741 {
742 char szQuery[LSCP_BUFSIZ];
743
744 if (pszEngineName == NULL || iSamplerChannel < 0)
745 return LSCP_FAILED;
746
747 sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);
748 return lscp_client_query(pClient, szQuery);
749 }
750
751
752 /**
753 * Current number of sampler channels:
754 * GET CHANNELS
755 *
756 * @param pClient Pointer to client instance structure.
757 *
758 * @returns The current total number of sampler channels on success,
759 * -1 otherwise.
760 */
761 int lscp_get_channels ( lscp_client_t *pClient )
762 {
763 int iChannels = -1;
764
765 if (pClient == NULL)
766 return -1;
767
768 // Lock this section up.
769 lscp_mutex_lock(pClient->mutex);
770
771 if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)
772 iChannels = atoi(lscp_client_get_result(pClient));
773
774 // Unlock this section doen.
775 lscp_mutex_unlock(pClient->mutex);
776
777 return iChannels;
778 }
779
780
781 /**
782 * List current sampler channels number identifiers:
783 * LIST CHANNELS
784 *
785 * @param pClient Pointer to client instance structure.
786 *
787 * @returns An array of the sampler channels identifiers as positive integers,
788 * terminated with -1 on success, NULL otherwise.
789 */
790 int *lscp_list_channels ( lscp_client_t *pClient )
791 {
792 const char *pszSeps = ",";
793
794 if (pClient == NULL)
795 return NULL;
796
797 // Lock this section up.
798 lscp_mutex_lock(pClient->mutex);
799
800 if (pClient->channels) {
801 lscp_isplit_destroy(pClient->channels);
802 pClient->channels = NULL;
803 }
804
805 if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)
806 pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
807
808 // Unlock this section down.
809 lscp_mutex_unlock(pClient->mutex);
810
811 return pClient->channels;
812 }
813
814
815 /**
816 * Adding a new sampler channel:
817 * ADD CHANNEL
818 *
819 * @param pClient Pointer to client instance structure.
820 *
821 * @returns The new sampler channel number identifier,
822 * or -1 in case of failure.
823 */
824 int lscp_add_channel ( lscp_client_t *pClient )
825 {
826 int iSamplerChannel = -1;
827
828 if (pClient == NULL)
829 return -1;
830
831 // Lock this section up.
832 lscp_mutex_lock(pClient->mutex);
833
834 if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)
835 iSamplerChannel = atoi(lscp_client_get_result(pClient));
836
837 // Unlock this section down.
838 lscp_mutex_unlock(pClient->mutex);
839
840 return iSamplerChannel;
841 }
842
843
844 /**
845 * Removing a sampler channel:
846 * REMOVE CHANNEL <sampler-channel>
847 *
848 * @param pClient Pointer to client instance structure.
849 * @param iSamplerChannel Sampler channel number.
850 *
851 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
852 */
853 lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
854 {
855 char szQuery[LSCP_BUFSIZ];
856
857 if (iSamplerChannel < 0)
858 return LSCP_FAILED;
859
860 sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
861 return lscp_client_query(pClient, szQuery);
862 }
863
864
865 /**
866 * Getting all available engines count:
867 * GET AVAILABLE_ENGINES
868 *
869 * @param pClient Pointer to client instance structure.
870 *
871 * @returns The current total number of sampler engines on success,
872 * -1 otherwise.
873 */
874 int lscp_get_available_engines ( lscp_client_t *pClient )
875 {
876 int iAvailableEngines = -1;
877
878 if (pClient == NULL)
879 return -1;
880
881 // Lock this section up.
882 lscp_mutex_lock(pClient->mutex);
883
884 if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
885 iAvailableEngines = atoi(lscp_client_get_result(pClient));
886
887 // Unlock this section down.
888 lscp_mutex_unlock(pClient->mutex);
889
890 return iAvailableEngines;
891 }
892
893
894 /**
895 * Getting all available engines:
896 * LIST AVAILABLE_ENGINES
897 *
898 * @param pClient Pointer to client instance structure.
899 *
900 * @returns A NULL terminated array of engine name strings,
901 * or NULL in case of failure.
902 */
903 const char **lscp_list_available_engines ( lscp_client_t *pClient )
904 {
905 const char *pszSeps = ",";
906
907 if (pClient == NULL)
908 return NULL;
909
910 // Lock this section up.
911 lscp_mutex_lock(pClient->mutex);
912
913 if (pClient->engines) {
914 lscp_szsplit_destroy(pClient->engines);
915 pClient->engines = NULL;
916 }
917
918 if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
919 pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
920
921 // Unlock this section down.
922 lscp_mutex_unlock(pClient->mutex);
923
924 return (const char **) pClient->engines;
925 }
926
927
928 /**
929 * Getting information about an engine.
930 * GET ENGINE INFO <engine-name>
931 *
932 * @param pClient Pointer to client instance structure.
933 * @param pszEngineName Engine name.
934 *
935 * @returns A pointer to a @ref lscp_engine_info_t structure, with all the
936 * information of the given sampler engine, or NULL in case of failure.
937 */
938 lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )
939 {
940 lscp_engine_info_t *pEngineInfo;
941 char szQuery[LSCP_BUFSIZ];
942 const char *pszResult;
943 const char *pszSeps = ":";
944 const char *pszCrlf = "\r\n";
945 char *pszToken;
946 char *pch;
947
948 if (pClient == NULL)
949 return NULL;
950 if (pszEngineName == NULL)
951 return NULL;
952
953 // Lock this section up.
954 lscp_mutex_lock(pClient->mutex);
955
956 pEngineInfo = &(pClient->engine_info);
957 lscp_engine_info_reset(pEngineInfo);
958
959 sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
960 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
961 pszResult = lscp_client_get_result(pClient);
962 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
963 while (pszToken) {
964 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
965 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
966 if (pszToken)
967 lscp_unquote_dup(&(pEngineInfo->description), &pszToken);
968 }
969 else if (strcasecmp(pszToken, "VERSION") == 0) {
970 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
971 if (pszToken)
972 lscp_unquote_dup(&(pEngineInfo->version), &pszToken);
973 }
974 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
975 }
976 }
977 else pEngineInfo = NULL;
978
979 // Unlock this section down.
980 lscp_mutex_unlock(pClient->mutex);
981
982 return pEngineInfo;
983 }
984
985
986 /**
987 * Getting sampler channel informations:
988 * GET CHANNEL INFO <sampler-channel>
989 *
990 * @param pClient Pointer to client instance structure.
991 * @param iSamplerChannel Sampler channel number.
992 *
993 * @returns A pointer to a @ref lscp_channel_info_t structure, with all the
994 * information of the given sampler channel, or NULL in case of failure.
995 */
996 lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
997 {
998 lscp_channel_info_t *pChannelInfo;
999 char szQuery[LSCP_BUFSIZ];
1000 const char *pszResult;
1001 const char *pszSeps = ":";
1002 const char *pszCrlf = "\r\n";
1003 char *pszToken;
1004 char *pch;
1005
1006 if (pClient == NULL)
1007 return NULL;
1008 if (iSamplerChannel < 0)
1009 return NULL;
1010
1011 // Lock this section up.
1012 lscp_mutex_lock(pClient->mutex);
1013
1014 pChannelInfo = &(pClient->channel_info);
1015 lscp_channel_info_reset(pChannelInfo);
1016
1017 sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1018 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1019 pszResult = lscp_client_get_result(pClient);
1020 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1021 while (pszToken) {
1022 if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
1023 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1024 if (pszToken)
1025 lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);
1026 }
1027 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
1028 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1029 if (pszToken)
1030 pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
1031 }
1032 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
1033 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1034 if (pszToken)
1035 pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
1036 }
1037 else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
1038 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1039 if (pszToken) {
1040 if (pChannelInfo->audio_routing)
1041 lscp_szsplit_destroy(pChannelInfo->audio_routing);
1042 pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");
1043 }
1044 }
1045 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
1046 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1047 if (pszToken)
1048 lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);
1049 }
1050 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
1051 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1052 if (pszToken)
1053 pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
1054 }
1055 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
1056 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1057 if (pszToken)
1058 lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);
1059 }
1060 else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
1061 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1062 if (pszToken)
1063 pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
1064 }
1065 else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
1066 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1067 if (pszToken)
1068 pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
1069 }
1070 else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
1071 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1072 if (pszToken)
1073 pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
1074 }
1075 else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
1076 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1077 if (pszToken) {
1078 pszToken = lscp_ltrim(pszToken);
1079 if (strcasecmp(pszToken, "ALL") == 0)
1080 pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;
1081 else
1082 pChannelInfo->midi_channel = atoi(pszToken);
1083 }
1084 }
1085 else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1086 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1087 if (pszToken) {
1088 pszToken = lscp_ltrim(pszToken);
1089 if (strcasecmp(pszToken, "NONE") == 0)
1090 pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1091 else
1092 if (strcasecmp(pszToken, "DEFAULT") == 0)
1093 pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1094 else
1095 pChannelInfo->midi_map = atoi(pszToken);
1096 }
1097 }
1098 else if (strcasecmp(pszToken, "VOLUME") == 0) {
1099 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1100 if (pszToken)
1101 pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));
1102 }
1103 else if (strcasecmp(pszToken, "MUTE") == 0) {
1104 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1105 if (pszToken)
1106 pChannelInfo->mute = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1107 }
1108 else if (strcasecmp(pszToken, "SOLO") == 0) {
1109 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1110 if (pszToken)
1111 pChannelInfo->solo = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1112 }
1113 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1114 }
1115 }
1116 else pChannelInfo = NULL;
1117
1118 // Unlock this section up.
1119 lscp_mutex_unlock(pClient->mutex);
1120
1121 return pChannelInfo;
1122 }
1123
1124
1125 /**
1126 * Current number of active voices:
1127 * GET CHANNEL VOICE_COUNT <sampler-channel>
1128 *
1129 * @param pClient Pointer to client instance structure.
1130 * @param iSamplerChannel Sampler channel number.
1131 *
1132 * @returns The number of voices currently active, -1 in case of failure.
1133 */
1134 int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
1135 {
1136 char szQuery[LSCP_BUFSIZ];
1137 int iVoiceCount = -1;
1138
1139 if (pClient == NULL)
1140 return -1;
1141 if (iSamplerChannel < 0)
1142 return -1;
1143
1144 // Lock this section up.
1145 lscp_mutex_lock(pClient->mutex);
1146
1147 sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
1148 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1149 iVoiceCount = atoi(lscp_client_get_result(pClient));
1150
1151 // Unlock this section down.
1152 lscp_mutex_unlock(pClient->mutex);
1153
1154 return iVoiceCount;
1155 }
1156
1157
1158 /**
1159 * Current number of active disk streams:
1160 * GET CHANNEL STREAM_COUNT <sampler-channel>
1161 *
1162 * @param pClient Pointer to client instance structure.
1163 * @param iSamplerChannel Sampler channel number.
1164 *
1165 * @returns The number of active disk streams on success, -1 otherwise.
1166 */
1167 int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
1168 {
1169 char szQuery[LSCP_BUFSIZ];
1170 int iStreamCount = -1;
1171
1172 if (pClient == NULL)
1173 return -1;
1174 if (iSamplerChannel < 0)
1175 return -1;
1176
1177 // Lock this section up.
1178 lscp_mutex_lock(pClient->mutex);
1179
1180 sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1181 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1182 iStreamCount = atoi(lscp_client_get_result(pClient));
1183
1184 // Unlock this section down.
1185 lscp_mutex_unlock(pClient->mutex);
1186
1187 return iStreamCount;
1188 }
1189
1190
1191 /**
1192 * Current least usage of active disk streams.
1193 *
1194 * @param pClient Pointer to client instance structure.
1195 * @param iSamplerChannel Sampler channel number.
1196 *
1197 * @returns The usage percentage of the least filled active disk stream
1198 * on success, -1 otherwise.
1199 */
1200 int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )
1201 {
1202 char szQuery[LSCP_BUFSIZ];
1203 int iStreamUsage = -1;
1204 const char *pszResult;
1205 const char *pszSeps = "[]%,";
1206 char *pszToken;
1207 char *pch;
1208 int iStream;
1209 int iPercent;
1210
1211 if (pClient == NULL)
1212 return -1;
1213 if (iSamplerChannel < 0)
1214 return -1;
1215
1216 // Lock this section up.
1217 lscp_mutex_lock(pClient->mutex);
1218
1219 iStream = 0;
1220 sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);
1221 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1222 pszResult = lscp_client_get_result(pClient);
1223 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1224 while (pszToken) {
1225 if (*pszToken) {
1226 // Skip stream id.
1227 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1228 if (pszToken == NULL)
1229 break;
1230 // Get least buffer fill percentage.
1231 iPercent = atol(pszToken);
1232 if (iStreamUsage > iPercent || iStream == 0)
1233 iStreamUsage = iPercent;
1234 iStream++;
1235 }
1236 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1237 }
1238 }
1239
1240 // Unlock this section down.
1241 lscp_mutex_unlock(pClient->mutex);
1242
1243 return iStreamUsage;
1244 }
1245
1246
1247 /**
1248 * Current fill state of disk stream buffers:
1249 * GET CHANNEL BUFFER_FILL {BYTES|PERCENTAGE} <sampler-channel>
1250 *
1251 * @param pClient Pointer to client instance structure.
1252 * @param usage_type Usage type to be returned, either
1253 * @ref LSCP_USAGE_BYTES, or
1254 * @ref LSCP_USAGE_PERCENTAGE.
1255 * @param iSamplerChannel Sampler channel number.
1256 *
1257 * @returns A pointer to a @ref lscp_buffer_fill_t structure, with the
1258 * information of the current disk stream buffer fill usage, for the given
1259 * sampler channel, or NULL in case of failure.
1260 */
1261 lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )
1262 {
1263 lscp_buffer_fill_t *pBufferFill;
1264 char szQuery[LSCP_BUFSIZ];
1265 int iStreamCount;
1266 const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1267 const char *pszResult;
1268 const char *pszSeps = "[]%,";
1269 char *pszToken;
1270 char *pch;
1271 int iStream;
1272
1273 // Retrieve a channel stream estimation.
1274 iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1275 if (iStreamCount < 0)
1276 return NULL;
1277
1278 // Lock this section up.
1279 lscp_mutex_lock(pClient->mutex);
1280
1281 // Check if we need to reallocate the stream usage array.
1282 if (pClient->iStreamCount != iStreamCount) {
1283 if (pClient->buffer_fill)
1284 free(pClient->buffer_fill);
1285 if (iStreamCount > 0)
1286 pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1287 else
1288 pClient->buffer_fill = NULL;
1289 pClient->iStreamCount = iStreamCount;
1290 }
1291
1292 // Get buffer fill usage...
1293 pBufferFill = pClient->buffer_fill;
1294 if (pBufferFill && iStreamCount > 0) {
1295 iStream = 0;
1296 pBufferFill = pClient->buffer_fill;
1297 sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1298 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1299 pszResult = lscp_client_get_result(pClient);
1300 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1301 while (pszToken && iStream < pClient->iStreamCount) {
1302 if (*pszToken) {
1303 pBufferFill[iStream].stream_id = atol(pszToken);
1304 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1305 if (pszToken == NULL)
1306 break;
1307 pBufferFill[iStream].stream_usage = atol(pszToken);
1308 iStream++;
1309 }
1310 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1311 }
1312 } // Reset the usage, whatever it was before.
1313 else while (iStream < pClient->iStreamCount)
1314 pBufferFill[iStream++].stream_usage = 0;
1315 }
1316
1317 // Unlock this section down.
1318 lscp_mutex_unlock(pClient->mutex);
1319
1320 return pBufferFill;
1321 }
1322
1323
1324 /**
1325 * Setting audio output type:
1326 * SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
1327 *
1328 * @param pClient Pointer to client instance structure.
1329 * @param iSamplerChannel Sampler channel number.
1330 * @param pszAudioDriver Audio output driver type (e.g. "ALSA" or "JACK").
1331 *
1332 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1333 */
1334 lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )
1335 {
1336 char szQuery[LSCP_BUFSIZ];
1337
1338 if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1339 return LSCP_FAILED;
1340
1341 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);
1342 return lscp_client_query(pClient, szQuery);
1343 }
1344
1345
1346 /**
1347 * Setting audio output device:
1348 * SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1349 *
1350 * @param pClient Pointer to client instance structure.
1351 * @param iSamplerChannel Sampler channel number.
1352 * @param iAudioDevice Audio output device number identifier.
1353 *
1354 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1355 */
1356 lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )
1357 {
1358 char szQuery[LSCP_BUFSIZ];
1359
1360 if (iSamplerChannel < 0 || iAudioDevice < 0)
1361 return LSCP_FAILED;
1362
1363 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);
1364 return lscp_client_query(pClient, szQuery);
1365 }
1366
1367
1368 /**
1369 * Setting audio output channel:
1370 * SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-output-chan> <audio-input-chan>
1371 *
1372 * @param pClient Pointer to client instance structure.
1373 * @param iSamplerChannel Sampler channel number.
1374 * @param iAudioOut Audio output device channel to be routed from.
1375 * @param iAudioIn Audio output device channel to be routed into.
1376 *
1377 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1378 */
1379 lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )
1380 {
1381 char szQuery[LSCP_BUFSIZ];
1382
1383 if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1384 return LSCP_FAILED;
1385
1386 sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);
1387 return lscp_client_query(pClient, szQuery);
1388 }
1389
1390
1391 /**
1392 * Setting MIDI input type:
1393 * SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
1394 *
1395 * @param pClient Pointer to client instance structure.
1396 * @param iSamplerChannel Sampler channel number.
1397 * @param pszMidiDriver MIDI input driver type (e.g. "ALSA").
1398 *
1399 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1400 */
1401 lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )
1402 {
1403 char szQuery[LSCP_BUFSIZ];
1404
1405 if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1406 return LSCP_FAILED;
1407
1408 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);
1409 return lscp_client_query(pClient, szQuery);
1410 }
1411
1412
1413 /**
1414 * Setting MIDI input device:
1415 * SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1416 *
1417 * @param pClient Pointer to client instance structure.
1418 * @param iSamplerChannel Sampler channel number.
1419 * @param iMidiDevice MIDI input device number identifier.
1420 *
1421 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1422 */
1423 lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )
1424 {
1425 char szQuery[LSCP_BUFSIZ];
1426
1427 if (iSamplerChannel < 0 || iMidiDevice < 0)
1428 return LSCP_FAILED;
1429
1430 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);
1431 return lscp_client_query(pClient, szQuery);
1432 }
1433
1434
1435 /**
1436 * Setting MIDI input port:
1437 * SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
1438 *
1439 * @param pClient Pointer to client instance structure.
1440 * @param iSamplerChannel Sampler channel number.
1441 * @param iMidiPort MIDI input driver virtual port number.
1442 *
1443 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1444 */
1445 lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )
1446 {
1447 char szQuery[LSCP_BUFSIZ];
1448
1449 if (iSamplerChannel < 0 || iMidiPort < 0)
1450 return LSCP_FAILED;
1451
1452 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);
1453 return lscp_client_query(pClient, szQuery);
1454 }
1455
1456
1457 /**
1458 * Setting MIDI input channel:
1459 * SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
1460 *
1461 * @param pClient Pointer to client instance structure.
1462 * @param iSamplerChannel Sampler channel number.
1463 * @param iMidiChannel MIDI channel address number to listen (0-15) or
1464 * @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1465 *
1466 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1467 */
1468 lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )
1469 {
1470 char szQuery[LSCP_BUFSIZ];
1471
1472 if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1473 return LSCP_FAILED;
1474
1475 if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1476 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);
1477 else
1478 sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);
1479 return lscp_client_query(pClient, szQuery);
1480 }
1481
1482
1483 /**
1484 * Setting MIDI instrument map:
1485 * SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1486 *
1487 * @param pClient Pointer to client instance structure.
1488 * @param iSamplerChannel Sampler channel number.
1489 * @param iMidiMap MIDI instrument map number, or either
1490 * @ref LSCP_MIDI_MAP_NONE or
1491 * @ref LSCP_MIDI_MAP_DEFAULT .
1492 *
1493 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1494 */
1495 lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient, int iSamplerChannel, int iMidiMap )
1496 {
1497 char szQuery[LSCP_BUFSIZ];
1498
1499 if (iSamplerChannel < 0)
1500 return LSCP_FAILED;
1501
1502 sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1503 if (iMidiMap == LSCP_MIDI_MAP_NONE)
1504 strcat(szQuery , "NONE");
1505 else
1506 if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1507 strcat(szQuery , "DEFAULT");
1508 else
1509 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1510
1511 strcat(szQuery, "\r\n");
1512
1513 return lscp_client_query(pClient, szQuery);
1514 }
1515
1516
1517 /**
1518 * Setting channel volume:
1519 * SET CHANNEL VOLUME <sampler-channel> <volume>
1520 *
1521 * @param pClient Pointer to client instance structure.
1522 * @param iSamplerChannel Sampler channel number.
1523 * @param fVolume Sampler channel volume as a positive floating point
1524 * number, where a value less than 1.0 for attenuation,
1525 * and greater than 1.0 for amplification.
1526 *
1527 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1528 */
1529 lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )
1530 {
1531 char szQuery[LSCP_BUFSIZ];
1532
1533 if (iSamplerChannel < 0 || fVolume < 0.0)
1534 return LSCP_FAILED;
1535
1536 sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);
1537 return lscp_client_query(pClient, szQuery);
1538 }
1539
1540
1541 /**
1542 * Muting a sampler channel:
1543 * SET CHANNEL MUTE <sampler-channel> <mute>
1544 *
1545 * @param pClient Pointer to client instance structure.
1546 * @param iSamplerChannel Sampler channel number.
1547 * @param iMute Sampler channel mute state as a boolean value,
1548 * either 1 (one) to mute the channel or 0 (zero)
1549 * to unmute the channel.
1550 *
1551 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1552 */
1553 lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )
1554 {
1555 char szQuery[LSCP_BUFSIZ];
1556
1557 if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1558 return LSCP_FAILED;
1559
1560 sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);
1561 return lscp_client_query(pClient, szQuery);
1562 }
1563
1564
1565 /**
1566 * Soloing a sampler channel:
1567 * SET CHANNEL SOLO <sampler-channel> <solo>
1568 *
1569 * @param pClient Pointer to client instance structure.
1570 * @param iSamplerChannel Sampler channel number.
1571 * @param iSolo Sampler channel solo state as a boolean value,
1572 * either 1 (one) to solo the channel or 0 (zero)
1573 * to unsolo the channel.
1574 *
1575 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1576 */
1577 lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )
1578 {
1579 char szQuery[LSCP_BUFSIZ];
1580
1581 if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1582 return LSCP_FAILED;
1583
1584 sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);
1585 return lscp_client_query(pClient, szQuery);
1586 }
1587
1588
1589 /**
1590 * Resetting a sampler channel:
1591 * RESET CHANNEL <sampler-channel>
1592 *
1593 * @param pClient Pointer to client instance structure.
1594 * @param iSamplerChannel Sampler channel number.
1595 *
1596 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1597 */
1598 lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1599 {
1600 char szQuery[LSCP_BUFSIZ];
1601
1602 if (iSamplerChannel < 0)
1603 return LSCP_FAILED;
1604
1605 sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1606 return lscp_client_query(pClient, szQuery);
1607 }
1608
1609
1610 /**
1611 * Resetting the sampler:
1612 * RESET
1613 *
1614 * @param pClient Pointer to client instance structure.
1615 *
1616 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1617 */
1618 lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1619 {
1620 return lscp_client_query(pClient, "RESET\r\n");
1621 }
1622
1623
1624 /**
1625 * Getting information about the server.
1626 * GET SERVER INFO
1627 *
1628 * @param pClient Pointer to client instance structure.
1629 *
1630 * @returns A pointer to a @ref lscp_server_info_t structure, with all the
1631 * information of the current connected server, or NULL in case of failure.
1632 */
1633 lscp_server_info_t *lscp_get_server_info ( lscp_client_t *pClient )
1634 {
1635 lscp_server_info_t *pServerInfo;
1636 const char *pszResult;
1637 const char *pszSeps = ":";
1638 const char *pszCrlf = "\r\n";
1639 char *pszToken;
1640 char *pch;
1641
1642 if (pClient == NULL)
1643 return NULL;
1644
1645 // Lock this section up.
1646 lscp_mutex_lock(pClient->mutex);
1647
1648 pServerInfo = &(pClient->server_info);
1649 lscp_server_info_reset(pServerInfo);
1650
1651 if (lscp_client_call(pClient, "GET SERVER INFO\r\n", 1) == LSCP_OK) {
1652 pszResult = lscp_client_get_result(pClient);
1653 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1654 while (pszToken) {
1655 if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1656 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1657 if (pszToken)
1658 lscp_unquote_dup(&(pServerInfo->description), &pszToken);
1659 }
1660 else if (strcasecmp(pszToken, "VERSION") == 0) {
1661 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1662 if (pszToken)
1663 lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1664 }
1665 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1666 }
1667 }
1668 else pServerInfo = NULL;
1669
1670 // Unlock this section down.
1671 lscp_mutex_unlock(pClient->mutex);
1672
1673 return pServerInfo;
1674 }
1675
1676
1677 /**
1678 * Current total number of active voices:
1679 * GET TOTAL_VOICE_COUNT
1680 *
1681 * @param pClient Pointer to client instance structure.
1682 *
1683 * @returns The total number of voices currently active,
1684 * -1 in case of failure.
1685 */
1686 int lscp_get_total_voice_count ( lscp_client_t *pClient )
1687 {
1688 int iVoiceCount = -1;
1689
1690 if (pClient == NULL)
1691 return -1;
1692
1693 // Lock this section up.
1694 lscp_mutex_lock(pClient->mutex);
1695
1696 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT\r\n", 0) == LSCP_OK)
1697 iVoiceCount = atoi(lscp_client_get_result(pClient));
1698
1699 // Unlock this section down.
1700 lscp_mutex_unlock(pClient->mutex);
1701
1702 return iVoiceCount;
1703 }
1704
1705
1706 /**
1707 * Maximum amount of active voices:
1708 * GET TOTAL_VOICE_COUNT_MAX
1709 *
1710 * @param pClient Pointer to client instance structure.
1711 *
1712 * @returns The maximum amount of voices currently active,
1713 * -1 in case of failure.
1714 */
1715 int lscp_get_total_voice_count_max ( lscp_client_t *pClient )
1716 {
1717 int iVoiceCount = -1;
1718
1719 if (pClient == NULL)
1720 return -1;
1721
1722 // Lock this section up.
1723 lscp_mutex_lock(pClient->mutex);
1724
1725 if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT_MAX\r\n", 0) == LSCP_OK)
1726 iVoiceCount = atoi(lscp_client_get_result(pClient));
1727
1728 // Unlock this section down.
1729 lscp_mutex_unlock(pClient->mutex);
1730
1731 return iVoiceCount;
1732 }
1733
1734
1735 /**
1736 * Create a new MIDI instrument map:
1737 * ADD MIDI_INSTRUMENT_MAP [<name>]
1738 *
1739 * @param pClient Pointer to client instance structure.
1740 * @param pszMapName MIDI instrument map name (optional)
1741 *
1742 * @returns The new MIDI instrument map number identifier,
1743 * or -1 in case of failure.
1744 */
1745 int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
1746 {
1747 int iMidiMap = -1;
1748 char szQuery[LSCP_BUFSIZ];
1749
1750 if (pClient == NULL)
1751 return -1;
1752
1753 // Lock this section up.
1754 lscp_mutex_lock(pClient->mutex);
1755
1756 strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
1757
1758 if (pszMapName)
1759 sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
1760
1761 strcat(szQuery, "\r\n");
1762
1763 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1764 iMidiMap = atoi(lscp_client_get_result(pClient));
1765
1766 // Unlock this section down.
1767 lscp_mutex_unlock(pClient->mutex);
1768
1769 return iMidiMap;
1770 }
1771
1772
1773 /**
1774 * Delete one particular or all MIDI instrument maps:
1775 * REMOVE MIDI_INSTRUMENT_MAP <midi-map>
1776 *
1777 * @param pClient Pointer to client instance structure.
1778 * @param iMidiMap MIDI instrument map number.
1779 *
1780 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1781 */
1782 lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
1783 {
1784 char szQuery[LSCP_BUFSIZ];
1785
1786 if (iMidiMap < 0)
1787 return LSCP_FAILED;
1788
1789 sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
1790
1791 return lscp_client_query(pClient, szQuery);
1792 }
1793
1794
1795 /**
1796 * Get amount of existing MIDI instrument maps:
1797 * GET MIDI_INSTRUMENT_MAPS
1798 *
1799 * @param pClient Pointer to client instance structure.
1800 *
1801 * @returns The current total number of MIDI instrument maps
1802 * on success, -1 otherwise.
1803 */
1804 int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
1805 {
1806 int iMidiMaps = -1;
1807
1808 if (pClient == NULL)
1809 return -1;
1810
1811 // Lock this section up.
1812 lscp_mutex_lock(pClient->mutex);
1813
1814 if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
1815 iMidiMaps = atoi(lscp_client_get_result(pClient));
1816
1817 // Unlock this section doen.
1818 lscp_mutex_unlock(pClient->mutex);
1819
1820 return iMidiMaps;
1821 }
1822
1823
1824 /**
1825 * Getting all created MIDI instrument maps:
1826 * LIST MIDI_INSTRUMENT_MAPS
1827 *
1828 * @param pClient Pointer to client instance structure.
1829 *
1830 * @returns An array of the MIDI instrument map identifiers as positive
1831 * integers, terminated with -1 on success, NULL otherwise.
1832 */
1833 int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
1834 {
1835 const char *pszSeps = ",";
1836
1837 if (pClient == NULL)
1838 return NULL;
1839
1840 // Lock this section up.
1841 lscp_mutex_lock(pClient->mutex);
1842
1843 if (pClient->midi_maps) {
1844 lscp_isplit_destroy(pClient->midi_maps);
1845 pClient->midi_maps = NULL;
1846 }
1847
1848 if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
1849 pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
1850
1851 // Unlock this section down.
1852 lscp_mutex_unlock(pClient->mutex);
1853
1854 return pClient->midi_maps;
1855 }
1856
1857
1858 /**
1859 * Getting a MIDI instrument map name:
1860 * GET MIDI_INSTRUMENT_MAP INFO <midi-map>
1861 *
1862 * @param pClient Pointer to client instance structure.
1863 * @param iMidiMap MIDI instrument map number.
1864 *
1865 * @returns The MIDI instrument map name on success, NULL on failure.
1866 */
1867 const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
1868 {
1869 char szQuery[LSCP_BUFSIZ];
1870 const char *pszResult;
1871 const char *pszSeps = ":";
1872 const char *pszCrlf = "\r\n";
1873 char *pszToken;
1874 char *pch;
1875
1876 if (pClient == NULL)
1877 return NULL;
1878 if (iMidiMap < 0)
1879 return NULL;
1880
1881 // Lock this section up.
1882 lscp_mutex_lock(pClient->mutex);
1883
1884 if (pClient->midi_map_name) {
1885 free(pClient->midi_map_name);
1886 pClient->midi_map_name = NULL;
1887 }
1888
1889 sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
1890 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1891 pszResult = lscp_client_get_result(pClient);
1892 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1893 while (pszToken) {
1894 if (strcasecmp(pszToken, "NAME") == 0) {
1895 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1896 if (pszToken)
1897 lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
1898 }
1899 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1900 }
1901 }
1902
1903 // Unlock this section down.
1904 lscp_mutex_unlock(pClient->mutex);
1905
1906 return pClient->midi_map_name;
1907 }
1908
1909
1910 /**
1911 * Renaming a MIDI instrument map:
1912 * SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
1913 *
1914 * @param pClient Pointer to client instance structure.
1915 * @param iMidiMap MIDI instrument map number.
1916 * @param pszMapName MIDI instrument map name.
1917 *
1918 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1919 */
1920 lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
1921 {
1922 char szQuery[LSCP_BUFSIZ];
1923
1924 if (iMidiMap < 0)
1925 return LSCP_FAILED;
1926 if (pszMapName == NULL)
1927 return LSCP_FAILED;
1928
1929 sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
1930 iMidiMap, pszMapName);
1931
1932 return lscp_client_query(pClient, szQuery);
1933 }
1934
1935
1936 /**
1937 * Create or replace a MIDI instrumnet map entry:
1938 * MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
1939 * <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
1940 *
1941 * @param pClient Pointer to client instance structure.
1942 * @param pMidiInstr MIDI instrument bank and program parameter key.
1943 * @param pszEngineName Engine name.
1944 * @param pszFileName Instrument file name.
1945 * @param iInstrIndex Instrument index number.
1946 * @param fVolume Reflects the master volume of the instrument as
1947 * a positive floating point number, where a value
1948 * less than 1.0 for attenuation, and greater than
1949 * 1.0 for amplification.
1950 * @param load_mode Instrument load life-time strategy, either
1951 * @ref LSCP_LOAD_DEFAULT, or
1952 * @ref LSCP_LOAD_ON_DEMAND, or
1953 * @ref LSCP_LOAD_ON_DEMAND_HOLD, or
1954 * @ref LSCP_LOAD_PERSISTENT.
1955 * @param pszName Instrument custom name for the map entry (optional).
1956 *
1957 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
1958 */
1959 lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )
1960 {
1961 char szQuery[LSCP_BUFSIZ];
1962
1963 if (pMidiInstr->map < 0)
1964 return LSCP_FAILED;
1965 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
1966 return LSCP_FAILED;
1967 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
1968 return LSCP_FAILED;
1969 if (pszEngineName == NULL || pszFileName == NULL)
1970 return LSCP_FAILED;
1971
1972 if (fVolume < 0.0f)
1973 fVolume = 1.0f;
1974
1975 sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
1976 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
1977 pszEngineName, pszFileName, iInstrIndex, fVolume);
1978
1979 switch (load_mode) {
1980 case LSCP_LOAD_PERSISTENT:
1981 strcat(szQuery, " PERSISTENT");
1982 break;
1983 case LSCP_LOAD_ON_DEMAND_HOLD:
1984 strcat(szQuery, " ON_DEMAND_HOLD");
1985 break;
1986 case LSCP_LOAD_ON_DEMAND:
1987 strcat(szQuery, " ON_DEMAND");
1988 break;
1989 case LSCP_LOAD_DEFAULT:
1990 default:
1991 break;
1992 }
1993
1994 if (pszName)
1995 sprintf(szQuery + strlen(szQuery), " '%s'", pszName);
1996
1997 strcat(szQuery, "\r\n");
1998
1999 return lscp_client_query(pClient, szQuery);
2000 }
2001
2002
2003 /**
2004 * Remove an entry from the MIDI instrument map:
2005 * UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2006 *
2007 * @param pClient Pointer to client instance structure.
2008 * @param pMidiInstr MIDI instrument bank and program parameter key.
2009 *
2010 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2011 */
2012 lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )
2013 {
2014 char szQuery[LSCP_BUFSIZ];
2015
2016 if (pMidiInstr->map < 0)
2017 return LSCP_FAILED;
2018 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2019 return LSCP_FAILED;
2020 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2021 return LSCP_FAILED;
2022
2023 sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2024 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2025
2026 return lscp_client_query(pClient, szQuery);
2027 }
2028
2029
2030 /**
2031 * Get the total count of MIDI instrument map entries:
2032 * GET MIDI_INSTRUMENTS ALL|<midi-map>
2033 *
2034 * @param pClient Pointer to client instance structure.
2035 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2036 *
2037 * @returns The current total number of MIDI instrument map entries
2038 * on success, -1 otherwise.
2039 */
2040 int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2041 {
2042 int iInstruments = -1;
2043 char szQuery[LSCP_BUFSIZ];
2044
2045 if (pClient == NULL)
2046 return -1;
2047
2048 // Lock this section up.
2049 lscp_mutex_lock(pClient->mutex);
2050
2051 strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
2052
2053 if (iMidiMap < 0)
2054 strcat(szQuery, "ALL");
2055 else
2056 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2057
2058 strcat(szQuery, "\r\n");
2059
2060 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2061 iInstruments = atoi(lscp_client_get_result(pClient));
2062
2063 // Unlock this section down.
2064 lscp_mutex_unlock(pClient->mutex);
2065
2066 return iInstruments;
2067 }
2068
2069
2070 /**
2071 * Getting indeces of all MIDI instrument map entries:
2072 * LIST MIDI_INSTRUMENTS ALL|<midi-map>
2073 *
2074 * @param pClient Pointer to client instance structure.
2075 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2076 *
2077 * @returns An array of @ref lscp_midi_instrument_t, terminated with the
2078 * {-1,-1,-1} triplet, NULL otherwise.
2079 */
2080 lscp_midi_instrument_t *lscp_list_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2081 {
2082 char szQuery[LSCP_BUFSIZ];
2083
2084 if (pClient == NULL)
2085 return NULL;
2086
2087 // Lock this section up.
2088 lscp_mutex_lock(pClient->mutex);
2089
2090 if (pClient->midi_instruments) {
2091 lscp_midi_instruments_destroy(pClient->midi_instruments);
2092 pClient->midi_instruments = NULL;
2093 }
2094
2095 strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
2096
2097 if (iMidiMap < 0)
2098 strcat(szQuery, "ALL");
2099 else
2100 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2101
2102 strcat(szQuery, "\r\n");
2103
2104 if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2105 pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));
2106
2107 // Unlock this section down.
2108 lscp_mutex_unlock(pClient->mutex);
2109
2110 return pClient->midi_instruments;
2111 }
2112
2113
2114 /**
2115 * Getting information about a MIDI instrument map entry:
2116 * GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2117 *
2118 * @param pClient Pointer to client instance structure.
2119 * @param pMidiInstr MIDI instrument bank and program parameter key.
2120 *
2121 * @returns A pointer to a @ref lscp_midi_instrument_info_t structure,
2122 * with all the information of the given MIDI instrument map entry,
2123 * or NULL in case of failure.
2124 */
2125 lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )
2126 {
2127 lscp_midi_instrument_info_t *pInstrInfo;
2128 char szQuery[LSCP_BUFSIZ];
2129 const char *pszResult;
2130 const char *pszSeps = ":";
2131 const char *pszCrlf = "\r\n";
2132 char *pszToken;
2133 char *pch;
2134
2135 if (pClient == NULL)
2136 return NULL;
2137 if (pMidiInstr->map < 0)
2138 return NULL;
2139 if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2140 return NULL;
2141 if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2142 return NULL;
2143
2144 // Lock this section up.
2145 lscp_mutex_lock(pClient->mutex);
2146
2147 pInstrInfo = &(pClient->midi_instrument_info);
2148 lscp_midi_instrument_info_reset(pInstrInfo);
2149
2150 sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2151 pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2152 if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2153 pszResult = lscp_client_get_result(pClient);
2154 pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2155 while (pszToken) {
2156 if (strcasecmp(pszToken, "NAME") == 0) {
2157 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2158 if (pszToken)
2159 lscp_unquote_dup(&(pInstrInfo->name), &pszToken);
2160 }
2161 else if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
2162 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2163 if (pszToken)
2164 lscp_unquote_dup(&(pInstrInfo->engine_name), &pszToken);
2165 }
2166 else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
2167 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2168 if (pszToken)
2169 lscp_unquote_dup(&(pInstrInfo->instrument_file), &pszToken);
2170 }
2171 else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
2172 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2173 if (pszToken)
2174 pInstrInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
2175 }
2176 else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
2177 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2178 if (pszToken)
2179 lscp_unquote_dup(&(pInstrInfo->instrument_name), &pszToken);
2180 }
2181 else if (strcasecmp(pszToken, "LOAD_MODE") == 0) {
2182 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2183 if (pszToken) {
2184 pszToken = lscp_ltrim(pszToken);
2185 if (strcasecmp(pszToken, "ON_DEMAND") == 0)
2186 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND;
2187 else
2188 if (strcasecmp(pszToken, "ON_DEMAND_HOLD") == 0)
2189 pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND_HOLD;
2190 else
2191 if (strcasecmp(pszToken, "PERSISTENT") == 0)
2192 pInstrInfo->load_mode = LSCP_LOAD_PERSISTENT;
2193 else
2194 pInstrInfo->load_mode = LSCP_LOAD_DEFAULT;
2195 }
2196 }
2197 else if (strcasecmp(pszToken, "VOLUME") == 0) {
2198 pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2199 if (pszToken)
2200 pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));
2201 }
2202 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2203 }
2204 }
2205 else pInstrInfo = NULL;
2206
2207 // Unlock this section down.
2208 lscp_mutex_unlock(pClient->mutex);
2209
2210 return pInstrInfo;
2211 }
2212
2213
2214 /**
2215 * Clear the MIDI instrumnet map:
2216 * CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
2217 *
2218 * @param pClient Pointer to client instance structure.
2219 * @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2220 *
2221 * @returns LSCP_OK on success, LSCP_FAILED otherwise.
2222 */
2223 lscp_status_t lscp_clear_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2224 {
2225 char szQuery[LSCP_BUFSIZ];
2226
2227 strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
2228
2229 if (iMidiMap < 0)
2230 strcat(szQuery, "ALL");
2231 else
2232 sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2233
2234 strcat(szQuery, "\r\n");
2235
2236 return lscp_client_query(pClient, szQuery);
2237 }
2238
2239
2240 // end of client.c

  ViewVC Help
Powered by ViewVC