/[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 1665 by schoenebeck, Mon Feb 4 13:02:30 2008 UTC revision 3665 by schoenebeck, Sun Dec 22 13:01:23 2019 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-2008, 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    #ifdef WIN32
27    # include <errno.h>
28    #else
29    # include <sys/errno.h>
30    #endif
31    
32    
33  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
34  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
35    
36    
37    // Whether to use getaddrinfo() instead
38    // of deprecated gethostbyname()
39    #if !defined(WIN32)
40    #define USE_GETADDRINFO 1
41    #endif
42    
43    
44  // Local prototypes.  // Local prototypes.
45    
46  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
47    
48  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
49  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,
50            int iSubscribe, lscp_event_t event);
51    
52    
53    //-------------------------------------------------------------------------
54    // General helper functions.
55    
56    struct _locale_t {
57            char numeric[32];
58            char ctype[32];
59    };
60    
61    // we need to ensure a constant locale setting e.g. for parsing
62    // floating point numbers with atof(), as the floating point separator
63    // character varies by the invidual locale settings
64    static void _save_and_set_c_locale(struct _locale_t* locale)
65    {
66            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
67            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
68            setlocale(LC_NUMERIC, "C");
69            setlocale(LC_CTYPE, "C");
70    }
71    
72    // restore the original locale setting as nothing happened
73    static void _restore_locale(struct _locale_t* locale)
74    {
75            setlocale(LC_NUMERIC, locale->numeric);
76            setlocale(LC_CTYPE, locale->ctype);
77    }
78    
79    // seems the standard atof() function doesnt care much about locale
80    // runtime modifications, so we use this workaround
81    static float _atof(const char* txt) {
82            float f;
83            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
84            return f;
85    }
86    
87    
88  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 101  static void _lscp_client_evt_proc ( void
101          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
102          int    cchBuffer;          int    cchBuffer;
103          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
104          char * pszToken;          char  *pszToken;
105          char * pch;          char  *pch;
106          int     cchToken;          int    cchToken;
107    
108          lscp_event_t event;          lscp_event_t event;
109    
110  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 136  static void _lscp_client_evt_proc ( void
136                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
137                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
138                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
139                                  // Parse for the notification event message...                                  pch = achBuffer;
140                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
141                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
142                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
143                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
144                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
145                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
146                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
147                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
148                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
149                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
150                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
151                                                                  pClient,                                                          // Invoke the client event callback...
152                                                                  event,                                                          if ((*pClient->pfnCallback)(
153                                                                  pszToken,                                                                          pClient,
154                                                                  cchToken,                                                                          event,
155                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
156                                                          pClient->evt.iState = 0;                                                                          cchToken,
157                                                                            pClient->pvData) != LSCP_OK) {
158                                                                    pClient->evt.iState = 0;
159                                                            }
160                                                  }                                                  }
161                                          }                                          }
162                                  }                                  } while (*pch);
163                          } else {                          } else {
164                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
165                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
166                                    pClient->iErrno = -errno;
167                          }                          }
168                  }   // Check if select has in error.                  }   // Check if select has in error.
169                  else if (iSelect < 0) {                  else if (iSelect < 0) {
170                          lscp_socket_perror("_lscp_client_evt_proc: select");                          lscp_socket_perror("_lscp_client_evt_proc: select");
171                          pClient->evt.iState = 0;                          pClient->evt.iState = 0;
172                            pClient->iErrno = -errno;
173                  }                  }
174    
175                  // Finally, always signal the event.                  // Finally, always signal the event.
# Line 146  static lscp_status_t _lscp_client_evt_co Line 203  static lscp_status_t _lscp_client_evt_co
203          }          }
204    
205  #if defined(WIN32)  #if defined(WIN32)
206          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
207                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
208                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
209  #endif  #endif
210    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 232  static lscp_status_t _lscp_client_evt_co
232    
233    
234  // Subscribe to a single event.  // Subscribe to a single event.
235  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,
236            int iSubscribe, lscp_event_t event )
237  {  {
238          const char *pszEvent;          const char *pszEvent;
239          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 248  static lscp_status_t _lscp_client_evt_re
248                  return LSCP_FAILED;                  return LSCP_FAILED;
249    
250          // Build the query string...          // Build the query string...
251          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
252                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
253          // Just send data, forget result...          // Just send data, forget result...
254          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
255                  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 279  const char* lscp_client_package (void) {
279  /** Retrieve the current client library version string. */  /** Retrieve the current client library version string. */
280  const char* lscp_client_version (void) { return LSCP_VERSION; }  const char* lscp_client_version (void) { return LSCP_VERSION; }
281    
282  /** Retrieve the current client library build timestamp string. */  /** Retrieve the current client library build string. */
283  const char* lscp_client_build   (void) { return __DATE__ " " __TIME__; }  const char* lscp_client_build   (void) { return LSCP_BUILD; }
284    
285    
286  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 240  const char* lscp_client_build   (void) { Line 300  const char* lscp_client_build   (void) {
300   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
301   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
302   */   */
303  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,
304            lscp_client_proc_t pfnCallback, void *pvData )
305  {  {
306          lscp_client_t  *pClient;          lscp_client_t  *pClient;
307    #if defined(USE_GETADDRINFO)
308            char szPort[33];
309            struct addrinfo hints;
310            struct addrinfo *result, *res;
311    #else
312          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
313          struct sockaddr_in addr;          struct sockaddr_in addr;
314          int cAddr;          int cAddr;
315    #endif  /* !USE_GETADDRINFO */
316            lscp_socket_t sock;
317  #if defined(WIN32)  #if defined(WIN32)
318          int iSockOpt = (-1);          int iSockOpt = (-1);
319  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 323  lscp_client_t* lscp_client_create ( cons
323                  return NULL;                  return NULL;
324          }          }
325    
326    #if defined(USE_GETADDRINFO)
327    
328            // Convert port number to string/name...
329            snprintf(szPort, sizeof(szPort), "%d", iPort);
330    
331            // Obtain address(es) matching host/port...
332            memset(&hints, 0, sizeof(struct addrinfo));
333            hints.ai_family = AF_INET;
334            hints.ai_socktype = SOCK_STREAM;
335    
336            result = NULL;
337    
338            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
339                    lscp_socket_herror("lscp_client_create: getaddrinfo");
340                    return NULL;
341            }
342    
343    #else
344    
345            // Obtain host matching name...
346          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
347          if (pHost == NULL) {          if (pHost == NULL) {
348                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
349                  return NULL;                  return NULL;
350          }          }
351    
352    #endif  /* !USE_GETADDRINFO */
353    
354          // Allocate client descriptor...          // Allocate client descriptor...
355    
356          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 364  lscp_client_t* lscp_client_create ( cons
364          pClient->pvData = pvData;          pClient->pvData = pvData;
365    
366  #ifdef DEBUG  #ifdef DEBUG
367          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
368                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
369                     pClient, pszHost, iPort);
370  #endif  #endif
371    
372          // Prepare the command connection socket...          // Prepare the command connection socket...
373    
374    #if defined(USE_GETADDRINFO)
375    
376            // getaddrinfo() returns a list of address structures;
377            // try each address until we successfully connect(2);
378            // if socket or connect fails, we close the socket and
379            // try the next address...
380            sock = INVALID_SOCKET;
381    
382            for (res = result; res; res = res->ai_next) {
383                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
384                    if (sock == INVALID_SOCKET)
385                            continue;
386            #if defined(WIN32)
387                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
388                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
389                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
390            #endif
391            #ifdef DEBUG
392                    lscp_socket_getopts("lscp_client_create: cmd", sock);
393            #endif
394                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
395                            break;
396                    closesocket(sock);
397            }
398    
399            if (sock == INVALID_SOCKET) {
400                    lscp_socket_perror("lscp_client_create: cmd: socket");
401                    free(pClient);
402                    return NULL;
403            }
404    
405            if (res == NULL) {
406                    lscp_socket_perror("lscp_client_create: cmd: connect");
407                    free(pClient);
408                    return NULL;
409            }
410    
411            // Initialize the command socket agent struct...
412            lscp_socket_agent_init(&(pClient->cmd), sock,
413                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
414    
415            // No longer needed...
416            freeaddrinfo(result);
417    
418    #else
419    
420          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
421          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
422                  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 425  lscp_client_t* lscp_client_create ( cons
425          }          }
426    
427  #if defined(WIN32)  #if defined(WIN32)
428          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
429                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
430                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
431  #endif  #endif
432    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 450  lscp_client_t* lscp_client_create ( cons
450          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
451          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
452    
453    #endif  /* !USE_GETADDRINFO */
454    
455  #ifdef DEBUG  #ifdef DEBUG
456          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,
457                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
458                    pClient, pClient->cmd.sock,
459                    inet_ntoa(pClient->cmd.addr.sin_addr),
460                    ntohs(pClient->cmd.addr.sin_port));
461  #endif  #endif
462    
463          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 503  int lscp_client_get_timeout ( lscp_clien Line 647  int lscp_client_get_timeout ( lscp_clien
647          return pClient->iTimeout;          return pClient->iTimeout;
648  }  }
649    
650    /**
651     *  Check whether connection to server is lost.
652     *
653     *  @param pClient  Pointer to client instance structure.
654     *
655     *  @returns @c true if client lost connection to server, @c false otherwise.
656     */
657    bool lscp_client_connection_lost ( lscp_client_t *pClient )
658    {
659        int err = lscp_client_get_errno(pClient);
660        if (err >= 0) return false;
661        return err == -EPIPE || err == -ECONNRESET || err == -ECONNABORTED;
662    }
663    
664    
665  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
666  // Client common protocol functions.  // Client common protocol functions.
# Line 578  int lscp_client_get_errno ( lscp_client_ Line 736  int lscp_client_get_errno ( lscp_client_
736  // Client registration protocol functions.  // Client registration protocol functions.
737    
738  /**  /**
739   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
740     *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
741     *  for @e each event you want to subscribe. That is the old bitflag approach
742     *  was abondoned at this point. You can however still register all older
743     *  events with one lscp_client_subscribe() call at once. Thus, the old
744     *  behavior of this functions was not broken. Those older events are namely:
745     *  @code
746   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
747   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
748   *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO   *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
# Line 586  int lscp_client_get_errno ( lscp_client_ Line 750  int lscp_client_get_errno ( lscp_client_
750   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
751   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
752   *      | MISCELLANEOUS   *      | MISCELLANEOUS
753     *  @endcode
754     *  The old events occupy the lower 16 bits (as bit flags), and all younger
755     *  events enumerate the whole upper 16 bits range. The new, enumerated
756     *  events are namely:
757     *  @code
758     *  SUBSCRIBE CHANNEL_MIDI
759     *  @endcode
760   *   *
761   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
762   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
763   *   *
764   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
765   */   */
766  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 )
767  {  {
768          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
769            lscp_event_t currentEvent;
770    
771          if (pClient == NULL)          if (pClient == NULL)
772                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 637  lscp_status_t lscp_client_subscribe ( ls Line 809  lscp_status_t lscp_client_subscribe ( ls
809                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
810          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
811                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
812            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
813            currentEvent = events & 0xffff0000;
814            if (ret == LSCP_OK && currentEvent) {
815                    switch (currentEvent) {
816                            case LSCP_EVENT_CHANNEL_MIDI:
817                            case LSCP_EVENT_DEVICE_MIDI:
818                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
819                                    break;
820                            default: // unknown "upper" event type
821                                    ret = LSCP_FAILED;
822                                    break;
823                    }
824            }
825    
826          // Unlock this section down.          // Unlock this section down.
827          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 646  lscp_status_t lscp_client_subscribe ( ls Line 831  lscp_status_t lscp_client_subscribe ( ls
831    
832    
833  /**  /**
834   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
835     *  @e Caution: since liblscp v0.5.5.4 you have to call
836     *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
837     *  That is the old bitflag approach was abondoned at this point. You can
838     *  however still register all older events with one lscp_client_subscribe()
839     *  call at once. Thus, the old behavior of this functions was not broken.
840     *  Those older events are namely:
841     *  @code
842   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
843   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
844   *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO   *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
# Line 654  lscp_status_t lscp_client_subscribe ( ls Line 846  lscp_status_t lscp_client_subscribe ( ls
846   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
847   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
848   *      | MISCELLANEOUS   *      | MISCELLANEOUS
849     *  @endcode
850     *  The old events occupy the lower 16 bits (as bit flags), and all younger
851     *  events enumerate the whole upper 16 bits range. The new, enumerated
852     *  events are namely:
853     *  @code
854     *  UNSUBSCRIBE CHANNEL_MIDI
855     *  @endcode
856   *   *
857   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
858   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
859   *   *
860   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
861   */   */
862  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 )
863  {  {
864          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
865            lscp_event_t currentEvent;
866    
867          if (pClient == NULL)          if (pClient == NULL)
868                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 701  lscp_status_t lscp_client_unsubscribe ( Line 901  lscp_status_t lscp_client_unsubscribe (
901                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
902          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
903                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
904            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
905            currentEvent = events & 0xffff0000;
906            if (ret == LSCP_OK && currentEvent) {
907                    switch (currentEvent) {
908                            case LSCP_EVENT_CHANNEL_MIDI:
909                            case LSCP_EVENT_DEVICE_MIDI:
910                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
911                                    break;
912                            default: // unknown "upper" event type
913                                    ret = LSCP_FAILED;
914                                    break;
915                    }
916            }
917    
918          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
919          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 743  lscp_event_t lscp_client_get_events ( ls Line 956  lscp_event_t lscp_client_get_events ( ls
956   *   *
957   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
958   */   */
959  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,
960            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
961  {  {
962          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
963    
964          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
965                  return LSCP_FAILED;                  return LSCP_FAILED;
966    
967          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
968                    pszFileName, iInstrIndex, iSamplerChannel);
969          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
970  }  }
971    
# Line 766  lscp_status_t lscp_load_instrument ( lsc Line 981  lscp_status_t lscp_load_instrument ( lsc
981   *   *
982   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
983   */   */
984  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,
985            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
986  {  {
987          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
988    
989          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
990                  return LSCP_FAILED;                  return LSCP_FAILED;
991    
992          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",
993                    pszFileName, iInstrIndex, iSamplerChannel);
994          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
995  }  }
996    
# Line 795  lscp_status_t lscp_load_engine ( lscp_cl Line 1012  lscp_status_t lscp_load_engine ( lscp_cl
1012          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
1013                  return LSCP_FAILED;                  return LSCP_FAILED;
1014    
1015          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
1016                    pszEngineName, iSamplerChannel);
1017          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1018  }  }
1019    
# Line 986  const char **lscp_list_available_engines Line 1204  const char **lscp_list_available_engines
1204   *  @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
1205   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1206   */   */
1207  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,
1208            const char *pszEngineName )
1209  {  {
1210          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1211          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1053  lscp_channel_info_t *lscp_get_channel_in Line 1272  lscp_channel_info_t *lscp_get_channel_in
1272          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1273          char *pszToken;          char *pszToken;
1274          char *pch;          char *pch;
1275            struct _locale_t locale;
1276    
1277          if (pClient == NULL)          if (pClient == NULL)
1278                  return NULL;                  return NULL;
# Line 1065  lscp_channel_info_t *lscp_get_channel_in Line 1285  lscp_channel_info_t *lscp_get_channel_in
1285          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1286          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1287    
1288            _save_and_set_c_locale(&locale);
1289    
1290          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1291          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1292                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1149  lscp_channel_info_t *lscp_get_channel_in Line 1371  lscp_channel_info_t *lscp_get_channel_in
1371                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1372                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1373                                  if (pszToken)                                  if (pszToken)
1374                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1375                          }                          }
1376                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1377                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1166  lscp_channel_info_t *lscp_get_channel_in Line 1388  lscp_channel_info_t *lscp_get_channel_in
1388          }          }
1389          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1390    
1391            _restore_locale(&locale);
1392    
1393          // Unlock this section up.          // Unlock this section up.
1394          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1395    
# Line 1309  int lscp_get_channel_stream_usage ( lscp Line 1533  int lscp_get_channel_stream_usage ( lscp
1533   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1534   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1535   */   */
1536  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,
1537            lscp_usage_t usage_type, int iSamplerChannel )
1538  {  {
1539          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1540          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1382  lscp_buffer_fill_t *lscp_get_channel_buf Line 1607  lscp_buffer_fill_t *lscp_get_channel_buf
1607   *   *
1608   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1609   */   */
1610  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,
1611            int iSamplerChannel, const char *pszAudioDriver )
1612  {  {
1613          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1614    
1615          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1616                  return LSCP_FAILED;                  return LSCP_FAILED;
1617    
1618          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1619                    iSamplerChannel, pszAudioDriver);
1620          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1621  }  }
1622    
# Line 1404  lscp_status_t lscp_set_channel_audio_typ Line 1631  lscp_status_t lscp_set_channel_audio_typ
1631   *   *
1632   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1633   */   */
1634  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,
1635            int iSamplerChannel, int iAudioDevice )
1636  {  {
1637          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1638    
1639          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1640                  return LSCP_FAILED;                  return LSCP_FAILED;
1641    
1642          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1643                    iSamplerChannel, iAudioDevice);
1644          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1645  }  }
1646    
# Line 1427  lscp_status_t lscp_set_channel_audio_dev Line 1656  lscp_status_t lscp_set_channel_audio_dev
1656   *   *
1657   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1658   */   */
1659  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,
1660            int iSamplerChannel, int iAudioOut, int iAudioIn )
1661  {  {
1662          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1663    
1664          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1665                  return LSCP_FAILED;                  return LSCP_FAILED;
1666    
1667          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",
1668                    iSamplerChannel, iAudioOut, iAudioIn);
1669          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1670  }  }
1671    
# Line 1449  lscp_status_t lscp_set_channel_audio_cha Line 1680  lscp_status_t lscp_set_channel_audio_cha
1680   *   *
1681   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1682   */   */
1683  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,
1684            int iSamplerChannel, const char *pszMidiDriver )
1685  {  {
1686          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1687    
1688          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1689                  return LSCP_FAILED;                  return LSCP_FAILED;
1690    
1691          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1692                    iSamplerChannel, pszMidiDriver);
1693          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1694  }  }
1695    
# Line 1471  lscp_status_t lscp_set_channel_midi_type Line 1704  lscp_status_t lscp_set_channel_midi_type
1704   *   *
1705   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1706   */   */
1707  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,
1708            int iSamplerChannel, int iMidiDevice )
1709  {  {
1710          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1711    
1712          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1713                  return LSCP_FAILED;                  return LSCP_FAILED;
1714    
1715          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1716                    iSamplerChannel, iMidiDevice);
1717          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1718  }  }
1719    
# Line 1493  lscp_status_t lscp_set_channel_midi_devi Line 1728  lscp_status_t lscp_set_channel_midi_devi
1728   *   *
1729   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1730   */   */
1731  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,
1732            int iSamplerChannel, int iMidiPort )
1733  {  {
1734          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1735    
1736          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1737                  return LSCP_FAILED;                  return LSCP_FAILED;
1738    
1739          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1740                    iSamplerChannel, iMidiPort);
1741          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1742  }  }
1743    
# Line 1516  lscp_status_t lscp_set_channel_midi_port Line 1753  lscp_status_t lscp_set_channel_midi_port
1753   *   *
1754   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1755   */   */
1756  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,
1757            int iSamplerChannel, int iMidiChannel )
1758  {  {
1759          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1760    
# Line 1524  lscp_status_t lscp_set_channel_midi_chan Line 1762  lscp_status_t lscp_set_channel_midi_chan
1762                  return LSCP_FAILED;                  return LSCP_FAILED;
1763    
1764          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1765                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1766                            iSamplerChannel);
1767          else          else
1768                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1769                            iSamplerChannel, iMidiChannel);
1770          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1771  }  }
1772    
# Line 1543  lscp_status_t lscp_set_channel_midi_chan Line 1783  lscp_status_t lscp_set_channel_midi_chan
1783   *   *
1784   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1785   */   */
1786  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,
1787            int iSamplerChannel, int iMidiMap )
1788  {  {
1789          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1790    
# Line 1577  lscp_status_t lscp_set_channel_midi_map Line 1818  lscp_status_t lscp_set_channel_midi_map
1818   *   *
1819   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1820   */   */
1821  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,
1822            int iSamplerChannel, float fVolume )
1823  {  {
1824          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1825            struct _locale_t locale;
1826    
1827          if (iSamplerChannel < 0 || fVolume < 0.0f)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1828                  return LSCP_FAILED;                  return LSCP_FAILED;
1829    
1830          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1831            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1832                    iSamplerChannel, fVolume);
1833            _restore_locale(&locale);
1834    
1835          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1836  }  }
1837    
# Line 1601  lscp_status_t lscp_set_channel_volume ( Line 1848  lscp_status_t lscp_set_channel_volume (
1848   *   *
1849   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1850   */   */
1851  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,
1852            int iSamplerChannel, int iMute )
1853  {  {
1854          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1855    
1856          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1857                  return LSCP_FAILED;                  return LSCP_FAILED;
1858    
1859          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1860                    iSamplerChannel, iMute);
1861          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1862  }  }
1863    
# Line 1625  lscp_status_t lscp_set_channel_mute ( ls Line 1874  lscp_status_t lscp_set_channel_mute ( ls
1874   *   *
1875   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1876   */   */
1877  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,
1878            int iSamplerChannel, int iSolo )
1879  {  {
1880          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1881    
1882          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1883                  return LSCP_FAILED;                  return LSCP_FAILED;
1884    
1885          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1886                    iSamplerChannel, iSolo);
1887          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1888  }  }
1889    
# Line 1668  lscp_status_t lscp_reset_channel ( lscp_ Line 1919  lscp_status_t lscp_reset_channel ( lscp_
1919   */   */
1920  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1921  {  {
1922          // Do actual whole sampler reset...          // Do actual whole sampler reset...
1923          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1924  }  }
1925    
# Line 1801  int lscp_get_total_voice_count_max ( lsc Line 2052  int lscp_get_total_voice_count_max ( lsc
2052  float lscp_get_volume ( lscp_client_t *pClient )  float lscp_get_volume ( lscp_client_t *pClient )
2053  {  {
2054          float fVolume = 0.0f;          float fVolume = 0.0f;
2055            struct _locale_t locale;
2056    
2057          if (pClient == NULL)          if (pClient == NULL)
2058                  return 0.0f;                  return 0.0f;
# Line 1808  float lscp_get_volume ( lscp_client_t *p Line 2060  float lscp_get_volume ( lscp_client_t *p
2060          // Lock this section up.          // Lock this section up.
2061          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2062    
2063            _save_and_set_c_locale(&locale);
2064    
2065          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2066                  fVolume = (float) atof(lscp_client_get_result(pClient));                  fVolume = _atof(lscp_client_get_result(pClient));
2067    
2068            _restore_locale(&locale);
2069    
2070          // Unlock this section down.          // Unlock this section down.
2071          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1832  float lscp_get_volume ( lscp_client_t *p Line 2088  float lscp_get_volume ( lscp_client_t *p
2088  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2089  {  {
2090          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2091            struct _locale_t locale;
2092    
2093          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2094                  return LSCP_FAILED;                  return LSCP_FAILED;
2095    
2096            _save_and_set_c_locale(&locale);
2097          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2098            _restore_locale(&locale);
2099    
2100            return lscp_client_query(pClient, szQuery);
2101    }
2102    
2103    
2104    /**
2105     *  Get global voice limit setting:
2106     *  @code
2107     *  GET VOICES
2108     *  @endcode
2109     *  This value reflects the maximum amount of voices a sampler engine
2110     *  processes simultaniously before voice stealing kicks in.
2111     *
2112     *  @param pClient  Pointer to client instance structure.
2113     *
2114     *  @returns The current global maximum amount of voices limit or a
2115     *           negative value on error (e.g. if sampler doesn't support
2116     *           this command).
2117     */
2118    int lscp_get_voices ( lscp_client_t *pClient )
2119    {
2120            int iVoices = -1;
2121    
2122            if (pClient == NULL)
2123                    return -1;
2124    
2125            // Lock this section up.
2126            lscp_mutex_lock(pClient->mutex);
2127    
2128            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2129                    iVoices = atoi(lscp_client_get_result(pClient));
2130    
2131            // Unlock this section down.
2132            lscp_mutex_unlock(pClient->mutex);
2133    
2134            return iVoices;
2135    }
2136    
2137    
2138    /**
2139     *  Setting global voice limit setting:
2140     *  @code
2141     *  SET VOICES <max-voices>
2142     *  @endcode
2143     *  This value reflects the maximum amount of voices a sampler engine
2144     *  processes simultaniously before voice stealing kicks in. Note that
2145     *  this value will be passed to all sampler engine instances, that is
2146     *  the total amount of maximum voices on the running system is thus
2147     *  @param iMaxVoices multiplied with the current amount of sampler
2148     *  engine instances.
2149     *
2150     *  @param pClient     Pointer to client instance structure.
2151     *  @param iMaxVoices  Global voice limit setting as integer value larger
2152     *                     or equal to 1.
2153     *
2154     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2155     */
2156    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2157    {
2158            char szQuery[LSCP_BUFSIZ];
2159    
2160            if (iMaxVoices < 1)
2161                    return LSCP_FAILED;
2162    
2163            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2164            return lscp_client_query(pClient, szQuery);
2165    }
2166    
2167    
2168    /**
2169     *  Get global disk streams limit setting:
2170     *  @code
2171     *  GET STREAMS
2172     *  @endcode
2173     *  This value reflects the maximum amount of disk streams a sampler
2174     *  engine processes simultaniously.
2175     *
2176     *  @param pClient  Pointer to client instance structure.
2177     *
2178     *  @returns The current global maximum amount of disk streams limit
2179     *           or a negative value on error (e.g. if sampler doesn't
2180     *           support this command).
2181     */
2182    int lscp_get_streams ( lscp_client_t *pClient )
2183    {
2184            int iStreams = -1;
2185    
2186            if (pClient == NULL)
2187                    return -1;
2188    
2189            // Lock this section up.
2190            lscp_mutex_lock(pClient->mutex);
2191    
2192            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2193                    iStreams = atoi(lscp_client_get_result(pClient));
2194    
2195            // Unlock this section down.
2196            lscp_mutex_unlock(pClient->mutex);
2197    
2198            return iStreams;
2199    }
2200    
2201    
2202    /**
2203     *  Setting global disk streams limit setting:
2204     *  @code
2205     *  SET STREAMS <max-streams>
2206     *  @endcode
2207     *  This value reflects the maximum amount of dist streams a sampler
2208     *  engine instance processes simultaniously. Note that this value will
2209     *  be passed to all sampler engine instances, that is the total amount
2210     *  of maximum disk streams on the running system is thus
2211     *  @param iMaxStreams multiplied with the current amount of sampler
2212     *  engine instances.
2213     *
2214     *  @param pClient      Pointer to client instance structure.
2215     *  @param iMaxStreams  Global streams limit setting as positive integer
2216     *                      value (larger or equal to 0).
2217     *
2218     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2219     */
2220    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2221    {
2222            char szQuery[LSCP_BUFSIZ];
2223    
2224            if (iMaxStreams < 0)
2225                    return LSCP_FAILED;
2226    
2227            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2228          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2229  }  }
2230    
2231    
2232  /**  /**
2233   *  Add an effect send to a sampler channel:   *  Add an effect send to a sampler channel:
2234   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<name>]   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2235   *   *
2236   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2237   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
2238   *  @param iMidiController  MIDI controller used to alter the effect,   *  @param iMidiController  MIDI controller used to alter the effect,
2239   *                          usually a number between 0 and 127.   *                          usually a number between 0 and 127.
2240   *  @param pszName          Optional name for the effect send entity,   *  @param pszFxName        Optional name for the effect send entity,
2241   *                          does not have to be unique.   *                          does not have to be unique.
2242   *   *
2243   *  @returns The new effect send number identifier, or -1 in case of failure.   *  @returns The new effect send number identifier, or -1 in case of failure.
2244   */   */
2245  int lscp_create_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iMidiController, const char *pszFxName )  int lscp_create_fxsend ( lscp_client_t *pClient,
2246            int iSamplerChannel, int iMidiController, const char *pszFxName )
2247  {  {
2248          int iFxSend = -1;          int iFxSend = -1;
2249          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1867  int lscp_create_fxsend ( lscp_client_t * Line 2256  int lscp_create_fxsend ( lscp_client_t *
2256          // Lock this section up.          // Lock this section up.
2257          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2258    
2259          sprintf(szQuery, "CREATE FX_SEND %d %d", iSamplerChannel, iMidiController);          sprintf(szQuery, "CREATE FX_SEND %d %d",
2260                            iSamplerChannel, iMidiController);
2261    
2262          if (pszFxName)          if (pszFxName)
2263                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2264    
# Line 1894  int lscp_create_fxsend ( lscp_client_t * Line 2284  int lscp_create_fxsend ( lscp_client_t *
2284   *   *
2285   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2286   */   */
2287  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend )  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2288            int iSamplerChannel, int iFxSend )
2289  {  {
2290          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2291    
2292          if (iSamplerChannel < 0 || iFxSend < 0)          if (iSamplerChannel < 0 || iFxSend < 0)
2293                  return LSCP_FAILED;                  return LSCP_FAILED;
2294    
2295          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n", iSamplerChannel, iFxSend);          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2296                    iSamplerChannel, iFxSend);
2297    
2298          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2299  }  }
# Line 1991  int *lscp_list_fxsends ( lscp_client_t * Line 2383  int *lscp_list_fxsends ( lscp_client_t *
2383   *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the   *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2384   *  information of the given FX send, or NULL in case of failure.   *  information of the given FX send, or NULL in case of failure.
2385   */   */
2386  lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend )  lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2387            int iSamplerChannel, int iFxSend )
2388  {  {
2389          lscp_fxsend_info_t *pFxSendInfo;          lscp_fxsend_info_t *pFxSendInfo;
2390          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2000  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2393  lscp_fxsend_info_t *lscp_get_fxsend_info
2393          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2394          char *pszToken;          char *pszToken;
2395          char *pch;          char *pch;
2396            struct _locale_t locale;
2397    
2398          if (pClient == NULL)          if (pClient == NULL)
2399                  return NULL;                  return NULL;
# Line 2009  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2403  lscp_fxsend_info_t *lscp_get_fxsend_info
2403          // Lock this section up.          // Lock this section up.
2404          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2405    
2406            _save_and_set_c_locale(&locale);
2407    
2408          pFxSendInfo = &(pClient->fxsend_info);          pFxSendInfo = &(pClient->fxsend_info);
2409          lscp_fxsend_info_reset(pFxSendInfo);          lscp_fxsend_info_reset(pFxSendInfo);
2410    
# Line 2038  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2434  lscp_fxsend_info_t *lscp_get_fxsend_info
2434                          else if (strcasecmp(pszToken, "LEVEL") == 0) {                          else if (strcasecmp(pszToken, "LEVEL") == 0) {
2435                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2436                                  if (pszToken)                                  if (pszToken)
2437                                          pFxSendInfo->level = (float) atof(lscp_ltrim(pszToken));                                          pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2438                          }                          }
2439                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2440                  }                  }
2441          }          }
2442          else pFxSendInfo = NULL;          else pFxSendInfo = NULL;
2443    
2444            _restore_locale(&locale);
2445    
2446          // Unlock this section up.          // Unlock this section up.
2447          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2448    
2449          return pFxSendInfo;          return pFxSendInfo;
2450  }  }
2451    
2452    
2453  /**  /**
2454   *  Alter effect send's name:   *  Alter effect send's name:
2455   *  @code   *  @code
# Line 2064  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2463  lscp_fxsend_info_t *lscp_get_fxsend_info
2463   *   *
2464   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2465   */   */
2466  lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, const char *pszFxName )  lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2467            int iSamplerChannel, int iFxSend, const char *pszFxName )
2468  {  {
2469          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2470    
2471          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2472                  return LSCP_FAILED;                  return LSCP_FAILED;
2473    
2474          snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d %s\r\n", iSamplerChannel, iFxSend, pszFxName);          snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2475                    iSamplerChannel, iFxSend, pszFxName);
2476          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2477  }  }
2478    
2479    
2480  /**  /**
2481   *  Alter effect send's audio routing:   *  Alter effect send's audio routing:
2482   *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>   *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
# Line 2088  lscp_status_t lscp_set_fxsend_name ( lsc Line 2490  lscp_status_t lscp_set_fxsend_name ( lsc
2490   *   *
2491   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2492   */   */
2493  lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )  lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2494            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2495  {  {
2496          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2497    
2498          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2499                  return LSCP_FAILED;                  return LSCP_FAILED;
2500    
2501          sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n", iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);          sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2502                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2503          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2504  }  }
2505    
# Line 2112  lscp_status_t lscp_set_fxsend_audio_chan Line 2516  lscp_status_t lscp_set_fxsend_audio_chan
2516   *   *
2517   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2518   */   */
2519  lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, int iMidiController )  lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2520            int iSamplerChannel, int iFxSend, int iMidiController )
2521  {  {
2522          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2523    
2524          if (iSamplerChannel < 0 || iFxSend < 0 || iMidiController < 0 || iMidiController > 127)          if (iSamplerChannel < 0 || iFxSend < 0 ||
2525                    iMidiController < 0 || iMidiController > 127)
2526                  return LSCP_FAILED;                  return LSCP_FAILED;
2527    
2528          sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n", iSamplerChannel, iFxSend, iMidiController);          sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2529                    iSamplerChannel, iFxSend, iMidiController);
2530          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2531  }  }
2532    
# Line 2135  lscp_status_t lscp_set_fxsend_midi_contr Line 2542  lscp_status_t lscp_set_fxsend_midi_contr
2542   *   *
2543   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2544   */   */
2545  lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, float fLevel )  lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2546            int iSamplerChannel, int iFxSend, float fLevel )
2547  {  {
2548          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2549            struct _locale_t locale;
2550    
2551          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2552                  return LSCP_FAILED;                  return LSCP_FAILED;
2553    
2554          sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n", iSamplerChannel, iFxSend, fLevel);          _save_and_set_c_locale(&locale);
2555            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2556                    iSamplerChannel, iFxSend, fLevel);
2557            _restore_locale(&locale);
2558    
2559          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2560  }  }
2561    
# Line 2169  int lscp_add_midi_instrument_map ( lscp_ Line 2582  int lscp_add_midi_instrument_map ( lscp_
2582          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2583    
2584          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2585            
2586          if (pszMapName)          if (pszMapName)
2587                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2588    
# Line 2295  const char *lscp_get_midi_instrument_map Line 2708  const char *lscp_get_midi_instrument_map
2708    
2709          // Lock this section up.          // Lock this section up.
2710          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2711            
2712          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2713                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2714                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
# Line 2359  lscp_status_t lscp_set_midi_instrument_m Line 2772  lscp_status_t lscp_set_midi_instrument_m
2772   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2773   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2774   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2775   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2776   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2777   *                          1.0 for amplification.   *                          1.0 for amplification.
2778   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 2371  lscp_status_t lscp_set_midi_instrument_m Line 2784  lscp_status_t lscp_set_midi_instrument_m
2784   *   *
2785   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2786   */   */
2787  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,
2788            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2789            const char *pszFileName, int iInstrIndex, float fVolume,
2790            lscp_load_mode_t load_mode, const char *pszName )
2791  {  {
2792          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2793            struct _locale_t locale;
2794    
2795          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2796                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 2387  lscp_status_t lscp_map_midi_instrument ( Line 2804  lscp_status_t lscp_map_midi_instrument (
2804          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2805                  fVolume = 1.0f;                  fVolume = 1.0f;
2806    
2807            _save_and_set_c_locale(&locale);
2808          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2809                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2810                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2811            _restore_locale(&locale);
2812    
2813          switch (load_mode) {          switch (load_mode) {
2814          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2424  lscp_status_t lscp_map_midi_instrument ( Line 2843  lscp_status_t lscp_map_midi_instrument (
2843   *   *
2844   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2845   */   */
2846  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,
2847            lscp_midi_instrument_t *pMidiInstr )
2848  {  {
2849          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2850    
# Line 2517  lscp_midi_instrument_t *lscp_list_midi_i Line 2937  lscp_midi_instrument_t *lscp_list_midi_i
2937          strcat(szQuery, "\r\n");          strcat(szQuery, "\r\n");
2938    
2939          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2940                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));                  pClient->midi_instruments = lscp_midi_instruments_create(
2941                            lscp_client_get_result(pClient));
2942    
2943          // Unlock this section down.          // Unlock this section down.
2944          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 2537  lscp_midi_instrument_t *lscp_list_midi_i Line 2958  lscp_midi_instrument_t *lscp_list_midi_i
2958   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2959   *  or NULL in case of failure.   *  or NULL in case of failure.
2960   */   */
2961  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,
2962            lscp_midi_instrument_t *pMidiInstr )
2963  {  {
2964          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2965          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2546  lscp_midi_instrument_info_t *lscp_get_mi Line 2968  lscp_midi_instrument_info_t *lscp_get_mi
2968          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2969          char *pszToken;          char *pszToken;
2970          char *pch;          char *pch;
2971            struct _locale_t locale;
2972    
2973          if (pClient == NULL)          if (pClient == NULL)
2974                  return NULL;                  return NULL;
# Line 2558  lscp_midi_instrument_info_t *lscp_get_mi Line 2981  lscp_midi_instrument_info_t *lscp_get_mi
2981    
2982          // Lock this section up.          // Lock this section up.
2983          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2984            
2985            _save_and_set_c_locale(&locale);
2986    
2987          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2988          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2989    
# Line 2612  lscp_midi_instrument_info_t *lscp_get_mi Line 3037  lscp_midi_instrument_info_t *lscp_get_mi
3037                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3038                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3039                                  if (pszToken)                                  if (pszToken)
3040                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3041                          }                          }
3042                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3043                  }                  }
3044          }          }
3045          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3046    
3047            _restore_locale(&locale);
3048    
3049          // Unlock this section down.          // Unlock this section down.
3050          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3051    
# Line 2651  lscp_status_t lscp_clear_midi_instrument Line 3078  lscp_status_t lscp_clear_midi_instrument
3078          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
3079  }  }
3080    
3081    
3082  /**  /**
3083   * Open an instrument editor application for the instrument   * Open an instrument editor application for the instrument
3084   * on the given sampler channel:   * on the given sampler channel:

Legend:
Removed from v.1665  
changed lines
  Added in v.3665

  ViewVC Help
Powered by ViewVC