/[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 975 by capela, Sun Dec 17 00:59:40 2006 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-2006, 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 327  lscp_client_t* lscp_client_create ( cons Line 460  lscp_client_t* lscp_client_create ( cons
460          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
461          pClient->engines = NULL;          pClient->engines = NULL;
462          pClient->channels = NULL;          pClient->channels = NULL;
463            pClient->fxsends = NULL;
464          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
465          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
466          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 343  lscp_client_t* lscp_client_create ( cons Line 477  lscp_client_t* lscp_client_create ( cons
477          lscp_server_info_init(&(pClient->server_info));          lscp_server_info_init(&(pClient->server_info));
478          lscp_engine_info_init(&(pClient->engine_info));          lscp_engine_info_init(&(pClient->engine_info));
479          lscp_channel_info_init(&(pClient->channel_info));          lscp_channel_info_init(&(pClient->channel_info));
480            lscp_fxsend_info_init(&(pClient->fxsend_info));
481          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
482          // Initialize error stuff.          // Initialize error stuff.
483          pClient->pszResult = NULL;          pClient->pszResult = NULL;
# Line 405  lscp_status_t lscp_client_destroy ( lscp Line 540  lscp_status_t lscp_client_destroy ( lscp
540    
541          // Free up all cached members.          // Free up all cached members.
542          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
543            lscp_fxsend_info_free(&(pClient->fxsend_info));
544          lscp_channel_info_free(&(pClient->channel_info));          lscp_channel_info_free(&(pClient->channel_info));
545          lscp_engine_info_free(&(pClient->engine_info));          lscp_engine_info_free(&(pClient->engine_info));
546          lscp_server_info_free(&(pClient->server_info));          lscp_server_info_free(&(pClient->server_info));
# Line 425  lscp_status_t lscp_client_destroy ( lscp Line 561  lscp_status_t lscp_client_destroy ( lscp
561          lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->midi_devices);
562          lscp_szsplit_destroy(pClient->engines);          lscp_szsplit_destroy(pClient->engines);
563          lscp_isplit_destroy(pClient->channels);          lscp_isplit_destroy(pClient->channels);
564            lscp_isplit_destroy(pClient->fxsends);
565          lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_midi_instruments_destroy(pClient->midi_instruments);
566          lscp_isplit_destroy(pClient->midi_maps);          lscp_isplit_destroy(pClient->midi_maps);
567          if (pClient->midi_map_name)          if (pClient->midi_map_name)
# Line 436  lscp_status_t lscp_client_destroy ( lscp Line 573  lscp_status_t lscp_client_destroy ( lscp
573          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
574          pClient->engines = NULL;          pClient->engines = NULL;
575          pClient->channels = NULL;          pClient->channels = NULL;
576            pClient->fxsends = NULL;
577          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
578          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
579          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 573  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   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
716   *      | CHANNEL_INFO | MISCELLANEOUS   *  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
722     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
723     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
724     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
725     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
726     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
727     *      | 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 607  lscp_status_t lscp_client_subscribe ( ls Line 764  lscp_status_t lscp_client_subscribe ( ls
764                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
765          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
766                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
767            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
768                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
769            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
770                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
771            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
772                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
773            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
774                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
775            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
776                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
777            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
778                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
779            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
780                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
781            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
782                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
783            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
784                    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 618  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   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call
811   *      | CHANNEL_INFO | MISCELLANEOUS   *  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
818     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
819     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
820     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
821     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
822     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
823     *      | 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 648  lscp_status_t lscp_client_unsubscribe ( Line 856  lscp_status_t lscp_client_unsubscribe (
856                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
857          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
858                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
859            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
860                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
861            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
862                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
863            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
864                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
865            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
866                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
867            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
868                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
869            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
870                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
871            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
872                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
873            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
874                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
875            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
876                    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 692  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 715  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 744  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 935  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 1002  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 1014  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 1038  lscp_channel_info_t *lscp_get_channel_in Line 1286  lscp_channel_info_t *lscp_get_channel_in
1286                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1287                                  if (pszToken) {                                  if (pszToken) {
1288                                          if (pChannelInfo->audio_routing)                                          if (pChannelInfo->audio_routing)
1289                                                  lscp_szsplit_destroy(pChannelInfo->audio_routing);                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1290                                          pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1291                                  }                                  }
1292                          }                          }
1293                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
# Line 1098  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 1115  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 1258  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 1331  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 1353  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 1376  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 1398  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 1420  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 1442  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 1465  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 1473  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 1492  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 1526  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.0)          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 1550  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 1574  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 1617  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...
1898          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1899  }  }
1900    
# Line 1662  lscp_server_info_t *lscp_get_server_info Line 1940  lscp_server_info_t *lscp_get_server_info
1940                                  if (pszToken)                                  if (pszToken)
1941                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1942                          }                          }
1943                            else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1944                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1945                                    if (pszToken)
1946                                            lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1947                            }
1948                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1949                  }                  }
1950          }          }
# Line 1733  int lscp_get_total_voice_count_max ( lsc Line 2016  int lscp_get_total_voice_count_max ( lsc
2016    
2017    
2018  /**  /**
2019     *  Get global volume attenuation:
2020     *  GET VOLUME
2021     *
2022     *  @param pClient  Pointer to client instance structure.
2023     *
2024     *  @returns The global volume as positive floating point value usually in
2025     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2026     */
2027    float lscp_get_volume ( lscp_client_t *pClient )
2028    {
2029            float fVolume = 0.0f;
2030            struct _locale_t locale;
2031    
2032            if (pClient == NULL)
2033                    return 0.0f;
2034    
2035            // Lock this section up.
2036            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)
2041                    fVolume = _atof(lscp_client_get_result(pClient));
2042    
2043            _restore_locale(&locale);
2044    
2045            // Unlock this section down.
2046            lscp_mutex_unlock(pClient->mutex);
2047    
2048            return fVolume;
2049    }
2050    
2051    
2052    /**
2053     *  Setting global volume attenuation:
2054     *  SET VOLUME <volume>
2055     *
2056     *  @param pClient  Pointer to client instance structure.
2057     *  @param fVolume  Global volume parameter as positive floating point
2058     *                  value usually be in the range between 0.0 and 1.0,
2059     *                  that is for attenuating the overall volume.
2060     *
2061     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2062     */
2063    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2064    {
2065            char szQuery[LSCP_BUFSIZ];
2066            struct _locale_t locale;
2067    
2068            if (fVolume < 0.0f)
2069                    return LSCP_FAILED;
2070    
2071            _save_and_set_c_locale(&locale);
2072            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);
2204    }
2205    
2206    
2207    /**
2208     *  Add an effect send to a sampler channel:
2209     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2210     *
2211     *  @param pClient          Pointer to client instance structure.
2212     *  @param iSamplerChannel  Sampler channel number.
2213     *  @param iMidiController  MIDI controller used to alter the effect,
2214     *                          usually a number between 0 and 127.
2215     *  @param pszFxName        Optional name for the effect send entity,
2216     *                          does not have to be unique.
2217     *
2218     *  @returns The new effect send number identifier, or -1 in case of failure.
2219     */
2220    int lscp_create_fxsend ( lscp_client_t *pClient,
2221            int iSamplerChannel, int iMidiController, const char *pszFxName )
2222    {
2223            int iFxSend = -1;
2224            char szQuery[LSCP_BUFSIZ];
2225    
2226            if (pClient == NULL)
2227                    return -1;
2228            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2229                    return -1;
2230    
2231            // Lock this section up.
2232            lscp_mutex_lock(pClient->mutex);
2233    
2234            sprintf(szQuery, "CREATE FX_SEND %d %d",
2235                    iSamplerChannel, iMidiController);
2236    
2237            if (pszFxName)
2238                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2239    
2240            strcat(szQuery, "\r\n");
2241    
2242            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2243                    iFxSend = atoi(lscp_client_get_result(pClient));
2244    
2245            // Unlock this section down.
2246            lscp_mutex_unlock(pClient->mutex);
2247    
2248            return iFxSend;
2249    }
2250    
2251    
2252    /**
2253     *  Remove an effect send from a sampler channel:
2254     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2255     *
2256     *  @param pClient          Pointer to client instance structure.
2257     *  @param iSamplerChannel  Sampler channel number.
2258     *  @param iFxSend          Effect send number.
2259     *
2260     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2261     */
2262    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2263            int iSamplerChannel, int iFxSend )
2264    {
2265            char szQuery[LSCP_BUFSIZ];
2266    
2267            if (iSamplerChannel < 0 || iFxSend < 0)
2268                    return LSCP_FAILED;
2269    
2270            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2271                    iSamplerChannel, iFxSend);
2272    
2273            return lscp_client_query(pClient, szQuery);
2274    }
2275    
2276    
2277    /**
2278     *  Get amount of effect sends on a sampler channel:
2279     *  GET FX_SENDS <sampler-channel>
2280     *
2281     *  @param pClient          Pointer to client instance structure.
2282     *  @param iSamplerChannel  Sampler channel number.
2283     *
2284     *  @returns The current total number of effect sends of the sampler channel
2285     *  on success, -1 otherwise.
2286     */
2287    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2288    {
2289            int iFxSends = -1;
2290            char szQuery[LSCP_BUFSIZ];
2291    
2292            if (pClient == NULL)
2293                    return -1;
2294            if (iSamplerChannel < 0)
2295                    return -1;
2296    
2297            // Lock this section up.
2298            lscp_mutex_lock(pClient->mutex);
2299    
2300            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2301    
2302            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2303                    iFxSends = atoi(lscp_client_get_result(pClient));
2304    
2305            // Unlock this section doen.
2306            lscp_mutex_unlock(pClient->mutex);
2307    
2308            return iFxSends;
2309    }
2310    
2311    
2312    /**
2313     *  List all effect sends on a sampler channel:
2314     *  LIST FX_SENDS <sampler-channel>
2315     *
2316     *  @param pClient          Pointer to client instance structure.
2317     *  @param iSamplerChannel  Sampler channel number.
2318     *
2319     *  @returns An array of the effect sends identifiers as positive integers,
2320     *  terminated with -1 on success, NULL otherwise.
2321     */
2322    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2323    {
2324            const char *pszSeps = ",";
2325            char szQuery[LSCP_BUFSIZ];
2326    
2327            if (pClient == NULL)
2328                    return NULL;
2329    
2330            // Lock this section up.
2331            lscp_mutex_lock(pClient->mutex);
2332    
2333            if (pClient->fxsends) {
2334                    lscp_isplit_destroy(pClient->fxsends);
2335                    pClient->fxsends = NULL;
2336            }
2337    
2338            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2339    
2340            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2341                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2342    
2343            // Unlock this section down.
2344            lscp_mutex_unlock(pClient->mutex);
2345    
2346            return pClient->fxsends;
2347    }
2348    
2349    
2350    /**
2351     *  Getting effect send information
2352     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2353     *
2354     *  @param pClient          Pointer to client instance structure.
2355     *  @param iSamplerChannel  Sampler channel number.
2356     *  @param iFxSend          Effect send number.
2357     *
2358     *  @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.
2360     */
2361    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2362            int iSamplerChannel, int iFxSend )
2363    {
2364            lscp_fxsend_info_t *pFxSendInfo;
2365            char szQuery[LSCP_BUFSIZ];
2366            const char *pszResult;
2367            const char *pszSeps = ":";
2368            const char *pszCrlf = "\r\n";
2369            char *pszToken;
2370            char *pch;
2371            struct _locale_t locale;
2372    
2373            if (pClient == NULL)
2374                    return NULL;
2375            if (iSamplerChannel < 0 || iFxSend < 0)
2376                    return NULL;
2377    
2378            // Lock this section up.
2379            lscp_mutex_lock(pClient->mutex);
2380    
2381            _save_and_set_c_locale(&locale);
2382    
2383            pFxSendInfo = &(pClient->fxsend_info);
2384            lscp_fxsend_info_reset(pFxSendInfo);
2385    
2386            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2387            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2388                    pszResult = lscp_client_get_result(pClient);
2389                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2390                    while (pszToken) {
2391                            if (strcasecmp(pszToken, "NAME") == 0) {
2392                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2393                                    if (pszToken)
2394                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2395                            }
2396                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2397                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2398                                    if (pszToken)
2399                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2400                            }
2401                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2402                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2403                                    if (pszToken) {
2404                                            if (pFxSendInfo->audio_routing)
2405                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2406                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2407                                    }
2408                            }
2409                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2410                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2411                                    if (pszToken)
2412                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2413                            }
2414                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2415                    }
2416            }
2417            else pFxSendInfo = NULL;
2418    
2419            _restore_locale(&locale);
2420    
2421            // Unlock this section up.
2422            lscp_mutex_unlock(pClient->mutex);
2423    
2424            return pFxSendInfo;
2425    }
2426    
2427    
2428    /**
2429     *  Alter effect send's name:
2430     *  @code
2431     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2432     *  @endcode
2433     *
2434     *  @param pClient          Pointer to client instance structure.
2435     *  @param iSamplerChannel  Sampler channel number.
2436     *  @param iFxSend          Effect send number.
2437     *  @param pszFxName        Effect send's new name.
2438     *
2439     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2440     */
2441    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];
2445    
2446            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2447                    return LSCP_FAILED;
2448    
2449            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2450                    iSamplerChannel, iFxSend, pszFxName);
2451            return lscp_client_query(pClient, szQuery);
2452    }
2453    
2454    
2455    /**
2456     *  Alter effect send's audio routing:
2457     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2458     *    <audio-src> <audio-dst>
2459     *
2460     *  @param pClient          Pointer to client instance structure.
2461     *  @param iSamplerChannel  Sampler channel number.
2462     *  @param iFxSend          Effect send number.
2463     *  @param iAudioSrc        Audio output device channel to be routed from.
2464     *  @param iAudioDst        Audio output device channel to be routed into.
2465     *
2466     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2467     */
2468    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];
2472    
2473            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2474                    return LSCP_FAILED;
2475    
2476            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);
2479    }
2480    
2481    
2482    /**
2483     *  Alter effect send's MIDI controller:
2484     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2485     *
2486     *  @param pClient          Pointer to client instance structure.
2487     *  @param iSamplerChannel  Sampler channel number.
2488     *  @param iFxSend          Effect send number.
2489     *  @param iMidiController  MIDI controller used to alter the effect,
2490     *                          usually a number between 0 and 127.
2491     *
2492     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2493     */
2494    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];
2498    
2499            if (iSamplerChannel < 0 || iFxSend < 0 ||
2500                    iMidiController < 0 || iMidiController > 127)
2501                    return LSCP_FAILED;
2502    
2503            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2504                    iSamplerChannel, iFxSend, iMidiController);
2505            return lscp_client_query(pClient, szQuery);
2506    }
2507    
2508    
2509    /**
2510     *  Alter effect send's audio level:
2511     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2512     *
2513     *  @param pClient          Pointer to client instance structure.
2514     *  @param iSamplerChannel  Sampler channel number.
2515     *  @param iFxSend          Effect send number.
2516     *  @param fLevel           Effect send volume level.
2517     *
2518     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2519     */
2520    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2521            int iSamplerChannel, int iFxSend, float fLevel )
2522    {
2523            char szQuery[LSCP_BUFSIZ];
2524            struct _locale_t locale;
2525    
2526            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2527                    return LSCP_FAILED;
2528    
2529            _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);
2535    }
2536    
2537    
2538    /**
2539   *  Create a new MIDI instrument map:   *  Create a new MIDI instrument map:
2540   *  ADD MIDI_INSTRUMENT_MAP [<name>]   *  ADD MIDI_INSTRUMENT_MAP [<name>]
2541   *   *
# Line 1754  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 1880  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 1944  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 1956  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 1972  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 2009  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 2102  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 2122  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 2131  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 2143  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 2197  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 2235  lscp_status_t lscp_clear_midi_instrument Line 3052  lscp_status_t lscp_clear_midi_instrument
3052    
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
3059     * on the given sampler channel:
3060     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3061     *
3062     * @param pClient         Pointer to client instance structure.
3063     * @param iSamplerChannel Sampler Channel.
3064     *
3065     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3066     */
3067    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3068    {
3069            char szQuery[LSCP_BUFSIZ];
3070    
3071            if (iSamplerChannel < 0)
3072                    return LSCP_FAILED;
3073    
3074            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3075    
3076            return lscp_client_query(pClient, szQuery);
3077    }
3078    
3079    
3080  // end of client.c  // end of client.c

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

  ViewVC Help
Powered by ViewVC