/[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 2424 by capela, Sun Feb 24 19:02:30 2013 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-2013, 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    
26  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
27  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
28    
29    
30    // Whether to use getaddrinfo() instead
31    // of deprecated gethostbyname()
32    #if !defined(WIN32)
33    #define USE_GETADDRINFO 1
34    #endif
35    
36    
37  // Local prototypes.  // Local prototypes.
38    
39  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
40    
41    static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
42    static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
43            int iSubscribe, lscp_event_t event);
44    
45    
46    //-------------------------------------------------------------------------
47    // General helper functions.
48    
49    struct _locale_t {
50            char numeric[32];
51            char ctype[32];
52    };
53    
54    // we need to ensure a constant locale setting e.g. for parsing
55    // floating point numbers with atof(), as the floating point separator
56    // character varies by the invidual locale settings
57    static void _save_and_set_c_locale(struct _locale_t* locale)
58    {
59            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
60            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
61            setlocale(LC_NUMERIC, "C");
62            setlocale(LC_CTYPE, "C");
63    }
64    
65    // restore the original locale setting as nothing happened
66    static void _restore_locale(struct _locale_t* locale)
67    {
68            setlocale(LC_NUMERIC, locale->numeric);
69            setlocale(LC_CTYPE, locale->ctype);
70    }
71    
72  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  // seems the standard atof() function doesnt care much about locale
73  static lscp_status_t    _lscp_client_evt_request    (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);  // runtime modifications, so we use this workaround
74    static float _atof(const char* txt) {
75            float f;
76            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
77            return f;
78    }
79    
80    
81  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 94  static void _lscp_client_evt_proc ( void
94          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
95          int    cchBuffer;          int    cchBuffer;
96          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
97          char * pszToken;          char  *pszToken;
98          char * pch;          char  *pch;
99          int     cchToken;          int    cchToken;
100    
101          lscp_event_t event;          lscp_event_t event;
102    
103  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 129  static void _lscp_client_evt_proc ( void
129                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
130                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
131                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
132                                  // Parse for the notification event message...                                  pch = achBuffer;
133                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
134                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
135                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
136                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
137                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
138                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
139                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
140                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
141                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
142                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
143                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
144                                                                  pClient,                                                          // Invoke the client event callback...
145                                                                  event,                                                          if ((*pClient->pfnCallback)(
146                                                                  pszToken,                                                                          pClient,
147                                                                  cchToken,                                                                          event,
148                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
149                                                          pClient->evt.iState = 0;                                                                          cchToken,
150                                                                            pClient->pvData) != LSCP_OK) {
151                                                                    pClient->evt.iState = 0;
152                                                            }
153                                                  }                                                  }
154                                          }                                          }
155                                  }                                  } while (*pch);
156                          } else {                          } else {
157                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
158                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
# Line 146  static lscp_status_t _lscp_client_evt_co Line 194  static lscp_status_t _lscp_client_evt_co
194          }          }
195    
196  #if defined(WIN32)  #if defined(WIN32)
197          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
198                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
199                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
200  #endif  #endif
201    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 223  static lscp_status_t _lscp_client_evt_co
223    
224    
225  // Subscribe to a single event.  // Subscribe to a single event.
226  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,
227            int iSubscribe, lscp_event_t event )
228  {  {
229          const char *pszEvent;          const char *pszEvent;
230          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 239  static lscp_status_t _lscp_client_evt_re
239                  return LSCP_FAILED;                  return LSCP_FAILED;
240    
241          // Build the query string...          // Build the query string...
242          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
243                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
244          // Just send data, forget result...          // Just send data, forget result...
245          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
246                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 240  const char* lscp_client_build   (void) { Line 291  const char* lscp_client_build   (void) {
291   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
292   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
293   */   */
294  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,
295            lscp_client_proc_t pfnCallback, void *pvData )
296  {  {
297          lscp_client_t  *pClient;          lscp_client_t  *pClient;
298    #if defined(USE_GETADDRINFO)
299            char szPort[33];
300            struct addrinfo hints;
301            struct addrinfo *result, *res;
302    #else
303          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
304          struct sockaddr_in addr;          struct sockaddr_in addr;
305          int cAddr;          int cAddr;
306    #endif  /* !USE_GETADDRINFO */
307            lscp_socket_t sock;
308  #if defined(WIN32)  #if defined(WIN32)
309          int iSockOpt = (-1);          int iSockOpt = (-1);
310  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 314  lscp_client_t* lscp_client_create ( cons
314                  return NULL;                  return NULL;
315          }          }
316    
317    #if defined(USE_GETADDRINFO)
318    
319            // Convert port number to string/name...
320            snprintf(szPort, sizeof(szPort), "%d", iPort);
321    
322            // Obtain address(es) matching host/port...
323            memset(&hints, 0, sizeof(struct addrinfo));
324            hints.ai_family = AF_INET;
325            hints.ai_socktype = SOCK_STREAM;
326    
327            result = NULL;
328    
329            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
330                    lscp_socket_herror("lscp_client_create: getaddrinfo");
331                    return NULL;
332            }
333    
334    #else
335    
336            // Obtain host matching name...
337          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
338          if (pHost == NULL) {          if (pHost == NULL) {
339                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
340                  return NULL;                  return NULL;
341          }          }
342    
343    #endif  /* !USE_GETADDRINFO */
344    
345          // Allocate client descriptor...          // Allocate client descriptor...
346    
347          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 355  lscp_client_t* lscp_client_create ( cons
355          pClient->pvData = pvData;          pClient->pvData = pvData;
356    
357  #ifdef DEBUG  #ifdef DEBUG
358          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
359                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
360                     pClient, pszHost, iPort);
361  #endif  #endif
362    
363          // Prepare the command connection socket...          // Prepare the command connection socket...
364    
365    #if defined(USE_GETADDRINFO)
366    
367            // getaddrinfo() returns a list of address structures;
368            // try each address until we successfully connect(2);
369            // if socket or connect fails, we close the socket and
370            // try the next address...
371            sock = INVALID_SOCKET;
372    
373            for (res = result; res; res = res->ai_next) {
374                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
375                    if (sock == INVALID_SOCKET)
376                            continue;
377            #if defined(WIN32)
378                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
379                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
380                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
381            #endif
382            #ifdef DEBUG
383                    lscp_socket_getopts("lscp_client_create: cmd", sock);
384            #endif
385                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
386                            break;
387                    closesocket(sock);
388            }
389    
390            if (sock == INVALID_SOCKET) {
391                    lscp_socket_perror("lscp_client_create: cmd: socket");
392                    free(pClient);
393                    return NULL;
394            }
395    
396            if (res == NULL) {
397                    lscp_socket_perror("lscp_client_create: cmd: connect");
398                    free(pClient);
399                    return NULL;
400            }
401    
402            // Initialize the command socket agent struct...
403            lscp_socket_agent_init(&(pClient->cmd), sock,
404                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
405    
406            // No longer needed...
407            freeaddrinfo(result);
408    
409    #else
410    
411          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
412          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
413                  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 416  lscp_client_t* lscp_client_create ( cons
416          }          }
417    
418  #if defined(WIN32)  #if defined(WIN32)
419          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
420                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
421                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
422  #endif  #endif
423    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 441  lscp_client_t* lscp_client_create ( cons
441          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
442          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
443    
444    #endif  /* !USE_GETADDRINFO */
445    
446  #ifdef DEBUG  #ifdef DEBUG
447          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,
448                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
449                    pClient, pClient->cmd.sock,
450                    inet_ntoa(pClient->cmd.addr.sin_addr),
451                    ntohs(pClient->cmd.addr.sin_port));
452  #endif  #endif
453    
454          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 578  int lscp_client_get_errno ( lscp_client_ Line 713  int lscp_client_get_errno ( lscp_client_
713  // Client registration protocol functions.  // Client registration protocol functions.
714    
715  /**  /**
716   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
717     *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
718     *  for @e each event you want to subscribe. That is the old bitflag approach
719     *  was abondoned at this point. You can however still register all older
720     *  events with one lscp_client_subscribe() call at once. Thus, the old
721     *  behavior of this functions was not broken. Those older events are namely:
722     *  @code
723   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
724   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
725   *      | 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 727  int lscp_client_get_errno ( lscp_client_
727   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
728   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
729   *      | MISCELLANEOUS   *      | MISCELLANEOUS
730     *  @endcode
731     *  The old events occupy the lower 16 bits (as bit flags), and all younger
732     *  events enumerate the whole upper 16 bits range. The new, enumerated
733     *  events are namely:
734     *  @code
735     *  SUBSCRIBE CHANNEL_MIDI
736     *  @endcode
737   *   *
738   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
739   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
740   *   *
741   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
742   */   */
743  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 )
744  {  {
745          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
746            lscp_event_t currentEvent;
747    
748          if (pClient == NULL)          if (pClient == NULL)
749                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 637  lscp_status_t lscp_client_subscribe ( ls Line 786  lscp_status_t lscp_client_subscribe ( ls
786                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
787          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
788                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
789            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
790            currentEvent = events & 0xffff0000;
791            if (ret == LSCP_OK && currentEvent) {
792                    switch (currentEvent) {
793                            case LSCP_EVENT_CHANNEL_MIDI:
794                            case LSCP_EVENT_DEVICE_MIDI:
795                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
796                                    break;
797                            default: // unknown "upper" event type
798                                    ret = LSCP_FAILED;
799                                    break;
800                    }
801            }
802    
803          // Unlock this section down.          // Unlock this section down.
804          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 646  lscp_status_t lscp_client_subscribe ( ls Line 808  lscp_status_t lscp_client_subscribe ( ls
808    
809    
810  /**  /**
811   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
812     *  @e Caution: since liblscp v0.5.5.4 you have to call
813     *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
814     *  That is the old bitflag approach was abondoned at this point. You can
815     *  however still register all older events with one lscp_client_subscribe()
816     *  call at once. Thus, the old behavior of this functions was not broken.
817     *  Those older events are namely:
818     *  @code
819   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
820   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
821   *      | 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 823  lscp_status_t lscp_client_subscribe ( ls
823   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
824   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
825   *      | MISCELLANEOUS   *      | MISCELLANEOUS
826     *  @endcode
827     *  The old events occupy the lower 16 bits (as bit flags), and all younger
828     *  events enumerate the whole upper 16 bits range. The new, enumerated
829     *  events are namely:
830     *  @code
831     *  UNSUBSCRIBE CHANNEL_MIDI
832     *  @endcode
833   *   *
834   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
835   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
836   *   *
837   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
838   */   */
839  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 )
840  {  {
841          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
842            lscp_event_t currentEvent;
843    
844          if (pClient == NULL)          if (pClient == NULL)
845                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 701  lscp_status_t lscp_client_unsubscribe ( Line 878  lscp_status_t lscp_client_unsubscribe (
878                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
879          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
880                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
881            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
882            currentEvent = events & 0xffff0000;
883            if (ret == LSCP_OK && currentEvent) {
884                    switch (currentEvent) {
885                            case LSCP_EVENT_CHANNEL_MIDI:
886                            case LSCP_EVENT_DEVICE_MIDI:
887                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
888                                    break;
889                            default: // unknown "upper" event type
890                                    ret = LSCP_FAILED;
891                                    break;
892                    }
893            }
894    
895          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
896          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 743  lscp_event_t lscp_client_get_events ( ls Line 933  lscp_event_t lscp_client_get_events ( ls
933   *   *
934   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
935   */   */
936  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,
937            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
938  {  {
939          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
940    
941          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
942                  return LSCP_FAILED;                  return LSCP_FAILED;
943    
944          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
945                    pszFileName, iInstrIndex, iSamplerChannel);
946          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
947  }  }
948    
# Line 766  lscp_status_t lscp_load_instrument ( lsc Line 958  lscp_status_t lscp_load_instrument ( lsc
958   *   *
959   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
960   */   */
961  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,
962            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
963  {  {
964          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
965    
966          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
967                  return LSCP_FAILED;                  return LSCP_FAILED;
968    
969          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",
970                    pszFileName, iInstrIndex, iSamplerChannel);
971          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
972  }  }
973    
# Line 795  lscp_status_t lscp_load_engine ( lscp_cl Line 989  lscp_status_t lscp_load_engine ( lscp_cl
989          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
990                  return LSCP_FAILED;                  return LSCP_FAILED;
991    
992          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
993                    pszEngineName, iSamplerChannel);
994          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
995  }  }
996    
# Line 986  const char **lscp_list_available_engines Line 1181  const char **lscp_list_available_engines
1181   *  @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
1182   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1183   */   */
1184  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,
1185            const char *pszEngineName )
1186  {  {
1187          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1188          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1053  lscp_channel_info_t *lscp_get_channel_in Line 1249  lscp_channel_info_t *lscp_get_channel_in
1249          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1250          char *pszToken;          char *pszToken;
1251          char *pch;          char *pch;
1252            struct _locale_t locale;
1253    
1254          if (pClient == NULL)          if (pClient == NULL)
1255                  return NULL;                  return NULL;
# Line 1065  lscp_channel_info_t *lscp_get_channel_in Line 1262  lscp_channel_info_t *lscp_get_channel_in
1262          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1263          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1264    
1265            _save_and_set_c_locale(&locale);
1266    
1267          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1268          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1269                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1149  lscp_channel_info_t *lscp_get_channel_in Line 1348  lscp_channel_info_t *lscp_get_channel_in
1348                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1349                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1350                                  if (pszToken)                                  if (pszToken)
1351                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1352                          }                          }
1353                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1354                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1166  lscp_channel_info_t *lscp_get_channel_in Line 1365  lscp_channel_info_t *lscp_get_channel_in
1365          }          }
1366          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1367    
1368            _restore_locale(&locale);
1369    
1370          // Unlock this section up.          // Unlock this section up.
1371          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1372    
# Line 1309  int lscp_get_channel_stream_usage ( lscp Line 1510  int lscp_get_channel_stream_usage ( lscp
1510   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1511   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1512   */   */
1513  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,
1514            lscp_usage_t usage_type, int iSamplerChannel )
1515  {  {
1516          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1517          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1382  lscp_buffer_fill_t *lscp_get_channel_buf Line 1584  lscp_buffer_fill_t *lscp_get_channel_buf
1584   *   *
1585   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1586   */   */
1587  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,
1588            int iSamplerChannel, const char *pszAudioDriver )
1589  {  {
1590          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1591    
1592          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1593                  return LSCP_FAILED;                  return LSCP_FAILED;
1594    
1595          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1596                    iSamplerChannel, pszAudioDriver);
1597          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1598  }  }
1599    
# Line 1404  lscp_status_t lscp_set_channel_audio_typ Line 1608  lscp_status_t lscp_set_channel_audio_typ
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_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1612            int iSamplerChannel, int iAudioDevice )
1613  {  {
1614          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1615    
1616          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1617                  return LSCP_FAILED;                  return LSCP_FAILED;
1618    
1619          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1620                    iSamplerChannel, iAudioDevice);
1621          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1622  }  }
1623    
# Line 1427  lscp_status_t lscp_set_channel_audio_dev Line 1633  lscp_status_t lscp_set_channel_audio_dev
1633   *   *
1634   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1635   */   */
1636  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,
1637            int iSamplerChannel, int iAudioOut, int iAudioIn )
1638  {  {
1639          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1640    
1641          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1642                  return LSCP_FAILED;                  return LSCP_FAILED;
1643    
1644          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",
1645                    iSamplerChannel, iAudioOut, iAudioIn);
1646          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1647  }  }
1648    
# Line 1449  lscp_status_t lscp_set_channel_audio_cha Line 1657  lscp_status_t lscp_set_channel_audio_cha
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_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1661            int iSamplerChannel, const char *pszMidiDriver )
1662  {  {
1663          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1664    
1665          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1666                  return LSCP_FAILED;                  return LSCP_FAILED;
1667    
1668          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1669                    iSamplerChannel, pszMidiDriver);
1670          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1671  }  }
1672    
# Line 1471  lscp_status_t lscp_set_channel_midi_type Line 1681  lscp_status_t lscp_set_channel_midi_type
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_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1685            int iSamplerChannel, int iMidiDevice )
1686  {  {
1687          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1688    
1689          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1690                  return LSCP_FAILED;                  return LSCP_FAILED;
1691    
1692          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1693                    iSamplerChannel, iMidiDevice);
1694          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1695  }  }
1696    
# Line 1493  lscp_status_t lscp_set_channel_midi_devi Line 1705  lscp_status_t lscp_set_channel_midi_devi
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_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1709            int iSamplerChannel, int iMidiPort )
1710  {  {
1711          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1712    
1713          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1714                  return LSCP_FAILED;                  return LSCP_FAILED;
1715    
1716          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1717                    iSamplerChannel, iMidiPort);
1718          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1719  }  }
1720    
# Line 1516  lscp_status_t lscp_set_channel_midi_port Line 1730  lscp_status_t lscp_set_channel_midi_port
1730   *   *
1731   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1732   */   */
1733  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,
1734            int iSamplerChannel, int iMidiChannel )
1735  {  {
1736          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1737    
# Line 1524  lscp_status_t lscp_set_channel_midi_chan Line 1739  lscp_status_t lscp_set_channel_midi_chan
1739                  return LSCP_FAILED;                  return LSCP_FAILED;
1740    
1741          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1742                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1743                            iSamplerChannel);
1744          else          else
1745                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1746                            iSamplerChannel, iMidiChannel);
1747          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1748  }  }
1749    
# Line 1543  lscp_status_t lscp_set_channel_midi_chan Line 1760  lscp_status_t lscp_set_channel_midi_chan
1760   *   *
1761   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1762   */   */
1763  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,
1764            int iSamplerChannel, int iMidiMap )
1765  {  {
1766          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1767    
# Line 1577  lscp_status_t lscp_set_channel_midi_map Line 1795  lscp_status_t lscp_set_channel_midi_map
1795   *   *
1796   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1797   */   */
1798  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,
1799            int iSamplerChannel, float fVolume )
1800  {  {
1801          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1802            struct _locale_t locale;
1803    
1804          if (iSamplerChannel < 0 || fVolume < 0.0f)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1805                  return LSCP_FAILED;                  return LSCP_FAILED;
1806    
1807          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1808            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1809                    iSamplerChannel, fVolume);
1810            _restore_locale(&locale);
1811    
1812          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1813  }  }
1814    
# Line 1601  lscp_status_t lscp_set_channel_volume ( Line 1825  lscp_status_t lscp_set_channel_volume (
1825   *   *
1826   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1827   */   */
1828  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,
1829            int iSamplerChannel, int iMute )
1830  {  {
1831          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1832    
1833          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1834                  return LSCP_FAILED;                  return LSCP_FAILED;
1835    
1836          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1837                    iSamplerChannel, iMute);
1838          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1839  }  }
1840    
# Line 1625  lscp_status_t lscp_set_channel_mute ( ls Line 1851  lscp_status_t lscp_set_channel_mute ( ls
1851   *   *
1852   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1853   */   */
1854  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,
1855            int iSamplerChannel, int iSolo )
1856  {  {
1857          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1858    
1859          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1860                  return LSCP_FAILED;                  return LSCP_FAILED;
1861    
1862          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1863                    iSamplerChannel, iSolo);
1864          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1865  }  }
1866    
# Line 1668  lscp_status_t lscp_reset_channel ( lscp_ Line 1896  lscp_status_t lscp_reset_channel ( lscp_
1896   */   */
1897  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1898  {  {
1899          // Do actual whole sampler reset...          // Do actual whole sampler reset...
1900          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1901  }  }
1902    
# Line 1801  int lscp_get_total_voice_count_max ( lsc Line 2029  int lscp_get_total_voice_count_max ( lsc
2029  float lscp_get_volume ( lscp_client_t *pClient )  float lscp_get_volume ( lscp_client_t *pClient )
2030  {  {
2031          float fVolume = 0.0f;          float fVolume = 0.0f;
2032            struct _locale_t locale;
2033    
2034          if (pClient == NULL)          if (pClient == NULL)
2035                  return 0.0f;                  return 0.0f;
# Line 1808  float lscp_get_volume ( lscp_client_t *p Line 2037  float lscp_get_volume ( lscp_client_t *p
2037          // Lock this section up.          // Lock this section up.
2038          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2039    
2040            _save_and_set_c_locale(&locale);
2041    
2042          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2043                  fVolume = (float) atof(lscp_client_get_result(pClient));                  fVolume = _atof(lscp_client_get_result(pClient));
2044    
2045            _restore_locale(&locale);
2046    
2047          // Unlock this section down.          // Unlock this section down.
2048          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1832  float lscp_get_volume ( lscp_client_t *p Line 2065  float lscp_get_volume ( lscp_client_t *p
2065  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2066  {  {
2067          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2068            struct _locale_t locale;
2069    
2070          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2071                  return LSCP_FAILED;                  return LSCP_FAILED;
2072    
2073            _save_and_set_c_locale(&locale);
2074          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2075            _restore_locale(&locale);
2076    
2077            return lscp_client_query(pClient, szQuery);
2078    }
2079    
2080    
2081    /**
2082     *  Get global voice limit setting:
2083     *  @code
2084     *  GET VOICES
2085     *  @endcode
2086     *  This value reflects the maximum amount of voices a sampler engine
2087     *  processes simultaniously before voice stealing kicks in.
2088     *
2089     *  @param pClient  Pointer to client instance structure.
2090     *
2091     *  @returns The current global maximum amount of voices limit or a
2092     *           negative value on error (e.g. if sampler doesn't support
2093     *           this command).
2094     */
2095    int lscp_get_voices ( lscp_client_t *pClient )
2096    {
2097            int iVoices = -1;
2098    
2099            if (pClient == NULL)
2100                    return -1;
2101    
2102            // Lock this section up.
2103            lscp_mutex_lock(pClient->mutex);
2104    
2105            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2106                    iVoices = atoi(lscp_client_get_result(pClient));
2107    
2108            // Unlock this section down.
2109            lscp_mutex_unlock(pClient->mutex);
2110    
2111            return iVoices;
2112    }
2113    
2114    
2115    /**
2116     *  Setting global voice limit setting:
2117     *  @code
2118     *  SET VOICES <max-voices>
2119     *  @endcode
2120     *  This value reflects the maximum amount of voices a sampler engine
2121     *  processes simultaniously before voice stealing kicks in. Note that
2122     *  this value will be passed to all sampler engine instances, that is
2123     *  the total amount of maximum voices on the running system is thus
2124     *  @param iMaxVoices multiplied with the current amount of sampler
2125     *  engine instances.
2126     *
2127     *  @param pClient     Pointer to client instance structure.
2128     *  @param iMaxVoices  Global voice limit setting as integer value larger
2129     *                     or equal to 1.
2130     *
2131     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2132     */
2133    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2134    {
2135            char szQuery[LSCP_BUFSIZ];
2136    
2137            if (iMaxVoices < 1)
2138                    return LSCP_FAILED;
2139    
2140            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2141            return lscp_client_query(pClient, szQuery);
2142    }
2143    
2144    
2145    /**
2146     *  Get global disk streams limit setting:
2147     *  @code
2148     *  GET STREAMS
2149     *  @endcode
2150     *  This value reflects the maximum amount of disk streams a sampler
2151     *  engine processes simultaniously.
2152     *
2153     *  @param pClient  Pointer to client instance structure.
2154     *
2155     *  @returns The current global maximum amount of disk streams limit
2156     *           or a negative value on error (e.g. if sampler doesn't
2157     *           support this command).
2158     */
2159    int lscp_get_streams ( lscp_client_t *pClient )
2160    {
2161            int iStreams = -1;
2162    
2163            if (pClient == NULL)
2164                    return -1;
2165    
2166            // Lock this section up.
2167            lscp_mutex_lock(pClient->mutex);
2168    
2169            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2170                    iStreams = atoi(lscp_client_get_result(pClient));
2171    
2172            // Unlock this section down.
2173            lscp_mutex_unlock(pClient->mutex);
2174    
2175            return iStreams;
2176    }
2177    
2178    
2179    /**
2180     *  Setting global disk streams limit setting:
2181     *  @code
2182     *  SET STREAMS <max-streams>
2183     *  @endcode
2184     *  This value reflects the maximum amount of dist streams a sampler
2185     *  engine instance processes simultaniously. Note that this value will
2186     *  be passed to all sampler engine instances, that is the total amount
2187     *  of maximum disk streams on the running system is thus
2188     *  @param iMaxStreams multiplied with the current amount of sampler
2189     *  engine instances.
2190     *
2191     *  @param pClient      Pointer to client instance structure.
2192     *  @param iMaxStreams  Global streams limit setting as positive integer
2193     *                      value (larger or equal to 0).
2194     *
2195     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2196     */
2197    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2198    {
2199            char szQuery[LSCP_BUFSIZ];
2200    
2201            if (iMaxStreams < 0)
2202                    return LSCP_FAILED;
2203    
2204            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2205          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2206  }  }
2207    
2208    
2209  /**  /**
2210   *  Add an effect send to a sampler channel:   *  Add an effect send to a sampler channel:
2211   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<name>]   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2212   *   *
2213   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2214   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
2215   *  @param iMidiController  MIDI controller used to alter the effect,   *  @param iMidiController  MIDI controller used to alter the effect,
2216   *                          usually a number between 0 and 127.   *                          usually a number between 0 and 127.
2217   *  @param pszName          Optional name for the effect send entity,   *  @param pszFxName        Optional name for the effect send entity,
2218   *                          does not have to be unique.   *                          does not have to be unique.
2219   *   *
2220   *  @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.
2221   */   */
2222  int lscp_create_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iMidiController, const char *pszFxName )  int lscp_create_fxsend ( lscp_client_t *pClient,
2223            int iSamplerChannel, int iMidiController, const char *pszFxName )
2224  {  {
2225          int iFxSend = -1;          int iFxSend = -1;
2226          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1867  int lscp_create_fxsend ( lscp_client_t * Line 2233  int lscp_create_fxsend ( lscp_client_t *
2233          // Lock this section up.          // Lock this section up.
2234          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2235    
2236          sprintf(szQuery, "CREATE FX_SEND %d %d", iSamplerChannel, iMidiController);          sprintf(szQuery, "CREATE FX_SEND %d %d",
2237                            iSamplerChannel, iMidiController);
2238    
2239          if (pszFxName)          if (pszFxName)
2240                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2241    
# Line 1894  int lscp_create_fxsend ( lscp_client_t * Line 2261  int lscp_create_fxsend ( lscp_client_t *
2261   *   *
2262   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2263   */   */
2264  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend )  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2265            int iSamplerChannel, int iFxSend )
2266  {  {
2267          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2268    
2269          if (iSamplerChannel < 0 || iFxSend < 0)          if (iSamplerChannel < 0 || iFxSend < 0)
2270                  return LSCP_FAILED;                  return LSCP_FAILED;
2271    
2272          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n", iSamplerChannel, iFxSend);          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2273                    iSamplerChannel, iFxSend);
2274    
2275          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2276  }  }
# Line 1991  int *lscp_list_fxsends ( lscp_client_t * Line 2360  int *lscp_list_fxsends ( lscp_client_t *
2360   *  @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
2361   *  information of the given FX send, or NULL in case of failure.   *  information of the given FX send, or NULL in case of failure.
2362   */   */
2363  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,
2364            int iSamplerChannel, int iFxSend )
2365  {  {
2366          lscp_fxsend_info_t *pFxSendInfo;          lscp_fxsend_info_t *pFxSendInfo;
2367          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2000  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2370  lscp_fxsend_info_t *lscp_get_fxsend_info
2370          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2371          char *pszToken;          char *pszToken;
2372          char *pch;          char *pch;
2373            struct _locale_t locale;
2374    
2375          if (pClient == NULL)          if (pClient == NULL)
2376                  return NULL;                  return NULL;
# Line 2009  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2380  lscp_fxsend_info_t *lscp_get_fxsend_info
2380          // Lock this section up.          // Lock this section up.
2381          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2382    
2383            _save_and_set_c_locale(&locale);
2384    
2385          pFxSendInfo = &(pClient->fxsend_info);          pFxSendInfo = &(pClient->fxsend_info);
2386          lscp_fxsend_info_reset(pFxSendInfo);          lscp_fxsend_info_reset(pFxSendInfo);
2387    
# Line 2038  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2411  lscp_fxsend_info_t *lscp_get_fxsend_info
2411                          else if (strcasecmp(pszToken, "LEVEL") == 0) {                          else if (strcasecmp(pszToken, "LEVEL") == 0) {
2412                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2413                                  if (pszToken)                                  if (pszToken)
2414                                          pFxSendInfo->level = (float) atof(lscp_ltrim(pszToken));                                          pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2415                          }                          }
2416                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2417                  }                  }
2418          }          }
2419          else pFxSendInfo = NULL;          else pFxSendInfo = NULL;
2420    
2421            _restore_locale(&locale);
2422    
2423          // Unlock this section up.          // Unlock this section up.
2424          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2425    
2426          return pFxSendInfo;          return pFxSendInfo;
2427  }  }
2428    
2429    
2430  /**  /**
2431   *  Alter effect send's name:   *  Alter effect send's name:
2432   *  @code   *  @code
# Line 2064  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2440  lscp_fxsend_info_t *lscp_get_fxsend_info
2440   *   *
2441   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2442   */   */
2443  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,
2444            int iSamplerChannel, int iFxSend, const char *pszFxName )
2445  {  {
2446          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2447    
2448          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2449                  return LSCP_FAILED;                  return LSCP_FAILED;
2450    
2451          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",
2452                    iSamplerChannel, iFxSend, pszFxName);
2453          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2454  }  }
2455    
2456    
2457  /**  /**
2458   *  Alter effect send's audio routing:   *  Alter effect send's audio routing:
2459   *  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 2467  lscp_status_t lscp_set_fxsend_name ( lsc
2467   *   *
2468   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2469   */   */
2470  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,
2471            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2472  {  {
2473          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2474    
2475          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2476                  return LSCP_FAILED;                  return LSCP_FAILED;
2477    
2478          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",
2479                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2480          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2481  }  }
2482    
# Line 2112  lscp_status_t lscp_set_fxsend_audio_chan Line 2493  lscp_status_t lscp_set_fxsend_audio_chan
2493   *   *
2494   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2495   */   */
2496  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,
2497            int iSamplerChannel, int iFxSend, int iMidiController )
2498  {  {
2499          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2500    
2501          if (iSamplerChannel < 0 || iFxSend < 0 || iMidiController < 0 || iMidiController > 127)          if (iSamplerChannel < 0 || iFxSend < 0 ||
2502                    iMidiController < 0 || iMidiController > 127)
2503                  return LSCP_FAILED;                  return LSCP_FAILED;
2504    
2505          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",
2506                    iSamplerChannel, iFxSend, iMidiController);
2507          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2508  }  }
2509    
# Line 2135  lscp_status_t lscp_set_fxsend_midi_contr Line 2519  lscp_status_t lscp_set_fxsend_midi_contr
2519   *   *
2520   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2521   */   */
2522  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,
2523            int iSamplerChannel, int iFxSend, float fLevel )
2524  {  {
2525          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2526            struct _locale_t locale;
2527    
2528          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2529                  return LSCP_FAILED;                  return LSCP_FAILED;
2530    
2531          sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n", iSamplerChannel, iFxSend, fLevel);          _save_and_set_c_locale(&locale);
2532            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2533                    iSamplerChannel, iFxSend, fLevel);
2534            _restore_locale(&locale);
2535    
2536          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2537  }  }
2538    
# Line 2169  int lscp_add_midi_instrument_map ( lscp_ Line 2559  int lscp_add_midi_instrument_map ( lscp_
2559          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2560    
2561          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2562            
2563          if (pszMapName)          if (pszMapName)
2564                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2565    
# Line 2295  const char *lscp_get_midi_instrument_map Line 2685  const char *lscp_get_midi_instrument_map
2685    
2686          // Lock this section up.          // Lock this section up.
2687          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2688            
2689          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2690                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2691                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
# Line 2359  lscp_status_t lscp_set_midi_instrument_m Line 2749  lscp_status_t lscp_set_midi_instrument_m
2749   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2750   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2751   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2752   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2753   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2754   *                          1.0 for amplification.   *                          1.0 for amplification.
2755   *  @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 2761  lscp_status_t lscp_set_midi_instrument_m
2761   *   *
2762   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2763   */   */
2764  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,
2765            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2766            const char *pszFileName, int iInstrIndex, float fVolume,
2767            lscp_load_mode_t load_mode, const char *pszName )
2768  {  {
2769          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2770            struct _locale_t locale;
2771    
2772          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2773                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 2387  lscp_status_t lscp_map_midi_instrument ( Line 2781  lscp_status_t lscp_map_midi_instrument (
2781          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2782                  fVolume = 1.0f;                  fVolume = 1.0f;
2783    
2784            _save_and_set_c_locale(&locale);
2785          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2786                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2787                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2788            _restore_locale(&locale);
2789    
2790          switch (load_mode) {          switch (load_mode) {
2791          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2424  lscp_status_t lscp_map_midi_instrument ( Line 2820  lscp_status_t lscp_map_midi_instrument (
2820   *   *
2821   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2822   */   */
2823  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,
2824            lscp_midi_instrument_t *pMidiInstr )
2825  {  {
2826          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2827    
# Line 2517  lscp_midi_instrument_t *lscp_list_midi_i Line 2914  lscp_midi_instrument_t *lscp_list_midi_i
2914          strcat(szQuery, "\r\n");          strcat(szQuery, "\r\n");
2915    
2916          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2917                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));                  pClient->midi_instruments = lscp_midi_instruments_create(
2918                            lscp_client_get_result(pClient));
2919    
2920          // Unlock this section down.          // Unlock this section down.
2921          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 2537  lscp_midi_instrument_t *lscp_list_midi_i Line 2935  lscp_midi_instrument_t *lscp_list_midi_i
2935   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2936   *  or NULL in case of failure.   *  or NULL in case of failure.
2937   */   */
2938  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,
2939            lscp_midi_instrument_t *pMidiInstr )
2940  {  {
2941          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2942          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2546  lscp_midi_instrument_info_t *lscp_get_mi Line 2945  lscp_midi_instrument_info_t *lscp_get_mi
2945          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2946          char *pszToken;          char *pszToken;
2947          char *pch;          char *pch;
2948            struct _locale_t locale;
2949    
2950          if (pClient == NULL)          if (pClient == NULL)
2951                  return NULL;                  return NULL;
# Line 2558  lscp_midi_instrument_info_t *lscp_get_mi Line 2958  lscp_midi_instrument_info_t *lscp_get_mi
2958    
2959          // Lock this section up.          // Lock this section up.
2960          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2961            
2962            _save_and_set_c_locale(&locale);
2963    
2964          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2965          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2966    
# Line 2612  lscp_midi_instrument_info_t *lscp_get_mi Line 3014  lscp_midi_instrument_info_t *lscp_get_mi
3014                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3015                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3016                                  if (pszToken)                                  if (pszToken)
3017                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3018                          }                          }
3019                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3020                  }                  }
3021          }          }
3022          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3023    
3024            _restore_locale(&locale);
3025    
3026          // Unlock this section down.          // Unlock this section down.
3027          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3028    
# Line 2651  lscp_status_t lscp_clear_midi_instrument Line 3055  lscp_status_t lscp_clear_midi_instrument
3055          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
3056  }  }
3057    
3058    
3059  /**  /**
3060   * Open an instrument editor application for the instrument   * Open an instrument editor application for the instrument
3061   * on the given sampler channel:   * on the given sampler channel:

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

  ViewVC Help
Powered by ViewVC