/[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 3664 by schoenebeck, Sun Dec 22 12:53:26 2019 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-2008, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This library is free software; you can redistribute it and/or     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    #include <sys/time.h>
26    #include <sys/errno.h>
27    
28  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
29  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
30    
31    
32    // Whether to use getaddrinfo() instead
33    // of deprecated gethostbyname()
34    #if !defined(WIN32)
35    #define USE_GETADDRINFO 1
36    #endif
37    
38    
39  // Local prototypes.  // Local prototypes.
40    
41  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
42    
43  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
44  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,
45            int iSubscribe, lscp_event_t event);
46    
47    
48    //-------------------------------------------------------------------------
49    // General helper functions.
50    
51    struct _locale_t {
52            char numeric[32];
53            char ctype[32];
54    };
55    
56    // we need to ensure a constant locale setting e.g. for parsing
57    // floating point numbers with atof(), as the floating point separator
58    // character varies by the invidual locale settings
59    static void _save_and_set_c_locale(struct _locale_t* locale)
60    {
61            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
62            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
63            setlocale(LC_NUMERIC, "C");
64            setlocale(LC_CTYPE, "C");
65    }
66    
67    // restore the original locale setting as nothing happened
68    static void _restore_locale(struct _locale_t* locale)
69    {
70            setlocale(LC_NUMERIC, locale->numeric);
71            setlocale(LC_CTYPE, locale->ctype);
72    }
73    
74    // seems the standard atof() function doesnt care much about locale
75    // runtime modifications, so we use this workaround
76    static float _atof(const char* txt) {
77            float f;
78            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
79            return f;
80    }
81    
82    
83  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 96  static void _lscp_client_evt_proc ( void
96          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
97          int    cchBuffer;          int    cchBuffer;
98          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
99          char * pszToken;          char  *pszToken;
100          char * pch;          char  *pch;
101          int     cchToken;          int    cchToken;
102    
103          lscp_event_t event;          lscp_event_t event;
104    
105  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 131  static void _lscp_client_evt_proc ( void
131                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
132                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
133                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
134                                  // Parse for the notification event message...                                  pch = achBuffer;
135                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
136                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
137                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
138                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
139                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
140                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
141                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
142                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
143                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
144                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
145                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
146                                                                  pClient,                                                          // Invoke the client event callback...
147                                                                  event,                                                          if ((*pClient->pfnCallback)(
148                                                                  pszToken,                                                                          pClient,
149                                                                  cchToken,                                                                          event,
150                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
151                                                          pClient->evt.iState = 0;                                                                          cchToken,
152                                                                            pClient->pvData) != LSCP_OK) {
153                                                                    pClient->evt.iState = 0;
154                                                            }
155                                                  }                                                  }
156                                          }                                          }
157                                  }                                  } while (*pch);
158                          } else {                          } else {
159                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
160                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
161                                    pClient->iErrno = -errno;
162                          }                          }
163                  }   // Check if select has in error.                  }   // Check if select has in error.
164                  else if (iSelect < 0) {                  else if (iSelect < 0) {
165                          lscp_socket_perror("_lscp_client_evt_proc: select");                          lscp_socket_perror("_lscp_client_evt_proc: select");
166                          pClient->evt.iState = 0;                          pClient->evt.iState = 0;
167                            pClient->iErrno = -errno;
168                  }                  }
169    
170                  // Finally, always signal the event.                  // Finally, always signal the event.
# Line 146  static lscp_status_t _lscp_client_evt_co Line 198  static lscp_status_t _lscp_client_evt_co
198          }          }
199    
200  #if defined(WIN32)  #if defined(WIN32)
201          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
202                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
203                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
204  #endif  #endif
205    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 227  static lscp_status_t _lscp_client_evt_co
227    
228    
229  // Subscribe to a single event.  // Subscribe to a single event.
230  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,
231            int iSubscribe, lscp_event_t event )
232  {  {
233          const char *pszEvent;          const char *pszEvent;
234          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 243  static lscp_status_t _lscp_client_evt_re
243                  return LSCP_FAILED;                  return LSCP_FAILED;
244    
245          // Build the query string...          // Build the query string...
246          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
247                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
248          // Just send data, forget result...          // Just send data, forget result...
249          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
250                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 219  const char* lscp_client_package (void) { Line 274  const char* lscp_client_package (void) {
274  /** Retrieve the current client library version string. */  /** Retrieve the current client library version string. */
275  const char* lscp_client_version (void) { return LSCP_VERSION; }  const char* lscp_client_version (void) { return LSCP_VERSION; }
276    
277  /** Retrieve the current client library build timestamp string. */  /** Retrieve the current client library build string. */
278  const char* lscp_client_build   (void) { return __DATE__ " " __TIME__; }  const char* lscp_client_build   (void) { return LSCP_BUILD; }
279    
280    
281  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 240  const char* lscp_client_build   (void) { Line 295  const char* lscp_client_build   (void) {
295   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
296   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
297   */   */
298  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,
299            lscp_client_proc_t pfnCallback, void *pvData )
300  {  {
301          lscp_client_t  *pClient;          lscp_client_t  *pClient;
302    #if defined(USE_GETADDRINFO)
303            char szPort[33];
304            struct addrinfo hints;
305            struct addrinfo *result, *res;
306    #else
307          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
308          struct sockaddr_in addr;          struct sockaddr_in addr;
309          int cAddr;          int cAddr;
310    #endif  /* !USE_GETADDRINFO */
311            lscp_socket_t sock;
312  #if defined(WIN32)  #if defined(WIN32)
313          int iSockOpt = (-1);          int iSockOpt = (-1);
314  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 318  lscp_client_t* lscp_client_create ( cons
318                  return NULL;                  return NULL;
319          }          }
320    
321    #if defined(USE_GETADDRINFO)
322    
323            // Convert port number to string/name...
324            snprintf(szPort, sizeof(szPort), "%d", iPort);
325    
326            // Obtain address(es) matching host/port...
327            memset(&hints, 0, sizeof(struct addrinfo));
328            hints.ai_family = AF_INET;
329            hints.ai_socktype = SOCK_STREAM;
330    
331            result = NULL;
332    
333            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
334                    lscp_socket_herror("lscp_client_create: getaddrinfo");
335                    return NULL;
336            }
337    
338    #else
339    
340            // Obtain host matching name...
341          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
342          if (pHost == NULL) {          if (pHost == NULL) {
343                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
344                  return NULL;                  return NULL;
345          }          }
346    
347    #endif  /* !USE_GETADDRINFO */
348    
349          // Allocate client descriptor...          // Allocate client descriptor...
350    
351          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 359  lscp_client_t* lscp_client_create ( cons
359          pClient->pvData = pvData;          pClient->pvData = pvData;
360    
361  #ifdef DEBUG  #ifdef DEBUG
362          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
363                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
364                     pClient, pszHost, iPort);
365  #endif  #endif
366    
367          // Prepare the command connection socket...          // Prepare the command connection socket...
368    
369    #if defined(USE_GETADDRINFO)
370    
371            // getaddrinfo() returns a list of address structures;
372            // try each address until we successfully connect(2);
373            // if socket or connect fails, we close the socket and
374            // try the next address...
375            sock = INVALID_SOCKET;
376    
377            for (res = result; res; res = res->ai_next) {
378                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
379                    if (sock == INVALID_SOCKET)
380                            continue;
381            #if defined(WIN32)
382                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
383                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
384                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
385            #endif
386            #ifdef DEBUG
387                    lscp_socket_getopts("lscp_client_create: cmd", sock);
388            #endif
389                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
390                            break;
391                    closesocket(sock);
392            }
393    
394            if (sock == INVALID_SOCKET) {
395                    lscp_socket_perror("lscp_client_create: cmd: socket");
396                    free(pClient);
397                    return NULL;
398            }
399    
400            if (res == NULL) {
401                    lscp_socket_perror("lscp_client_create: cmd: connect");
402                    free(pClient);
403                    return NULL;
404            }
405    
406            // Initialize the command socket agent struct...
407            lscp_socket_agent_init(&(pClient->cmd), sock,
408                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
409    
410            // No longer needed...
411            freeaddrinfo(result);
412    
413    #else
414    
415          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
416          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
417                  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 420  lscp_client_t* lscp_client_create ( cons
420          }          }
421    
422  #if defined(WIN32)  #if defined(WIN32)
423          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
424                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
425                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
426  #endif  #endif
427    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 445  lscp_client_t* lscp_client_create ( cons
445          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
446          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
447    
448    #endif  /* !USE_GETADDRINFO */
449    
450  #ifdef DEBUG  #ifdef DEBUG
451          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,
452                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
453                    pClient, pClient->cmd.sock,
454                    inet_ntoa(pClient->cmd.addr.sin_addr),
455                    ntohs(pClient->cmd.addr.sin_port));
456  #endif  #endif
457    
458          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 503  int lscp_client_get_timeout ( lscp_clien Line 642  int lscp_client_get_timeout ( lscp_clien
642          return pClient->iTimeout;          return pClient->iTimeout;
643  }  }
644    
645    /**
646     *  Check whether connection to server is lost.
647     *
648     *  @param pClient  Pointer to client instance structure.
649     *
650     *  @returns @c true if client lost connection to server, @c false otherwise.
651     */
652    bool lscp_client_connection_lost ( lscp_client_t *pClient )
653    {
654        int err = lscp_client_get_errno(pClient);
655        if (err >= 0) return false;
656        return err == -EPIPE || err == -ECONNRESET || err == -ECONNABORTED;
657    }
658    
659    
660  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
661  // Client common protocol functions.  // Client common protocol functions.
# Line 578  int lscp_client_get_errno ( lscp_client_ Line 731  int lscp_client_get_errno ( lscp_client_
731  // Client registration protocol functions.  // Client registration protocol functions.
732    
733  /**  /**
734   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
735     *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
736     *  for @e each event you want to subscribe. That is the old bitflag approach
737     *  was abondoned at this point. You can however still register all older
738     *  events with one lscp_client_subscribe() call at once. Thus, the old
739     *  behavior of this functions was not broken. Those older events are namely:
740     *  @code
741   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
742   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
743   *      | 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 745  int lscp_client_get_errno ( lscp_client_
745   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
746   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
747   *      | MISCELLANEOUS   *      | MISCELLANEOUS
748     *  @endcode
749     *  The old events occupy the lower 16 bits (as bit flags), and all younger
750     *  events enumerate the whole upper 16 bits range. The new, enumerated
751     *  events are namely:
752     *  @code
753     *  SUBSCRIBE CHANNEL_MIDI
754     *  @endcode
755   *   *
756   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
757   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
758   *   *
759   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
760   */   */
761  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 )
762  {  {
763          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
764            lscp_event_t currentEvent;
765    
766          if (pClient == NULL)          if (pClient == NULL)
767                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 637  lscp_status_t lscp_client_subscribe ( ls Line 804  lscp_status_t lscp_client_subscribe ( ls
804                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
805          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
806                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
807            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
808            currentEvent = events & 0xffff0000;
809            if (ret == LSCP_OK && currentEvent) {
810                    switch (currentEvent) {
811                            case LSCP_EVENT_CHANNEL_MIDI:
812                            case LSCP_EVENT_DEVICE_MIDI:
813                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
814                                    break;
815                            default: // unknown "upper" event type
816                                    ret = LSCP_FAILED;
817                                    break;
818                    }
819            }
820    
821          // Unlock this section down.          // Unlock this section down.
822          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 646  lscp_status_t lscp_client_subscribe ( ls Line 826  lscp_status_t lscp_client_subscribe ( ls
826    
827    
828  /**  /**
829   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
830     *  @e Caution: since liblscp v0.5.5.4 you have to call
831     *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
832     *  That is the old bitflag approach was abondoned at this point. You can
833     *  however still register all older events with one lscp_client_subscribe()
834     *  call at once. Thus, the old behavior of this functions was not broken.
835     *  Those older events are namely:
836     *  @code
837   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT   *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
838   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT   *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
839   *      | 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 841  lscp_status_t lscp_client_subscribe ( ls
841   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO   *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
842   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO   *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
843   *      | MISCELLANEOUS   *      | MISCELLANEOUS
844     *  @endcode
845     *  The old events occupy the lower 16 bits (as bit flags), and all younger
846     *  events enumerate the whole upper 16 bits range. The new, enumerated
847     *  events are namely:
848     *  @code
849     *  UNSUBSCRIBE CHANNEL_MIDI
850     *  @endcode
851   *   *
852   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
853   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
854   *   *
855   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
856   */   */
857  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 )
858  {  {
859          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
860            lscp_event_t currentEvent;
861    
862          if (pClient == NULL)          if (pClient == NULL)
863                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 701  lscp_status_t lscp_client_unsubscribe ( Line 896  lscp_status_t lscp_client_unsubscribe (
896                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
897          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
898                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
899            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
900            currentEvent = events & 0xffff0000;
901            if (ret == LSCP_OK && currentEvent) {
902                    switch (currentEvent) {
903                            case LSCP_EVENT_CHANNEL_MIDI:
904                            case LSCP_EVENT_DEVICE_MIDI:
905                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
906                                    break;
907                            default: // unknown "upper" event type
908                                    ret = LSCP_FAILED;
909                                    break;
910                    }
911            }
912    
913          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
914          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 743  lscp_event_t lscp_client_get_events ( ls Line 951  lscp_event_t lscp_client_get_events ( ls
951   *   *
952   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
953   */   */
954  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,
955            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
956  {  {
957          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
958    
959          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
960                  return LSCP_FAILED;                  return LSCP_FAILED;
961    
962          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
963                    pszFileName, iInstrIndex, iSamplerChannel);
964          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
965  }  }
966    
# Line 766  lscp_status_t lscp_load_instrument ( lsc Line 976  lscp_status_t lscp_load_instrument ( lsc
976   *   *
977   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
978   */   */
979  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,
980            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
981  {  {
982          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
983    
984          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
985                  return LSCP_FAILED;                  return LSCP_FAILED;
986    
987          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",
988                    pszFileName, iInstrIndex, iSamplerChannel);
989          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
990  }  }
991    
# Line 795  lscp_status_t lscp_load_engine ( lscp_cl Line 1007  lscp_status_t lscp_load_engine ( lscp_cl
1007          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
1008                  return LSCP_FAILED;                  return LSCP_FAILED;
1009    
1010          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
1011                    pszEngineName, iSamplerChannel);
1012          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1013  }  }
1014    
# Line 986  const char **lscp_list_available_engines Line 1199  const char **lscp_list_available_engines
1199   *  @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
1200   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1201   */   */
1202  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,
1203            const char *pszEngineName )
1204  {  {
1205          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1206          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1053  lscp_channel_info_t *lscp_get_channel_in Line 1267  lscp_channel_info_t *lscp_get_channel_in
1267          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1268          char *pszToken;          char *pszToken;
1269          char *pch;          char *pch;
1270            struct _locale_t locale;
1271    
1272          if (pClient == NULL)          if (pClient == NULL)
1273                  return NULL;                  return NULL;
# Line 1065  lscp_channel_info_t *lscp_get_channel_in Line 1280  lscp_channel_info_t *lscp_get_channel_in
1280          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1281          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1282    
1283            _save_and_set_c_locale(&locale);
1284    
1285          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1286          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1287                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1149  lscp_channel_info_t *lscp_get_channel_in Line 1366  lscp_channel_info_t *lscp_get_channel_in
1366                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1367                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1368                                  if (pszToken)                                  if (pszToken)
1369                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1370                          }                          }
1371                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1372                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1166  lscp_channel_info_t *lscp_get_channel_in Line 1383  lscp_channel_info_t *lscp_get_channel_in
1383          }          }
1384          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1385    
1386            _restore_locale(&locale);
1387    
1388          // Unlock this section up.          // Unlock this section up.
1389          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1390    
# Line 1309  int lscp_get_channel_stream_usage ( lscp Line 1528  int lscp_get_channel_stream_usage ( lscp
1528   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1529   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1530   */   */
1531  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,
1532            lscp_usage_t usage_type, int iSamplerChannel )
1533  {  {
1534          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1535          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1382  lscp_buffer_fill_t *lscp_get_channel_buf Line 1602  lscp_buffer_fill_t *lscp_get_channel_buf
1602   *   *
1603   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1604   */   */
1605  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,
1606            int iSamplerChannel, const char *pszAudioDriver )
1607  {  {
1608          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1609    
1610          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1611                  return LSCP_FAILED;                  return LSCP_FAILED;
1612    
1613          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1614                    iSamplerChannel, pszAudioDriver);
1615          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1616  }  }
1617    
# Line 1404  lscp_status_t lscp_set_channel_audio_typ Line 1626  lscp_status_t lscp_set_channel_audio_typ
1626   *   *
1627   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1628   */   */
1629  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,
1630            int iSamplerChannel, int iAudioDevice )
1631  {  {
1632          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1633    
1634          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1635                  return LSCP_FAILED;                  return LSCP_FAILED;
1636    
1637          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1638                    iSamplerChannel, iAudioDevice);
1639          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1640  }  }
1641    
# Line 1427  lscp_status_t lscp_set_channel_audio_dev Line 1651  lscp_status_t lscp_set_channel_audio_dev
1651   *   *
1652   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1653   */   */
1654  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,
1655            int iSamplerChannel, int iAudioOut, int iAudioIn )
1656  {  {
1657          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1658    
1659          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1660                  return LSCP_FAILED;                  return LSCP_FAILED;
1661    
1662          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",
1663                    iSamplerChannel, iAudioOut, iAudioIn);
1664          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1665  }  }
1666    
# Line 1449  lscp_status_t lscp_set_channel_audio_cha Line 1675  lscp_status_t lscp_set_channel_audio_cha
1675   *   *
1676   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1677   */   */
1678  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,
1679            int iSamplerChannel, const char *pszMidiDriver )
1680  {  {
1681          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1682    
1683          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1684                  return LSCP_FAILED;                  return LSCP_FAILED;
1685    
1686          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1687                    iSamplerChannel, pszMidiDriver);
1688          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1689  }  }
1690    
# Line 1471  lscp_status_t lscp_set_channel_midi_type Line 1699  lscp_status_t lscp_set_channel_midi_type
1699   *   *
1700   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1701   */   */
1702  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,
1703            int iSamplerChannel, int iMidiDevice )
1704  {  {
1705          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1706    
1707          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1708                  return LSCP_FAILED;                  return LSCP_FAILED;
1709    
1710          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1711                    iSamplerChannel, iMidiDevice);
1712          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1713  }  }
1714    
# Line 1493  lscp_status_t lscp_set_channel_midi_devi Line 1723  lscp_status_t lscp_set_channel_midi_devi
1723   *   *
1724   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1725   */   */
1726  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,
1727            int iSamplerChannel, int iMidiPort )
1728  {  {
1729          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1730    
1731          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1732                  return LSCP_FAILED;                  return LSCP_FAILED;
1733    
1734          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1735                    iSamplerChannel, iMidiPort);
1736          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1737  }  }
1738    
# Line 1516  lscp_status_t lscp_set_channel_midi_port Line 1748  lscp_status_t lscp_set_channel_midi_port
1748   *   *
1749   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1750   */   */
1751  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,
1752            int iSamplerChannel, int iMidiChannel )
1753  {  {
1754          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1755    
# Line 1524  lscp_status_t lscp_set_channel_midi_chan Line 1757  lscp_status_t lscp_set_channel_midi_chan
1757                  return LSCP_FAILED;                  return LSCP_FAILED;
1758    
1759          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1760                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1761                            iSamplerChannel);
1762          else          else
1763                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1764                            iSamplerChannel, iMidiChannel);
1765          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1766  }  }
1767    
# Line 1543  lscp_status_t lscp_set_channel_midi_chan Line 1778  lscp_status_t lscp_set_channel_midi_chan
1778   *   *
1779   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1780   */   */
1781  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,
1782            int iSamplerChannel, int iMidiMap )
1783  {  {
1784          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1785    
# Line 1577  lscp_status_t lscp_set_channel_midi_map Line 1813  lscp_status_t lscp_set_channel_midi_map
1813   *   *
1814   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1815   */   */
1816  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,
1817            int iSamplerChannel, float fVolume )
1818  {  {
1819          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1820            struct _locale_t locale;
1821    
1822          if (iSamplerChannel < 0 || fVolume < 0.0f)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1823                  return LSCP_FAILED;                  return LSCP_FAILED;
1824    
1825          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1826            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1827                    iSamplerChannel, fVolume);
1828            _restore_locale(&locale);
1829    
1830          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1831  }  }
1832    
# Line 1601  lscp_status_t lscp_set_channel_volume ( Line 1843  lscp_status_t lscp_set_channel_volume (
1843   *   *
1844   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1845   */   */
1846  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,
1847            int iSamplerChannel, int iMute )
1848  {  {
1849          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1850    
1851          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1852                  return LSCP_FAILED;                  return LSCP_FAILED;
1853    
1854          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1855                    iSamplerChannel, iMute);
1856          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1857  }  }
1858    
# Line 1625  lscp_status_t lscp_set_channel_mute ( ls Line 1869  lscp_status_t lscp_set_channel_mute ( ls
1869   *   *
1870   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1871   */   */
1872  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,
1873            int iSamplerChannel, int iSolo )
1874  {  {
1875          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1876    
1877          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1878                  return LSCP_FAILED;                  return LSCP_FAILED;
1879    
1880          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1881                    iSamplerChannel, iSolo);
1882          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1883  }  }
1884    
# Line 1668  lscp_status_t lscp_reset_channel ( lscp_ Line 1914  lscp_status_t lscp_reset_channel ( lscp_
1914   */   */
1915  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1916  {  {
1917          // Do actual whole sampler reset...          // Do actual whole sampler reset...
1918          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1919  }  }
1920    
# Line 1801  int lscp_get_total_voice_count_max ( lsc Line 2047  int lscp_get_total_voice_count_max ( lsc
2047  float lscp_get_volume ( lscp_client_t *pClient )  float lscp_get_volume ( lscp_client_t *pClient )
2048  {  {
2049          float fVolume = 0.0f;          float fVolume = 0.0f;
2050            struct _locale_t locale;
2051    
2052          if (pClient == NULL)          if (pClient == NULL)
2053                  return 0.0f;                  return 0.0f;
# Line 1808  float lscp_get_volume ( lscp_client_t *p Line 2055  float lscp_get_volume ( lscp_client_t *p
2055          // Lock this section up.          // Lock this section up.
2056          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2057    
2058            _save_and_set_c_locale(&locale);
2059    
2060          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2061                  fVolume = (float) atof(lscp_client_get_result(pClient));                  fVolume = _atof(lscp_client_get_result(pClient));
2062    
2063            _restore_locale(&locale);
2064    
2065          // Unlock this section down.          // Unlock this section down.
2066          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1832  float lscp_get_volume ( lscp_client_t *p Line 2083  float lscp_get_volume ( lscp_client_t *p
2083  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2084  {  {
2085          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2086            struct _locale_t locale;
2087    
2088          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2089                  return LSCP_FAILED;                  return LSCP_FAILED;
2090    
2091            _save_and_set_c_locale(&locale);
2092          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2093            _restore_locale(&locale);
2094    
2095            return lscp_client_query(pClient, szQuery);
2096    }
2097    
2098    
2099    /**
2100     *  Get global voice limit setting:
2101     *  @code
2102     *  GET VOICES
2103     *  @endcode
2104     *  This value reflects the maximum amount of voices a sampler engine
2105     *  processes simultaniously before voice stealing kicks in.
2106     *
2107     *  @param pClient  Pointer to client instance structure.
2108     *
2109     *  @returns The current global maximum amount of voices limit or a
2110     *           negative value on error (e.g. if sampler doesn't support
2111     *           this command).
2112     */
2113    int lscp_get_voices ( lscp_client_t *pClient )
2114    {
2115            int iVoices = -1;
2116    
2117            if (pClient == NULL)
2118                    return -1;
2119    
2120            // Lock this section up.
2121            lscp_mutex_lock(pClient->mutex);
2122    
2123            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2124                    iVoices = atoi(lscp_client_get_result(pClient));
2125    
2126            // Unlock this section down.
2127            lscp_mutex_unlock(pClient->mutex);
2128    
2129            return iVoices;
2130    }
2131    
2132    
2133    /**
2134     *  Setting global voice limit setting:
2135     *  @code
2136     *  SET VOICES <max-voices>
2137     *  @endcode
2138     *  This value reflects the maximum amount of voices a sampler engine
2139     *  processes simultaniously before voice stealing kicks in. Note that
2140     *  this value will be passed to all sampler engine instances, that is
2141     *  the total amount of maximum voices on the running system is thus
2142     *  @param iMaxVoices multiplied with the current amount of sampler
2143     *  engine instances.
2144     *
2145     *  @param pClient     Pointer to client instance structure.
2146     *  @param iMaxVoices  Global voice limit setting as integer value larger
2147     *                     or equal to 1.
2148     *
2149     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2150     */
2151    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2152    {
2153            char szQuery[LSCP_BUFSIZ];
2154    
2155            if (iMaxVoices < 1)
2156                    return LSCP_FAILED;
2157    
2158            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2159            return lscp_client_query(pClient, szQuery);
2160    }
2161    
2162    
2163    /**
2164     *  Get global disk streams limit setting:
2165     *  @code
2166     *  GET STREAMS
2167     *  @endcode
2168     *  This value reflects the maximum amount of disk streams a sampler
2169     *  engine processes simultaniously.
2170     *
2171     *  @param pClient  Pointer to client instance structure.
2172     *
2173     *  @returns The current global maximum amount of disk streams limit
2174     *           or a negative value on error (e.g. if sampler doesn't
2175     *           support this command).
2176     */
2177    int lscp_get_streams ( lscp_client_t *pClient )
2178    {
2179            int iStreams = -1;
2180    
2181            if (pClient == NULL)
2182                    return -1;
2183    
2184            // Lock this section up.
2185            lscp_mutex_lock(pClient->mutex);
2186    
2187            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2188                    iStreams = atoi(lscp_client_get_result(pClient));
2189    
2190            // Unlock this section down.
2191            lscp_mutex_unlock(pClient->mutex);
2192    
2193            return iStreams;
2194    }
2195    
2196    
2197    /**
2198     *  Setting global disk streams limit setting:
2199     *  @code
2200     *  SET STREAMS <max-streams>
2201     *  @endcode
2202     *  This value reflects the maximum amount of dist streams a sampler
2203     *  engine instance processes simultaniously. Note that this value will
2204     *  be passed to all sampler engine instances, that is the total amount
2205     *  of maximum disk streams on the running system is thus
2206     *  @param iMaxStreams multiplied with the current amount of sampler
2207     *  engine instances.
2208     *
2209     *  @param pClient      Pointer to client instance structure.
2210     *  @param iMaxStreams  Global streams limit setting as positive integer
2211     *                      value (larger or equal to 0).
2212     *
2213     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2214     */
2215    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2216    {
2217            char szQuery[LSCP_BUFSIZ];
2218    
2219            if (iMaxStreams < 0)
2220                    return LSCP_FAILED;
2221    
2222            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2223          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2224  }  }
2225    
2226    
2227  /**  /**
2228   *  Add an effect send to a sampler channel:   *  Add an effect send to a sampler channel:
2229   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<name>]   *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2230   *   *
2231   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2232   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
2233   *  @param iMidiController  MIDI controller used to alter the effect,   *  @param iMidiController  MIDI controller used to alter the effect,
2234   *                          usually a number between 0 and 127.   *                          usually a number between 0 and 127.
2235   *  @param pszName          Optional name for the effect send entity,   *  @param pszFxName        Optional name for the effect send entity,
2236   *                          does not have to be unique.   *                          does not have to be unique.
2237   *   *
2238   *  @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.
2239   */   */
2240  int lscp_create_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iMidiController, const char *pszFxName )  int lscp_create_fxsend ( lscp_client_t *pClient,
2241            int iSamplerChannel, int iMidiController, const char *pszFxName )
2242  {  {
2243          int iFxSend = -1;          int iFxSend = -1;
2244          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1867  int lscp_create_fxsend ( lscp_client_t * Line 2251  int lscp_create_fxsend ( lscp_client_t *
2251          // Lock this section up.          // Lock this section up.
2252          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2253    
2254          sprintf(szQuery, "CREATE FX_SEND %d %d", iSamplerChannel, iMidiController);          sprintf(szQuery, "CREATE FX_SEND %d %d",
2255                            iSamplerChannel, iMidiController);
2256    
2257          if (pszFxName)          if (pszFxName)
2258                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2259    
# Line 1894  int lscp_create_fxsend ( lscp_client_t * Line 2279  int lscp_create_fxsend ( lscp_client_t *
2279   *   *
2280   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2281   */   */
2282  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend )  lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2283            int iSamplerChannel, int iFxSend )
2284  {  {
2285          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2286    
2287          if (iSamplerChannel < 0 || iFxSend < 0)          if (iSamplerChannel < 0 || iFxSend < 0)
2288                  return LSCP_FAILED;                  return LSCP_FAILED;
2289    
2290          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n", iSamplerChannel, iFxSend);          sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2291                    iSamplerChannel, iFxSend);
2292    
2293          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2294  }  }
# Line 1991  int *lscp_list_fxsends ( lscp_client_t * Line 2378  int *lscp_list_fxsends ( lscp_client_t *
2378   *  @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
2379   *  information of the given FX send, or NULL in case of failure.   *  information of the given FX send, or NULL in case of failure.
2380   */   */
2381  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,
2382            int iSamplerChannel, int iFxSend )
2383  {  {
2384          lscp_fxsend_info_t *pFxSendInfo;          lscp_fxsend_info_t *pFxSendInfo;
2385          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2000  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2388  lscp_fxsend_info_t *lscp_get_fxsend_info
2388          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2389          char *pszToken;          char *pszToken;
2390          char *pch;          char *pch;
2391            struct _locale_t locale;
2392    
2393          if (pClient == NULL)          if (pClient == NULL)
2394                  return NULL;                  return NULL;
# Line 2009  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2398  lscp_fxsend_info_t *lscp_get_fxsend_info
2398          // Lock this section up.          // Lock this section up.
2399          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2400    
2401            _save_and_set_c_locale(&locale);
2402    
2403          pFxSendInfo = &(pClient->fxsend_info);          pFxSendInfo = &(pClient->fxsend_info);
2404          lscp_fxsend_info_reset(pFxSendInfo);          lscp_fxsend_info_reset(pFxSendInfo);
2405    
# Line 2038  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2429  lscp_fxsend_info_t *lscp_get_fxsend_info
2429                          else if (strcasecmp(pszToken, "LEVEL") == 0) {                          else if (strcasecmp(pszToken, "LEVEL") == 0) {
2430                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2431                                  if (pszToken)                                  if (pszToken)
2432                                          pFxSendInfo->level = (float) atof(lscp_ltrim(pszToken));                                          pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2433                          }                          }
2434                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2435                  }                  }
2436          }          }
2437          else pFxSendInfo = NULL;          else pFxSendInfo = NULL;
2438    
2439            _restore_locale(&locale);
2440    
2441          // Unlock this section up.          // Unlock this section up.
2442          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2443    
2444          return pFxSendInfo;          return pFxSendInfo;
2445  }  }
2446    
2447    
2448  /**  /**
2449   *  Alter effect send's name:   *  Alter effect send's name:
2450   *  @code   *  @code
# Line 2064  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2458  lscp_fxsend_info_t *lscp_get_fxsend_info
2458   *   *
2459   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2460   */   */
2461  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,
2462            int iSamplerChannel, int iFxSend, const char *pszFxName )
2463  {  {
2464          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2465    
2466          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)          if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2467                  return LSCP_FAILED;                  return LSCP_FAILED;
2468    
2469          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",
2470                    iSamplerChannel, iFxSend, pszFxName);
2471          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2472  }  }
2473    
2474    
2475  /**  /**
2476   *  Alter effect send's audio routing:   *  Alter effect send's audio routing:
2477   *  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 2485  lscp_status_t lscp_set_fxsend_name ( lsc
2485   *   *
2486   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2487   */   */
2488  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,
2489            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2490  {  {
2491          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2492    
2493          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)          if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2494                  return LSCP_FAILED;                  return LSCP_FAILED;
2495    
2496          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",
2497                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2498          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2499  }  }
2500    
# Line 2112  lscp_status_t lscp_set_fxsend_audio_chan Line 2511  lscp_status_t lscp_set_fxsend_audio_chan
2511   *   *
2512   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2513   */   */
2514  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,
2515            int iSamplerChannel, int iFxSend, int iMidiController )
2516  {  {
2517          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2518    
2519          if (iSamplerChannel < 0 || iFxSend < 0 || iMidiController < 0 || iMidiController > 127)          if (iSamplerChannel < 0 || iFxSend < 0 ||
2520                    iMidiController < 0 || iMidiController > 127)
2521                  return LSCP_FAILED;                  return LSCP_FAILED;
2522    
2523          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",
2524                    iSamplerChannel, iFxSend, iMidiController);
2525          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2526  }  }
2527    
# Line 2135  lscp_status_t lscp_set_fxsend_midi_contr Line 2537  lscp_status_t lscp_set_fxsend_midi_contr
2537   *   *
2538   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2539   */   */
2540  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,
2541            int iSamplerChannel, int iFxSend, float fLevel )
2542  {  {
2543          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2544            struct _locale_t locale;
2545    
2546          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2547                  return LSCP_FAILED;                  return LSCP_FAILED;
2548    
2549          sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n", iSamplerChannel, iFxSend, fLevel);          _save_and_set_c_locale(&locale);
2550            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2551                    iSamplerChannel, iFxSend, fLevel);
2552            _restore_locale(&locale);
2553    
2554          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2555  }  }
2556    
# Line 2169  int lscp_add_midi_instrument_map ( lscp_ Line 2577  int lscp_add_midi_instrument_map ( lscp_
2577          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2578    
2579          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2580            
2581          if (pszMapName)          if (pszMapName)
2582                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2583    
# Line 2295  const char *lscp_get_midi_instrument_map Line 2703  const char *lscp_get_midi_instrument_map
2703    
2704          // Lock this section up.          // Lock this section up.
2705          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2706            
2707          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2708                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2709                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
# Line 2359  lscp_status_t lscp_set_midi_instrument_m Line 2767  lscp_status_t lscp_set_midi_instrument_m
2767   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2768   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2769   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2770   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2771   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2772   *                          1.0 for amplification.   *                          1.0 for amplification.
2773   *  @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 2779  lscp_status_t lscp_set_midi_instrument_m
2779   *   *
2780   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2781   */   */
2782  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,
2783            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2784            const char *pszFileName, int iInstrIndex, float fVolume,
2785            lscp_load_mode_t load_mode, const char *pszName )
2786  {  {
2787          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2788            struct _locale_t locale;
2789    
2790          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2791                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 2387  lscp_status_t lscp_map_midi_instrument ( Line 2799  lscp_status_t lscp_map_midi_instrument (
2799          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2800                  fVolume = 1.0f;                  fVolume = 1.0f;
2801    
2802            _save_and_set_c_locale(&locale);
2803          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2804                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2805                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2806            _restore_locale(&locale);
2807    
2808          switch (load_mode) {          switch (load_mode) {
2809          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2424  lscp_status_t lscp_map_midi_instrument ( Line 2838  lscp_status_t lscp_map_midi_instrument (
2838   *   *
2839   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2840   */   */
2841  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,
2842            lscp_midi_instrument_t *pMidiInstr )
2843  {  {
2844          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2845    
# Line 2517  lscp_midi_instrument_t *lscp_list_midi_i Line 2932  lscp_midi_instrument_t *lscp_list_midi_i
2932          strcat(szQuery, "\r\n");          strcat(szQuery, "\r\n");
2933    
2934          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2935                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));                  pClient->midi_instruments = lscp_midi_instruments_create(
2936                            lscp_client_get_result(pClient));
2937    
2938          // Unlock this section down.          // Unlock this section down.
2939          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 2537  lscp_midi_instrument_t *lscp_list_midi_i Line 2953  lscp_midi_instrument_t *lscp_list_midi_i
2953   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2954   *  or NULL in case of failure.   *  or NULL in case of failure.
2955   */   */
2956  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,
2957            lscp_midi_instrument_t *pMidiInstr )
2958  {  {
2959          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2960          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2546  lscp_midi_instrument_info_t *lscp_get_mi Line 2963  lscp_midi_instrument_info_t *lscp_get_mi
2963          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2964          char *pszToken;          char *pszToken;
2965          char *pch;          char *pch;
2966            struct _locale_t locale;
2967    
2968          if (pClient == NULL)          if (pClient == NULL)
2969                  return NULL;                  return NULL;
# Line 2558  lscp_midi_instrument_info_t *lscp_get_mi Line 2976  lscp_midi_instrument_info_t *lscp_get_mi
2976    
2977          // Lock this section up.          // Lock this section up.
2978          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2979            
2980            _save_and_set_c_locale(&locale);
2981    
2982          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2983          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2984    
# Line 2612  lscp_midi_instrument_info_t *lscp_get_mi Line 3032  lscp_midi_instrument_info_t *lscp_get_mi
3032                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3033                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3034                                  if (pszToken)                                  if (pszToken)
3035                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3036                          }                          }
3037                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3038                  }                  }
3039          }          }
3040          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3041    
3042            _restore_locale(&locale);
3043    
3044          // Unlock this section down.          // Unlock this section down.
3045          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3046    
# Line 2651  lscp_status_t lscp_clear_midi_instrument Line 3073  lscp_status_t lscp_clear_midi_instrument
3073          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
3074  }  }
3075    
3076    
3077  /**  /**
3078   * Open an instrument editor application for the instrument   * Open an instrument editor application for the instrument
3079   * on the given sampler channel:   * on the given sampler channel:

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

  ViewVC Help
Powered by ViewVC