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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 978 by capela, Sun Dec 17 20:29:45 2006 UTC revision 3663 by schoenebeck, Sun Dec 22 12:41:28 2019 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This library is free software; you can redistribute it and/or     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    #include <sys/time.h>
26    
27  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
28  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
29    
30    
31    // Whether to use getaddrinfo() instead
32    // of deprecated gethostbyname()
33    #if !defined(WIN32)
34    #define USE_GETADDRINFO 1
35    #endif
36    
37    
38  // Local prototypes.  // Local prototypes.
39    
40  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
41    
42    static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
43    static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
44            int iSubscribe, lscp_event_t event);
45    
46    
47    //-------------------------------------------------------------------------
48    // General helper functions.
49    
50    struct _locale_t {
51            char numeric[32];
52            char ctype[32];
53    };
54    
55    // we need to ensure a constant locale setting e.g. for parsing
56    // floating point numbers with atof(), as the floating point separator
57    // character varies by the invidual locale settings
58    static void _save_and_set_c_locale(struct _locale_t* locale)
59    {
60            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
61            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
62            setlocale(LC_NUMERIC, "C");
63            setlocale(LC_CTYPE, "C");
64    }
65    
66    // restore the original locale setting as nothing happened
67    static void _restore_locale(struct _locale_t* locale)
68    {
69            setlocale(LC_NUMERIC, locale->numeric);
70            setlocale(LC_CTYPE, locale->ctype);
71    }
72    
73  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  // seems the standard atof() function doesnt care much about locale
74  static lscp_status_t    _lscp_client_evt_request    (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);  // runtime modifications, so we use this workaround
75    static float _atof(const char* txt) {
76            float f;
77            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
78            return f;
79    }
80    
81    
82  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 95  static void _lscp_client_evt_proc ( void
95          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
96          int    cchBuffer;          int    cchBuffer;
97          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
98          char * pszToken;          char  *pszToken;
99          char * pch;          char  *pch;
100          int     cchToken;          int    cchToken;
101    
102          lscp_event_t event;          lscp_event_t event;
103    
104  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 130  static void _lscp_client_evt_proc ( void
130                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
131                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
132                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
133                                  // Parse for the notification event message...                                  pch = achBuffer;
134                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
135                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
136                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
137                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
138                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
139                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
140                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
141                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
142                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
143                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
144                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
145                                                                  pClient,                                                          // Invoke the client event callback...
146                                                                  event,                                                          if ((*pClient->pfnCallback)(
147                                                                  pszToken,                                                                          pClient,
148                                                                  cchToken,                                                                          event,
149                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
150                                                          pClient->evt.iState = 0;                                                                          cchToken,
151                                                                            pClient->pvData) != LSCP_OK) {
152                                                                    pClient->evt.iState = 0;
153                                                            }
154                                                  }                                                  }
155                                          }                                          }
156                                  }                                  } while (*pch);
157                          } else {                          } else {
158                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
159                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
# Line 146  static lscp_status_t _lscp_client_evt_co Line 195  static lscp_status_t _lscp_client_evt_co
195          }          }
196    
197  #if defined(WIN32)  #if defined(WIN32)
198          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
199                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
200                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
201  #endif  #endif
202    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 224  static lscp_status_t _lscp_client_evt_co
224    
225    
226  // Subscribe to a single event.  // Subscribe to a single event.
227  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
228            int iSubscribe, lscp_event_t event )
229  {  {
230          const char *pszEvent;          const char *pszEvent;
231          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 240  static lscp_status_t _lscp_client_evt_re
240                  return LSCP_FAILED;                  return LSCP_FAILED;
241    
242          // Build the query string...          // Build the query string...
243          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
244                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
245          // Just send data, forget result...          // Just send data, forget result...
246          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
247                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 219  const char* lscp_client_package (void) { Line 271  const char* lscp_client_package (void) {
271  /** Retrieve the current client library version string. */  /** Retrieve the current client library version string. */
272  const char* lscp_client_version (void) { return LSCP_VERSION; }  const char* lscp_client_version (void) { return LSCP_VERSION; }
273    
274  /** Retrieve the current client library build timestamp string. */  /** Retrieve the current client library build string. */
275  const char* lscp_client_build   (void) { return __DATE__ " " __TIME__; }  const char* lscp_client_build   (void) { return LSCP_BUILD; }
276    
277    
278  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 240  const char* lscp_client_build   (void) { Line 292  const char* lscp_client_build   (void) {
292   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
293   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
294   */   */
295  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort,
296            lscp_client_proc_t pfnCallback, void *pvData )
297  {  {
298          lscp_client_t  *pClient;          lscp_client_t  *pClient;
299    #if defined(USE_GETADDRINFO)
300            char szPort[33];
301            struct addrinfo hints;
302            struct addrinfo *result, *res;
303    #else
304          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
305          struct sockaddr_in addr;          struct sockaddr_in addr;
306          int cAddr;          int cAddr;
307    #endif  /* !USE_GETADDRINFO */
308            lscp_socket_t sock;
309  #if defined(WIN32)  #if defined(WIN32)
310          int iSockOpt = (-1);          int iSockOpt = (-1);
311  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 315  lscp_client_t* lscp_client_create ( cons
315                  return NULL;                  return NULL;
316          }          }
317    
318    #if defined(USE_GETADDRINFO)
319    
320            // Convert port number to string/name...
321            snprintf(szPort, sizeof(szPort), "%d", iPort);
322    
323            // Obtain address(es) matching host/port...
324            memset(&hints, 0, sizeof(struct addrinfo));
325            hints.ai_family = AF_INET;
326            hints.ai_socktype = SOCK_STREAM;
327    
328            result = NULL;
329    
330            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
331                    lscp_socket_herror("lscp_client_create: getaddrinfo");
332                    return NULL;
333            }
334    
335    #else
336    
337            // Obtain host matching name...
338          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
339          if (pHost == NULL) {          if (pHost == NULL) {
340                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
341                  return NULL;                  return NULL;
342          }          }
343    
344    #endif  /* !USE_GETADDRINFO */
345    
346          // Allocate client descriptor...          // Allocate client descriptor...
347    
348          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
# Line 275  lscp_client_t* lscp_client_create ( cons Line 356  lscp_client_t* lscp_client_create ( cons
356          pClient->pvData = pvData;          pClient->pvData = pvData;
357    
358  #ifdef DEBUG  #ifdef DEBUG
359          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
360                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
361                     pClient, pszHost, iPort);
362  #endif  #endif
363    
364          // Prepare the command connection socket...          // Prepare the command connection socket...
365    
366    #if defined(USE_GETADDRINFO)
367    
368            // getaddrinfo() returns a list of address structures;
369            // try each address until we successfully connect(2);
370            // if socket or connect fails, we close the socket and
371            // try the next address...
372            sock = INVALID_SOCKET;
373    
374            for (res = result; res; res = res->ai_next) {
375                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
376                    if (sock == INVALID_SOCKET)
377                            continue;
378            #if defined(WIN32)
379                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
380                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
381                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
382            #endif
383            #ifdef DEBUG
384                    lscp_socket_getopts("lscp_client_create: cmd", sock);
385            #endif
386                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
387                            break;
388                    closesocket(sock);
389            }
390    
391            if (sock == INVALID_SOCKET) {
392                    lscp_socket_perror("lscp_client_create: cmd: socket");
393                    free(pClient);
394                    return NULL;
395            }
396    
397            if (res == NULL) {
398                    lscp_socket_perror("lscp_client_create: cmd: connect");
399                    free(pClient);
400                    return NULL;
401            }
402    
403            // Initialize the command socket agent struct...
404            lscp_socket_agent_init(&(pClient->cmd), sock,
405                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
406    
407            // No longer needed...
408            freeaddrinfo(result);
409    
410    #else
411    
412          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
413          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
414                  lscp_socket_perror("lscp_client_create: cmd: socket");                  lscp_socket_perror("lscp_client_create: cmd: socket");
# Line 288  lscp_client_t* lscp_client_create ( cons Line 417  lscp_client_t* lscp_client_create ( cons
417          }          }
418    
419  #if defined(WIN32)  #if defined(WIN32)
420          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
421                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
422                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
423  #endif  #endif
424    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 442  lscp_client_t* lscp_client_create ( cons
442          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
443          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
444    
445    #endif  /* !USE_GETADDRINFO */
446    
447  #ifdef DEBUG  #ifdef DEBUG
448          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));          fprintf(stderr,
449                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
450                    pClient, pClient->cmd.sock,
451                    inet_ntoa(pClient->cmd.addr.sin_addr),
452                    ntohs(pClient->cmd.addr.sin_port));
453  #endif  #endif
454    
455          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 327  lscp_client_t* lscp_client_create ( cons Line 463  lscp_client_t* lscp_client_create ( cons
463          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
464          pClient->engines = NULL;          pClient->engines = NULL;
465          pClient->channels = NULL;          pClient->channels = NULL;
466            pClient->fxsends = NULL;
467          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
468          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
469          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 343  lscp_client_t* lscp_client_create ( cons Line 480  lscp_client_t* lscp_client_create ( cons
480          lscp_server_info_init(&(pClient->server_info));          lscp_server_info_init(&(pClient->server_info));
481          lscp_engine_info_init(&(pClient->engine_info));          lscp_engine_info_init(&(pClient->engine_info));
482          lscp_channel_info_init(&(pClient->channel_info));          lscp_channel_info_init(&(pClient->channel_info));
483            lscp_fxsend_info_init(&(pClient->fxsend_info));
484          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
485          // Initialize error stuff.          // Initialize error stuff.
486          pClient->pszResult = NULL;          pClient->pszResult = NULL;
# Line 405  lscp_status_t lscp_client_destroy ( lscp Line 543  lscp_status_t lscp_client_destroy ( lscp
543    
544          // Free up all cached members.          // Free up all cached members.
545          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
546            lscp_fxsend_info_free(&(pClient->fxsend_info));
547          lscp_channel_info_free(&(pClient->channel_info));          lscp_channel_info_free(&(pClient->channel_info));
548          lscp_engine_info_free(&(pClient->engine_info));          lscp_engine_info_free(&(pClient->engine_info));
549          lscp_server_info_free(&(pClient->server_info));          lscp_server_info_free(&(pClient->server_info));
# Line 425  lscp_status_t lscp_client_destroy ( lscp Line 564  lscp_status_t lscp_client_destroy ( lscp
564          lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->midi_devices);
565          lscp_szsplit_destroy(pClient->engines);          lscp_szsplit_destroy(pClient->engines);
566          lscp_isplit_destroy(pClient->channels);          lscp_isplit_destroy(pClient->channels);
567            lscp_isplit_destroy(pClient->fxsends);
568          lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_midi_instruments_destroy(pClient->midi_instruments);
569          lscp_isplit_destroy(pClient->midi_maps);          lscp_isplit_destroy(pClient->midi_maps);
570          if (pClient->midi_map_name)          if (pClient->midi_map_name)
# Line 436  lscp_status_t lscp_client_destroy ( lscp Line 576  lscp_status_t lscp_client_destroy ( lscp
576          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
577          pClient->engines = NULL;          pClient->engines = NULL;
578          pClient->channels = NULL;          pClient->channels = NULL;
579            pClient->fxsends = NULL;
580          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
581          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
582          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 573  int lscp_client_get_errno ( lscp_client_ Line 714  int lscp_client_get_errno ( lscp_client_
714  // Client registration protocol functions.  // Client registration protocol functions.
715    
716  /**  /**
717   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
718   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
719   *      | CHANNEL_INFO | MISCELLANEOUS   *  for @e each event you want to subscribe. That is the old bitflag approach
720     *  was abondoned at this point. You can however still register all older
721     *  events with one lscp_client_subscribe() call at once. Thus, the old
722     *  behavior of this functions was not broken. Those older events are namely:
723     *  @code
724     *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
725     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
726     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
727     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
728     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
729     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
730     *      | MISCELLANEOUS
731     *  @endcode
732     *  The old events occupy the lower 16 bits (as bit flags), and all younger
733     *  events enumerate the whole upper 16 bits range. The new, enumerated
734     *  events are namely:
735     *  @code
736     *  SUBSCRIBE CHANNEL_MIDI
737     *  @endcode
738   *   *
739   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
740   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
741   *   *
742   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
743   */   */
744  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
745  {  {
746          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
747            lscp_event_t currentEvent;
748    
749          if (pClient == NULL)          if (pClient == NULL)
750                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 607  lscp_status_t lscp_client_subscribe ( ls Line 767  lscp_status_t lscp_client_subscribe ( ls
767                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
768          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
769                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
770            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
771                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
772            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
773                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
774            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
775                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
776            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
777                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
778            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
779                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
780            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
781                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
782            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
783                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
784            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
785                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
786            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
787                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
788          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
789                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
790            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
791            currentEvent = events & 0xffff0000;
792            if (ret == LSCP_OK && currentEvent) {
793                    switch (currentEvent) {
794                            case LSCP_EVENT_CHANNEL_MIDI:
795                            case LSCP_EVENT_DEVICE_MIDI:
796                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
797                                    break;
798                            default: // unknown "upper" event type
799                                    ret = LSCP_FAILED;
800                                    break;
801                    }
802            }
803    
804          // Unlock this section down.          // Unlock this section down.
805          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 618  lscp_status_t lscp_client_subscribe ( ls Line 809  lscp_status_t lscp_client_subscribe ( ls
809    
810    
811  /**  /**
812   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
813   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call
814   *      | CHANNEL_INFO | MISCELLANEOUS   *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
815     *  That is the old bitflag approach was abondoned at this point. You can
816     *  however still register all older events with one lscp_client_subscribe()
817     *  call at once. Thus, the old behavior of this functions was not broken.
818     *  Those older events are namely:
819     *  @code
820     *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
821     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
822     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
823     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
824     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
825     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
826     *      | MISCELLANEOUS
827     *  @endcode
828     *  The old events occupy the lower 16 bits (as bit flags), and all younger
829     *  events enumerate the whole upper 16 bits range. The new, enumerated
830     *  events are namely:
831     *  @code
832     *  UNSUBSCRIBE CHANNEL_MIDI
833     *  @endcode
834   *   *
835   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
836   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
837   *   *
838   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
839   */   */
840  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
841  {  {
842          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
843            lscp_event_t currentEvent;
844    
845          if (pClient == NULL)          if (pClient == NULL)
846                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 648  lscp_status_t lscp_client_unsubscribe ( Line 859  lscp_status_t lscp_client_unsubscribe (
859                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
860          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
861                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
862            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
863                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
864            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
865                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
866            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
867                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
868            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
869                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
870            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
871                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
872            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
873                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
874            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
875                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
876            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
877                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
878            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
879                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
880          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
881                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
882            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
883            currentEvent = events & 0xffff0000;
884            if (ret == LSCP_OK && currentEvent) {
885                    switch (currentEvent) {
886                            case LSCP_EVENT_CHANNEL_MIDI:
887                            case LSCP_EVENT_DEVICE_MIDI:
888                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
889                                    break;
890                            default: // unknown "upper" event type
891                                    ret = LSCP_FAILED;
892                                    break;
893                    }
894            }
895    
896          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
897          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 692  lscp_event_t lscp_client_get_events ( ls Line 934  lscp_event_t lscp_client_get_events ( ls
934   *   *
935   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
936   */   */
937  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient,
938            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
939  {  {
940          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
941    
942          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
943                  return LSCP_FAILED;                  return LSCP_FAILED;
944    
945          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
946                    pszFileName, iInstrIndex, iSamplerChannel);
947          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
948  }  }
949    
# Line 715  lscp_status_t lscp_load_instrument ( lsc Line 959  lscp_status_t lscp_load_instrument ( lsc
959   *   *
960   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
961   */   */
962  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient,
963            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
964  {  {
965          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
966    
967          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
968                  return LSCP_FAILED;                  return LSCP_FAILED;
969    
970          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n",
971                    pszFileName, iInstrIndex, iSamplerChannel);
972          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
973  }  }
974    
# Line 744  lscp_status_t lscp_load_engine ( lscp_cl Line 990  lscp_status_t lscp_load_engine ( lscp_cl
990          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
991                  return LSCP_FAILED;                  return LSCP_FAILED;
992    
993          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
994                    pszEngineName, iSamplerChannel);
995          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
996  }  }
997    
# Line 935  const char **lscp_list_available_engines Line 1182  const char **lscp_list_available_engines
1182   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the
1183   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1184   */   */
1185  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient,
1186            const char *pszEngineName )
1187  {  {
1188          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1189          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1002  lscp_channel_info_t *lscp_get_channel_in Line 1250  lscp_channel_info_t *lscp_get_channel_in
1250          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1251          char *pszToken;          char *pszToken;
1252          char *pch;          char *pch;
1253            struct _locale_t locale;
1254    
1255          if (pClient == NULL)          if (pClient == NULL)
1256                  return NULL;                  return NULL;
# Line 1014  lscp_channel_info_t *lscp_get_channel_in Line 1263  lscp_channel_info_t *lscp_get_channel_in
1263          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1264          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1265    
1266            _save_and_set_c_locale(&locale);
1267    
1268          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1269          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1270                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1038  lscp_channel_info_t *lscp_get_channel_in Line 1289  lscp_channel_info_t *lscp_get_channel_in
1289                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1290                                  if (pszToken) {                                  if (pszToken) {
1291                                          if (pChannelInfo->audio_routing)                                          if (pChannelInfo->audio_routing)
1292                                                  lscp_szsplit_destroy(pChannelInfo->audio_routing);                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1293                                          pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1294                                  }                                  }
1295                          }                          }
1296                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
# Line 1098  lscp_channel_info_t *lscp_get_channel_in Line 1349  lscp_channel_info_t *lscp_get_channel_in
1349                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1350                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1351                                  if (pszToken)                                  if (pszToken)
1352                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1353                          }                          }
1354                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1355                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1115  lscp_channel_info_t *lscp_get_channel_in Line 1366  lscp_channel_info_t *lscp_get_channel_in
1366          }          }
1367          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1368    
1369            _restore_locale(&locale);
1370    
1371          // Unlock this section up.          // Unlock this section up.
1372          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1373    
# Line 1258  int lscp_get_channel_stream_usage ( lscp Line 1511  int lscp_get_channel_stream_usage ( lscp
1511   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1512   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1513   */   */
1514  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient,
1515            lscp_usage_t usage_type, int iSamplerChannel )
1516  {  {
1517          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1518          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1331  lscp_buffer_fill_t *lscp_get_channel_buf Line 1585  lscp_buffer_fill_t *lscp_get_channel_buf
1585   *   *
1586   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1587   */   */
1588  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1589            int iSamplerChannel, const char *pszAudioDriver )
1590  {  {
1591          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1592    
1593          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1594                  return LSCP_FAILED;                  return LSCP_FAILED;
1595    
1596          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1597                    iSamplerChannel, pszAudioDriver);
1598          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1599  }  }
1600    
# Line 1353  lscp_status_t lscp_set_channel_audio_typ Line 1609  lscp_status_t lscp_set_channel_audio_typ
1609   *   *
1610   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1611   */   */
1612  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1613            int iSamplerChannel, int iAudioDevice )
1614  {  {
1615          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1616    
1617          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1618                  return LSCP_FAILED;                  return LSCP_FAILED;
1619    
1620          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1621                    iSamplerChannel, iAudioDevice);
1622          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1623  }  }
1624    
# Line 1376  lscp_status_t lscp_set_channel_audio_dev Line 1634  lscp_status_t lscp_set_channel_audio_dev
1634   *   *
1635   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1636   */   */
1637  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1638            int iSamplerChannel, int iAudioOut, int iAudioIn )
1639  {  {
1640          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1641    
1642          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1643                  return LSCP_FAILED;                  return LSCP_FAILED;
1644    
1645          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n",
1646                    iSamplerChannel, iAudioOut, iAudioIn);
1647          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1648  }  }
1649    
# Line 1398  lscp_status_t lscp_set_channel_audio_cha Line 1658  lscp_status_t lscp_set_channel_audio_cha
1658   *   *
1659   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1660   */   */
1661  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1662            int iSamplerChannel, const char *pszMidiDriver )
1663  {  {
1664          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1665    
1666          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1667                  return LSCP_FAILED;                  return LSCP_FAILED;
1668    
1669          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1670                    iSamplerChannel, pszMidiDriver);
1671          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1672  }  }
1673    
# Line 1420  lscp_status_t lscp_set_channel_midi_type Line 1682  lscp_status_t lscp_set_channel_midi_type
1682   *   *
1683   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1684   */   */
1685  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1686            int iSamplerChannel, int iMidiDevice )
1687  {  {
1688          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1689    
1690          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1691                  return LSCP_FAILED;                  return LSCP_FAILED;
1692    
1693          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1694                    iSamplerChannel, iMidiDevice);
1695          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1696  }  }
1697    
# Line 1442  lscp_status_t lscp_set_channel_midi_devi Line 1706  lscp_status_t lscp_set_channel_midi_devi
1706   *   *
1707   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1708   */   */
1709  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1710            int iSamplerChannel, int iMidiPort )
1711  {  {
1712          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1713    
1714          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1715                  return LSCP_FAILED;                  return LSCP_FAILED;
1716    
1717          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1718                    iSamplerChannel, iMidiPort);
1719          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1720  }  }
1721    
# Line 1465  lscp_status_t lscp_set_channel_midi_port Line 1731  lscp_status_t lscp_set_channel_midi_port
1731   *   *
1732   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1733   */   */
1734  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient,
1735            int iSamplerChannel, int iMidiChannel )
1736  {  {
1737          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1738    
# Line 1473  lscp_status_t lscp_set_channel_midi_chan Line 1740  lscp_status_t lscp_set_channel_midi_chan
1740                  return LSCP_FAILED;                  return LSCP_FAILED;
1741    
1742          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1743                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1744                            iSamplerChannel);
1745          else          else
1746                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1747                            iSamplerChannel, iMidiChannel);
1748          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1749  }  }
1750    
# Line 1492  lscp_status_t lscp_set_channel_midi_chan Line 1761  lscp_status_t lscp_set_channel_midi_chan
1761   *   *
1762   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1763   */   */
1764  lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient, int iSamplerChannel, int iMidiMap )  lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1765            int iSamplerChannel, int iMidiMap )
1766  {  {
1767          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1768    
# Line 1526  lscp_status_t lscp_set_channel_midi_map Line 1796  lscp_status_t lscp_set_channel_midi_map
1796   *   *
1797   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1798   */   */
1799  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient,
1800            int iSamplerChannel, float fVolume )
1801  {  {
1802          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1803            struct _locale_t locale;
1804    
1805          if (iSamplerChannel < 0 || fVolume < 0.0)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1806                  return LSCP_FAILED;                  return LSCP_FAILED;
1807    
1808          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1809            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1810                    iSamplerChannel, fVolume);
1811            _restore_locale(&locale);
1812    
1813          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1814  }  }
1815    
# Line 1550  lscp_status_t lscp_set_channel_volume ( Line 1826  lscp_status_t lscp_set_channel_volume (
1826   *   *
1827   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1828   */   */
1829  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1830            int iSamplerChannel, int iMute )
1831  {  {
1832          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1833    
1834          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1835                  return LSCP_FAILED;                  return LSCP_FAILED;
1836    
1837          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1838                    iSamplerChannel, iMute);
1839          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1840  }  }
1841    
# Line 1574  lscp_status_t lscp_set_channel_mute ( ls Line 1852  lscp_status_t lscp_set_channel_mute ( ls
1852   *   *
1853   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1854   */   */
1855  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient,
1856            int iSamplerChannel, int iSolo )
1857  {  {
1858          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1859    
1860          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1861                  return LSCP_FAILED;                  return LSCP_FAILED;
1862    
1863          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1864                    iSamplerChannel, iSolo);
1865          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1866  }  }
1867    
# Line 1617  lscp_status_t lscp_reset_channel ( lscp_ Line 1897  lscp_status_t lscp_reset_channel ( lscp_
1897   */   */
1898  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1899  {  {
1900            // Do actual whole sampler reset...
1901          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1902  }  }
1903    
# Line 1738  int lscp_get_total_voice_count_max ( lsc Line 2019  int lscp_get_total_voice_count_max ( lsc
2019    
2020    
2021  /**  /**
2022     *  Get global volume attenuation:
2023     *  GET VOLUME
2024     *
2025     *  @param pClient  Pointer to client instance structure.
2026     *
2027     *  @returns The global volume as positive floating point value usually in
2028     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2029     */
2030    float lscp_get_volume ( lscp_client_t *pClient )
2031    {
2032            float fVolume = 0.0f;
2033            struct _locale_t locale;
2034    
2035            if (pClient == NULL)
2036                    return 0.0f;
2037    
2038            // Lock this section up.
2039            lscp_mutex_lock(pClient->mutex);
2040    
2041            _save_and_set_c_locale(&locale);
2042    
2043            if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2044                    fVolume = _atof(lscp_client_get_result(pClient));
2045    
2046            _restore_locale(&locale);
2047    
2048            // Unlock this section down.
2049            lscp_mutex_unlock(pClient->mutex);
2050    
2051            return fVolume;
2052    }
2053    
2054    
2055    /**
2056     *  Setting global volume attenuation:
2057     *  SET VOLUME <volume>
2058     *
2059     *  @param pClient  Pointer to client instance structure.
2060     *  @param fVolume  Global volume parameter as positive floating point
2061     *                  value usually be in the range between 0.0 and 1.0,
2062     *                  that is for attenuating the overall volume.
2063     *
2064     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2065     */
2066    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2067    {
2068            char szQuery[LSCP_BUFSIZ];
2069            struct _locale_t locale;
2070    
2071            if (fVolume < 0.0f)
2072                    return LSCP_FAILED;
2073    
2074            _save_and_set_c_locale(&locale);
2075            sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2076            _restore_locale(&locale);
2077    
2078            return lscp_client_query(pClient, szQuery);
2079    }
2080    
2081    
2082    /**
2083     *  Get global voice limit setting:
2084     *  @code
2085     *  GET VOICES
2086     *  @endcode
2087     *  This value reflects the maximum amount of voices a sampler engine
2088     *  processes simultaniously before voice stealing kicks in.
2089     *
2090     *  @param pClient  Pointer to client instance structure.
2091     *
2092     *  @returns The current global maximum amount of voices limit or a
2093     *           negative value on error (e.g. if sampler doesn't support
2094     *           this command).
2095     */
2096    int lscp_get_voices ( lscp_client_t *pClient )
2097    {
2098            int iVoices = -1;
2099    
2100            if (pClient == NULL)
2101                    return -1;
2102    
2103            // Lock this section up.
2104            lscp_mutex_lock(pClient->mutex);
2105    
2106            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2107                    iVoices = atoi(lscp_client_get_result(pClient));
2108    
2109            // Unlock this section down.
2110            lscp_mutex_unlock(pClient->mutex);
2111    
2112            return iVoices;
2113    }
2114    
2115    
2116    /**
2117     *  Setting global voice limit setting:
2118     *  @code
2119     *  SET VOICES <max-voices>
2120     *  @endcode
2121     *  This value reflects the maximum amount of voices a sampler engine
2122     *  processes simultaniously before voice stealing kicks in. Note that
2123     *  this value will be passed to all sampler engine instances, that is
2124     *  the total amount of maximum voices on the running system is thus
2125     *  @param iMaxVoices multiplied with the current amount of sampler
2126     *  engine instances.
2127     *
2128     *  @param pClient     Pointer to client instance structure.
2129     *  @param iMaxVoices  Global voice limit setting as integer value larger
2130     *                     or equal to 1.
2131     *
2132     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2133     */
2134    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2135    {
2136            char szQuery[LSCP_BUFSIZ];
2137    
2138            if (iMaxVoices < 1)
2139                    return LSCP_FAILED;
2140    
2141            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2142            return lscp_client_query(pClient, szQuery);
2143    }
2144    
2145    
2146    /**
2147     *  Get global disk streams limit setting:
2148     *  @code
2149     *  GET STREAMS
2150     *  @endcode
2151     *  This value reflects the maximum amount of disk streams a sampler
2152     *  engine processes simultaniously.
2153     *
2154     *  @param pClient  Pointer to client instance structure.
2155     *
2156     *  @returns The current global maximum amount of disk streams limit
2157     *           or a negative value on error (e.g. if sampler doesn't
2158     *           support this command).
2159     */
2160    int lscp_get_streams ( lscp_client_t *pClient )
2161    {
2162            int iStreams = -1;
2163    
2164            if (pClient == NULL)
2165                    return -1;
2166    
2167            // Lock this section up.
2168            lscp_mutex_lock(pClient->mutex);
2169    
2170            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2171                    iStreams = atoi(lscp_client_get_result(pClient));
2172    
2173            // Unlock this section down.
2174            lscp_mutex_unlock(pClient->mutex);
2175    
2176            return iStreams;
2177    }
2178    
2179    
2180    /**
2181     *  Setting global disk streams limit setting:
2182     *  @code
2183     *  SET STREAMS <max-streams>
2184     *  @endcode
2185     *  This value reflects the maximum amount of dist streams a sampler
2186     *  engine instance processes simultaniously. Note that this value will
2187     *  be passed to all sampler engine instances, that is the total amount
2188     *  of maximum disk streams on the running system is thus
2189     *  @param iMaxStreams multiplied with the current amount of sampler
2190     *  engine instances.
2191     *
2192     *  @param pClient      Pointer to client instance structure.
2193     *  @param iMaxStreams  Global streams limit setting as positive integer
2194     *                      value (larger or equal to 0).
2195     *
2196     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2197     */
2198    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2199    {
2200            char szQuery[LSCP_BUFSIZ];
2201    
2202            if (iMaxStreams < 0)
2203                    return LSCP_FAILED;
2204    
2205            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2206            return lscp_client_query(pClient, szQuery);
2207    }
2208    
2209    
2210    /**
2211     *  Add an effect send to a sampler channel:
2212     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2213     *
2214     *  @param pClient          Pointer to client instance structure.
2215     *  @param iSamplerChannel  Sampler channel number.
2216     *  @param iMidiController  MIDI controller used to alter the effect,
2217     *                          usually a number between 0 and 127.
2218     *  @param pszFxName        Optional name for the effect send entity,
2219     *                          does not have to be unique.
2220     *
2221     *  @returns The new effect send number identifier, or -1 in case of failure.
2222     */
2223    int lscp_create_fxsend ( lscp_client_t *pClient,
2224            int iSamplerChannel, int iMidiController, const char *pszFxName )
2225    {
2226            int iFxSend = -1;
2227            char szQuery[LSCP_BUFSIZ];
2228    
2229            if (pClient == NULL)
2230                    return -1;
2231            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2232                    return -1;
2233    
2234            // Lock this section up.
2235            lscp_mutex_lock(pClient->mutex);
2236    
2237            sprintf(szQuery, "CREATE FX_SEND %d %d",
2238                    iSamplerChannel, iMidiController);
2239    
2240            if (pszFxName)
2241                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2242    
2243            strcat(szQuery, "\r\n");
2244    
2245            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2246                    iFxSend = atoi(lscp_client_get_result(pClient));
2247    
2248            // Unlock this section down.
2249            lscp_mutex_unlock(pClient->mutex);
2250    
2251            return iFxSend;
2252    }
2253    
2254    
2255    /**
2256     *  Remove an effect send from a sampler channel:
2257     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2258     *
2259     *  @param pClient          Pointer to client instance structure.
2260     *  @param iSamplerChannel  Sampler channel number.
2261     *  @param iFxSend          Effect send number.
2262     *
2263     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2264     */
2265    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2266            int iSamplerChannel, int iFxSend )
2267    {
2268            char szQuery[LSCP_BUFSIZ];
2269    
2270            if (iSamplerChannel < 0 || iFxSend < 0)
2271                    return LSCP_FAILED;
2272    
2273            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2274                    iSamplerChannel, iFxSend);
2275    
2276            return lscp_client_query(pClient, szQuery);
2277    }
2278    
2279    
2280    /**
2281     *  Get amount of effect sends on a sampler channel:
2282     *  GET FX_SENDS <sampler-channel>
2283     *
2284     *  @param pClient          Pointer to client instance structure.
2285     *  @param iSamplerChannel  Sampler channel number.
2286     *
2287     *  @returns The current total number of effect sends of the sampler channel
2288     *  on success, -1 otherwise.
2289     */
2290    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2291    {
2292            int iFxSends = -1;
2293            char szQuery[LSCP_BUFSIZ];
2294    
2295            if (pClient == NULL)
2296                    return -1;
2297            if (iSamplerChannel < 0)
2298                    return -1;
2299    
2300            // Lock this section up.
2301            lscp_mutex_lock(pClient->mutex);
2302    
2303            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2304    
2305            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2306                    iFxSends = atoi(lscp_client_get_result(pClient));
2307    
2308            // Unlock this section doen.
2309            lscp_mutex_unlock(pClient->mutex);
2310    
2311            return iFxSends;
2312    }
2313    
2314    
2315    /**
2316     *  List all effect sends on a sampler channel:
2317     *  LIST FX_SENDS <sampler-channel>
2318     *
2319     *  @param pClient          Pointer to client instance structure.
2320     *  @param iSamplerChannel  Sampler channel number.
2321     *
2322     *  @returns An array of the effect sends identifiers as positive integers,
2323     *  terminated with -1 on success, NULL otherwise.
2324     */
2325    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2326    {
2327            const char *pszSeps = ",";
2328            char szQuery[LSCP_BUFSIZ];
2329    
2330            if (pClient == NULL)
2331                    return NULL;
2332    
2333            // Lock this section up.
2334            lscp_mutex_lock(pClient->mutex);
2335    
2336            if (pClient->fxsends) {
2337                    lscp_isplit_destroy(pClient->fxsends);
2338                    pClient->fxsends = NULL;
2339            }
2340    
2341            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2342    
2343            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2344                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2345    
2346            // Unlock this section down.
2347            lscp_mutex_unlock(pClient->mutex);
2348    
2349            return pClient->fxsends;
2350    }
2351    
2352    
2353    /**
2354     *  Getting effect send information
2355     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2356     *
2357     *  @param pClient          Pointer to client instance structure.
2358     *  @param iSamplerChannel  Sampler channel number.
2359     *  @param iFxSend          Effect send number.
2360     *
2361     *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2362     *  information of the given FX send, or NULL in case of failure.
2363     */
2364    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2365            int iSamplerChannel, int iFxSend )
2366    {
2367            lscp_fxsend_info_t *pFxSendInfo;
2368            char szQuery[LSCP_BUFSIZ];
2369            const char *pszResult;
2370            const char *pszSeps = ":";
2371            const char *pszCrlf = "\r\n";
2372            char *pszToken;
2373            char *pch;
2374            struct _locale_t locale;
2375    
2376            if (pClient == NULL)
2377                    return NULL;
2378            if (iSamplerChannel < 0 || iFxSend < 0)
2379                    return NULL;
2380    
2381            // Lock this section up.
2382            lscp_mutex_lock(pClient->mutex);
2383    
2384            _save_and_set_c_locale(&locale);
2385    
2386            pFxSendInfo = &(pClient->fxsend_info);
2387            lscp_fxsend_info_reset(pFxSendInfo);
2388    
2389            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2390            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2391                    pszResult = lscp_client_get_result(pClient);
2392                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2393                    while (pszToken) {
2394                            if (strcasecmp(pszToken, "NAME") == 0) {
2395                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2396                                    if (pszToken)
2397                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2398                            }
2399                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2400                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2401                                    if (pszToken)
2402                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2403                            }
2404                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2405                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2406                                    if (pszToken) {
2407                                            if (pFxSendInfo->audio_routing)
2408                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2409                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2410                                    }
2411                            }
2412                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2413                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2414                                    if (pszToken)
2415                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2416                            }
2417                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2418                    }
2419            }
2420            else pFxSendInfo = NULL;
2421    
2422            _restore_locale(&locale);
2423    
2424            // Unlock this section up.
2425            lscp_mutex_unlock(pClient->mutex);
2426    
2427            return pFxSendInfo;
2428    }
2429    
2430    
2431    /**
2432     *  Alter effect send's name:
2433     *  @code
2434     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2435     *  @endcode
2436     *
2437     *  @param pClient          Pointer to client instance structure.
2438     *  @param iSamplerChannel  Sampler channel number.
2439     *  @param iFxSend          Effect send number.
2440     *  @param pszFxName        Effect send's new name.
2441     *
2442     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2443     */
2444    lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2445            int iSamplerChannel, int iFxSend, const char *pszFxName )
2446    {
2447            char szQuery[LSCP_BUFSIZ];
2448    
2449            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2450                    return LSCP_FAILED;
2451    
2452            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2453                    iSamplerChannel, iFxSend, pszFxName);
2454            return lscp_client_query(pClient, szQuery);
2455    }
2456    
2457    
2458    /**
2459     *  Alter effect send's audio routing:
2460     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2461     *    <audio-src> <audio-dst>
2462     *
2463     *  @param pClient          Pointer to client instance structure.
2464     *  @param iSamplerChannel  Sampler channel number.
2465     *  @param iFxSend          Effect send number.
2466     *  @param iAudioSrc        Audio output device channel to be routed from.
2467     *  @param iAudioDst        Audio output device channel to be routed into.
2468     *
2469     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2470     */
2471    lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2472            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2473    {
2474            char szQuery[LSCP_BUFSIZ];
2475    
2476            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2477                    return LSCP_FAILED;
2478    
2479            sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2480                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2481            return lscp_client_query(pClient, szQuery);
2482    }
2483    
2484    
2485    /**
2486     *  Alter effect send's MIDI controller:
2487     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2488     *
2489     *  @param pClient          Pointer to client instance structure.
2490     *  @param iSamplerChannel  Sampler channel number.
2491     *  @param iFxSend          Effect send number.
2492     *  @param iMidiController  MIDI controller used to alter the effect,
2493     *                          usually a number between 0 and 127.
2494     *
2495     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2496     */
2497    lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2498            int iSamplerChannel, int iFxSend, int iMidiController )
2499    {
2500            char szQuery[LSCP_BUFSIZ];
2501    
2502            if (iSamplerChannel < 0 || iFxSend < 0 ||
2503                    iMidiController < 0 || iMidiController > 127)
2504                    return LSCP_FAILED;
2505    
2506            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2507                    iSamplerChannel, iFxSend, iMidiController);
2508            return lscp_client_query(pClient, szQuery);
2509    }
2510    
2511    
2512    /**
2513     *  Alter effect send's audio level:
2514     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2515     *
2516     *  @param pClient          Pointer to client instance structure.
2517     *  @param iSamplerChannel  Sampler channel number.
2518     *  @param iFxSend          Effect send number.
2519     *  @param fLevel           Effect send volume level.
2520     *
2521     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2522     */
2523    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2524            int iSamplerChannel, int iFxSend, float fLevel )
2525    {
2526            char szQuery[LSCP_BUFSIZ];
2527            struct _locale_t locale;
2528    
2529            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2530                    return LSCP_FAILED;
2531    
2532            _save_and_set_c_locale(&locale);
2533            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2534                    iSamplerChannel, iFxSend, fLevel);
2535            _restore_locale(&locale);
2536    
2537            return lscp_client_query(pClient, szQuery);
2538    }
2539    
2540    
2541    /**
2542   *  Create a new MIDI instrument map:   *  Create a new MIDI instrument map:
2543   *  ADD MIDI_INSTRUMENT_MAP [<name>]   *  ADD MIDI_INSTRUMENT_MAP [<name>]
2544   *   *
# Line 1759  int lscp_add_midi_instrument_map ( lscp_ Line 2560  int lscp_add_midi_instrument_map ( lscp_
2560          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2561    
2562          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2563            
2564          if (pszMapName)          if (pszMapName)
2565                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2566    
# Line 1885  const char *lscp_get_midi_instrument_map Line 2686  const char *lscp_get_midi_instrument_map
2686    
2687          // Lock this section up.          // Lock this section up.
2688          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2689            
2690          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2691                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2692                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
2693          }          }
2694    
2695          sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);          sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
2696          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2697                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
2698                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2699                  while (pszToken) {                  while (pszToken) {
# Line 1949  lscp_status_t lscp_set_midi_instrument_m Line 2750  lscp_status_t lscp_set_midi_instrument_m
2750   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2751   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2752   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2753   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2754   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2755   *                          1.0 for amplification.   *                          1.0 for amplification.
2756   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 1961  lscp_status_t lscp_set_midi_instrument_m Line 2762  lscp_status_t lscp_set_midi_instrument_m
2762   *   *
2763   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2764   */   */
2765  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 )  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient,
2766            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2767            const char *pszFileName, int iInstrIndex, float fVolume,
2768            lscp_load_mode_t load_mode, const char *pszName )
2769  {  {
2770          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2771            struct _locale_t locale;
2772    
2773          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2774                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 1977  lscp_status_t lscp_map_midi_instrument ( Line 2782  lscp_status_t lscp_map_midi_instrument (
2782          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2783                  fVolume = 1.0f;                  fVolume = 1.0f;
2784    
2785            _save_and_set_c_locale(&locale);
2786          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2787                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2788                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2789            _restore_locale(&locale);
2790    
2791          switch (load_mode) {          switch (load_mode) {
2792          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2014  lscp_status_t lscp_map_midi_instrument ( Line 2821  lscp_status_t lscp_map_midi_instrument (
2821   *   *
2822   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2823   */   */
2824  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient,
2825            lscp_midi_instrument_t *pMidiInstr )
2826  {  {
2827          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2828    
# Line 2107  lscp_midi_instrument_t *lscp_list_midi_i Line 2915  lscp_midi_instrument_t *lscp_list_midi_i
2915          strcat(szQuery, "\r\n");          strcat(szQuery, "\r\n");
2916    
2917          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2918                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));                  pClient->midi_instruments = lscp_midi_instruments_create(
2919                            lscp_client_get_result(pClient));
2920    
2921          // Unlock this section down.          // Unlock this section down.
2922          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 2127  lscp_midi_instrument_t *lscp_list_midi_i Line 2936  lscp_midi_instrument_t *lscp_list_midi_i
2936   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2937   *  or NULL in case of failure.   *  or NULL in case of failure.
2938   */   */
2939  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient,
2940            lscp_midi_instrument_t *pMidiInstr )
2941  {  {
2942          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2943          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2136  lscp_midi_instrument_info_t *lscp_get_mi Line 2946  lscp_midi_instrument_info_t *lscp_get_mi
2946          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2947          char *pszToken;          char *pszToken;
2948          char *pch;          char *pch;
2949            struct _locale_t locale;
2950    
2951          if (pClient == NULL)          if (pClient == NULL)
2952                  return NULL;                  return NULL;
# Line 2148  lscp_midi_instrument_info_t *lscp_get_mi Line 2959  lscp_midi_instrument_info_t *lscp_get_mi
2959    
2960          // Lock this section up.          // Lock this section up.
2961          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2962            
2963            _save_and_set_c_locale(&locale);
2964    
2965          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2966          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2967    
# Line 2202  lscp_midi_instrument_info_t *lscp_get_mi Line 3015  lscp_midi_instrument_info_t *lscp_get_mi
3015                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3016                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3017                                  if (pszToken)                                  if (pszToken)
3018                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3019                          }                          }
3020                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3021                  }                  }
3022          }          }
3023          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3024    
3025            _restore_locale(&locale);
3026    
3027          // Unlock this section down.          // Unlock this section down.
3028          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3029    
# Line 2240  lscp_status_t lscp_clear_midi_instrument Line 3055  lscp_status_t lscp_clear_midi_instrument
3055    
3056          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
3057  }  }
3058    
3059    
3060    /**
3061     * Open an instrument editor application for the instrument
3062     * on the given sampler channel:
3063     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3064     *
3065     * @param pClient         Pointer to client instance structure.
3066     * @param iSamplerChannel Sampler Channel.
3067     *
3068     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3069     */
3070    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3071    {
3072            char szQuery[LSCP_BUFSIZ];
3073    
3074            if (iSamplerChannel < 0)
3075                    return LSCP_FAILED;
3076    
3077            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3078    
3079            return lscp_client_query(pClient, szQuery);
3080    }
3081    
3082    
3083  // end of client.c  // end of client.c

Legend:
Removed from v.978  
changed lines
  Added in v.3663

  ViewVC Help
Powered by ViewVC