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

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

  ViewVC Help
Powered by ViewVC