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

Legend:
Removed from v.1666  
changed lines
  Added in v.3666

  ViewVC Help
Powered by ViewVC