/[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 977 by capela, Sun Dec 17 15:08:35 2006 UTC revision 2424 by capela, Sun Feb 24 19:02:30 2013 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-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    #if !defined(WIN32)
33    #define USE_GETADDRINFO 1
34    #endif
35    
36    
37  // Local prototypes.  // Local prototypes.
38    
39  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
40    
41    static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
42    static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
43            int iSubscribe, lscp_event_t event);
44    
45    
46    //-------------------------------------------------------------------------
47    // General helper functions.
48    
49    struct _locale_t {
50            char numeric[32];
51            char ctype[32];
52    };
53    
54    // we need to ensure a constant locale setting e.g. for parsing
55    // floating point numbers with atof(), as the floating point separator
56    // character varies by the invidual locale settings
57    static void _save_and_set_c_locale(struct _locale_t* locale)
58    {
59            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
60            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
61            setlocale(LC_NUMERIC, "C");
62            setlocale(LC_CTYPE, "C");
63    }
64    
65    // restore the original locale setting as nothing happened
66    static void _restore_locale(struct _locale_t* locale)
67    {
68            setlocale(LC_NUMERIC, locale->numeric);
69            setlocale(LC_CTYPE, locale->ctype);
70    }
71    
72  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  // seems the standard atof() function doesnt care much about locale
73  static lscp_status_t    _lscp_client_evt_request    (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);  // runtime modifications, so we use this workaround
74    static float _atof(const char* txt) {
75            float f;
76            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
77            return f;
78    }
79    
80    
81  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 94  static void _lscp_client_evt_proc ( void
94          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
95          int    cchBuffer;          int    cchBuffer;
96          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
97          char * pszToken;          char  *pszToken;
98          char * pch;          char  *pch;
99          int     cchToken;          int    cchToken;
100    
101          lscp_event_t event;          lscp_event_t event;
102    
103  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 129  static void _lscp_client_evt_proc ( void
129                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
130                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
131                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
132                                  // Parse for the notification event message...                                  pch = achBuffer;
133                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
134                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
135                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
136                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
137                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
138                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
139                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
140                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
141                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
142                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
143                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
144                                                                  pClient,                                                          // Invoke the client event callback...
145                                                                  event,                                                          if ((*pClient->pfnCallback)(
146                                                                  pszToken,                                                                          pClient,
147                                                                  cchToken,                                                                          event,
148                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
149                                                          pClient->evt.iState = 0;                                                                          cchToken,
150                                                                            pClient->pvData) != LSCP_OK) {
151                                                                    pClient->evt.iState = 0;
152                                                            }
153                                                  }                                                  }
154                                          }                                          }
155                                  }                                  } while (*pch);
156                          } else {                          } else {
157                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
158                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
# Line 146  static lscp_status_t _lscp_client_evt_co Line 194  static lscp_status_t _lscp_client_evt_co
194          }          }
195    
196  #if defined(WIN32)  #if defined(WIN32)
197          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
198                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
199                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
200  #endif  #endif
201    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 223  static lscp_status_t _lscp_client_evt_co
223    
224    
225  // Subscribe to a single event.  // Subscribe to a single event.
226  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
227            int iSubscribe, lscp_event_t event )
228  {  {
229          const char *pszEvent;          const char *pszEvent;
230          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 239  static lscp_status_t _lscp_client_evt_re
239                  return LSCP_FAILED;                  return LSCP_FAILED;
240    
241          // Build the query string...          // Build the query string...
242          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
243                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
244          // Just send data, forget result...          // Just send data, forget result...
245          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
246                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 240  const char* lscp_client_build   (void) { Line 291  const char* lscp_client_build   (void) {
291   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
292   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
293   */   */
294  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort,
295            lscp_client_proc_t pfnCallback, void *pvData )
296  {  {
297          lscp_client_t  *pClient;          lscp_client_t  *pClient;
298    #if defined(USE_GETADDRINFO)
299            char szPort[33];
300            struct addrinfo hints;
301            struct addrinfo *result, *res;
302    #else
303          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
304          struct sockaddr_in addr;          struct sockaddr_in addr;
305          int cAddr;          int cAddr;
306    #endif  /* !USE_GETADDRINFO */
307            lscp_socket_t sock;
308  #if defined(WIN32)  #if defined(WIN32)
309          int iSockOpt = (-1);          int iSockOpt = (-1);
310  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 314  lscp_client_t* lscp_client_create ( cons
314                  return NULL;                  return NULL;
315          }          }
316    
317    #if defined(USE_GETADDRINFO)
318    
319            // Convert port number to string/name...
320            snprintf(szPort, sizeof(szPort), "%d", iPort);
321    
322            // Obtain address(es) matching host/port...
323            memset(&hints, 0, sizeof(struct addrinfo));
324            hints.ai_family = AF_INET;
325            hints.ai_socktype = SOCK_STREAM;
326    
327            result = NULL;
328    
329            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
330                    lscp_socket_herror("lscp_client_create: getaddrinfo");
331                    return NULL;
332            }
333    
334    #else
335    
336            // Obtain host matching name...
337          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
338          if (pHost == NULL) {          if (pHost == NULL) {
339                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
340                  return NULL;                  return NULL;
341          }          }
342    
343    #endif  /* !USE_GETADDRINFO */
344    
345          // Allocate client descriptor...          // Allocate client descriptor...
346    
347          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
# Line 275  lscp_client_t* lscp_client_create ( cons Line 355  lscp_client_t* lscp_client_create ( cons
355          pClient->pvData = pvData;          pClient->pvData = pvData;
356    
357  #ifdef DEBUG  #ifdef DEBUG
358          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
359                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
360                     pClient, pszHost, iPort);
361  #endif  #endif
362    
363          // Prepare the command connection socket...          // Prepare the command connection socket...
364    
365    #if defined(USE_GETADDRINFO)
366    
367            // getaddrinfo() returns a list of address structures;
368            // try each address until we successfully connect(2);
369            // if socket or connect fails, we close the socket and
370            // try the next address...
371            sock = INVALID_SOCKET;
372    
373            for (res = result; res; res = res->ai_next) {
374                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
375                    if (sock == INVALID_SOCKET)
376                            continue;
377            #if defined(WIN32)
378                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
379                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
380                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
381            #endif
382            #ifdef DEBUG
383                    lscp_socket_getopts("lscp_client_create: cmd", sock);
384            #endif
385                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
386                            break;
387                    closesocket(sock);
388            }
389    
390            if (sock == INVALID_SOCKET) {
391                    lscp_socket_perror("lscp_client_create: cmd: socket");
392                    free(pClient);
393                    return NULL;
394            }
395    
396            if (res == NULL) {
397                    lscp_socket_perror("lscp_client_create: cmd: connect");
398                    free(pClient);
399                    return NULL;
400            }
401    
402            // Initialize the command socket agent struct...
403            lscp_socket_agent_init(&(pClient->cmd), sock,
404                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
405    
406            // No longer needed...
407            freeaddrinfo(result);
408    
409    #else
410    
411          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
412          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
413                  lscp_socket_perror("lscp_client_create: cmd: socket");                  lscp_socket_perror("lscp_client_create: cmd: socket");
# Line 288  lscp_client_t* lscp_client_create ( cons Line 416  lscp_client_t* lscp_client_create ( cons
416          }          }
417    
418  #if defined(WIN32)  #if defined(WIN32)
419          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
420                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
421                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
422  #endif  #endif
423    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 441  lscp_client_t* lscp_client_create ( cons
441          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
442          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
443    
444    #endif  /* !USE_GETADDRINFO */
445    
446  #ifdef DEBUG  #ifdef DEBUG
447          fprintf(stderr, "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->cmd.sock, inet_ntoa(pClient->cmd.addr.sin_addr), ntohs(pClient->cmd.addr.sin_port));          fprintf(stderr,
448                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
449                    pClient, pClient->cmd.sock,
450                    inet_ntoa(pClient->cmd.addr.sin_addr),
451                    ntohs(pClient->cmd.addr.sin_port));
452  #endif  #endif
453    
454          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 327  lscp_client_t* lscp_client_create ( cons Line 462  lscp_client_t* lscp_client_create ( cons
462          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
463          pClient->engines = NULL;          pClient->engines = NULL;
464          pClient->channels = NULL;          pClient->channels = NULL;
465            pClient->fxsends = NULL;
466          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
467          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
468          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 343  lscp_client_t* lscp_client_create ( cons Line 479  lscp_client_t* lscp_client_create ( cons
479          lscp_server_info_init(&(pClient->server_info));          lscp_server_info_init(&(pClient->server_info));
480          lscp_engine_info_init(&(pClient->engine_info));          lscp_engine_info_init(&(pClient->engine_info));
481          lscp_channel_info_init(&(pClient->channel_info));          lscp_channel_info_init(&(pClient->channel_info));
482            lscp_fxsend_info_init(&(pClient->fxsend_info));
483          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
484          // Initialize error stuff.          // Initialize error stuff.
485          pClient->pszResult = NULL;          pClient->pszResult = NULL;
# Line 405  lscp_status_t lscp_client_destroy ( lscp Line 542  lscp_status_t lscp_client_destroy ( lscp
542    
543          // Free up all cached members.          // Free up all cached members.
544          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
545            lscp_fxsend_info_free(&(pClient->fxsend_info));
546          lscp_channel_info_free(&(pClient->channel_info));          lscp_channel_info_free(&(pClient->channel_info));
547          lscp_engine_info_free(&(pClient->engine_info));          lscp_engine_info_free(&(pClient->engine_info));
548          lscp_server_info_free(&(pClient->server_info));          lscp_server_info_free(&(pClient->server_info));
# Line 425  lscp_status_t lscp_client_destroy ( lscp Line 563  lscp_status_t lscp_client_destroy ( lscp
563          lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->midi_devices);
564          lscp_szsplit_destroy(pClient->engines);          lscp_szsplit_destroy(pClient->engines);
565          lscp_isplit_destroy(pClient->channels);          lscp_isplit_destroy(pClient->channels);
566            lscp_isplit_destroy(pClient->fxsends);
567          lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_midi_instruments_destroy(pClient->midi_instruments);
568          lscp_isplit_destroy(pClient->midi_maps);          lscp_isplit_destroy(pClient->midi_maps);
569          if (pClient->midi_map_name)          if (pClient->midi_map_name)
# Line 436  lscp_status_t lscp_client_destroy ( lscp Line 575  lscp_status_t lscp_client_destroy ( lscp
575          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
576          pClient->engines = NULL;          pClient->engines = NULL;
577          pClient->channels = NULL;          pClient->channels = NULL;
578            pClient->fxsends = NULL;
579          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
580          pClient->midi_maps = NULL;          pClient->midi_maps = NULL;
581          pClient->midi_map_name = NULL;          pClient->midi_map_name = NULL;
# Line 573  int lscp_client_get_errno ( lscp_client_ Line 713  int lscp_client_get_errno ( lscp_client_
713  // Client registration protocol functions.  // Client registration protocol functions.
714    
715  /**  /**
716   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
717   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
718   *      | CHANNEL_INFO | MISCELLANEOUS   *  for @e each event you want to subscribe. That is the old bitflag approach
719     *  was abondoned at this point. You can however still register all older
720     *  events with one lscp_client_subscribe() call at once. Thus, the old
721     *  behavior of this functions was not broken. Those older events are namely:
722     *  @code
723     *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
724     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
725     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
726     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
727     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
728     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
729     *      | MISCELLANEOUS
730     *  @endcode
731     *  The old events occupy the lower 16 bits (as bit flags), and all younger
732     *  events enumerate the whole upper 16 bits range. The new, enumerated
733     *  events are namely:
734     *  @code
735     *  SUBSCRIBE CHANNEL_MIDI
736     *  @endcode
737   *   *
738   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
739   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
740   *   *
741   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
742   */   */
743  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
744  {  {
745          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
746            lscp_event_t currentEvent;
747    
748          if (pClient == NULL)          if (pClient == NULL)
749                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 607  lscp_status_t lscp_client_subscribe ( ls Line 766  lscp_status_t lscp_client_subscribe ( ls
766                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
767          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
768                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
769            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
770                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
771            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
772                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
773            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
774                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
775            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
776                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
777            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
778                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
779            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
780                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
781            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
782                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
783            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
784                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
785            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
786                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
787          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
788                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
789            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
790            currentEvent = events & 0xffff0000;
791            if (ret == LSCP_OK && currentEvent) {
792                    switch (currentEvent) {
793                            case LSCP_EVENT_CHANNEL_MIDI:
794                            case LSCP_EVENT_DEVICE_MIDI:
795                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
796                                    break;
797                            default: // unknown "upper" event type
798                                    ret = LSCP_FAILED;
799                                    break;
800                    }
801            }
802    
803          // Unlock this section down.          // Unlock this section down.
804          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 618  lscp_status_t lscp_client_subscribe ( ls Line 808  lscp_status_t lscp_client_subscribe ( ls
808    
809    
810  /**  /**
811   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
812   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call
813   *      | CHANNEL_INFO | MISCELLANEOUS   *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
814     *  That is the old bitflag approach was abondoned at this point. You can
815     *  however still register all older events with one lscp_client_subscribe()
816     *  call at once. Thus, the old behavior of this functions was not broken.
817     *  Those older events are namely:
818     *  @code
819     *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
820     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
821     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
822     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
823     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
824     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
825     *      | MISCELLANEOUS
826     *  @endcode
827     *  The old events occupy the lower 16 bits (as bit flags), and all younger
828     *  events enumerate the whole upper 16 bits range. The new, enumerated
829     *  events are namely:
830     *  @code
831     *  UNSUBSCRIBE CHANNEL_MIDI
832     *  @endcode
833   *   *
834   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
835   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
836   *   *
837   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
838   */   */
839  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
840  {  {
841          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
842            lscp_event_t currentEvent;
843    
844          if (pClient == NULL)          if (pClient == NULL)
845                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 648  lscp_status_t lscp_client_unsubscribe ( Line 858  lscp_status_t lscp_client_unsubscribe (
858                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
859          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
860                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
861            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
862                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
863            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
864                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
865            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
866                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
867            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
868                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
869            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
870                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
871            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
872                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
873            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
874                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
875            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
876                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
877            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
878                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
879          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
880                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
881            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
882            currentEvent = events & 0xffff0000;
883            if (ret == LSCP_OK && currentEvent) {
884                    switch (currentEvent) {
885                            case LSCP_EVENT_CHANNEL_MIDI:
886                            case LSCP_EVENT_DEVICE_MIDI:
887                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
888                                    break;
889                            default: // unknown "upper" event type
890                                    ret = LSCP_FAILED;
891                                    break;
892                    }
893            }
894    
895          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
896          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 692  lscp_event_t lscp_client_get_events ( ls Line 933  lscp_event_t lscp_client_get_events ( ls
933   *   *
934   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
935   */   */
936  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient,
937            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
938  {  {
939          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
940    
941          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
942                  return LSCP_FAILED;                  return LSCP_FAILED;
943    
944          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
945                    pszFileName, iInstrIndex, iSamplerChannel);
946          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
947  }  }
948    
# Line 715  lscp_status_t lscp_load_instrument ( lsc Line 958  lscp_status_t lscp_load_instrument ( lsc
958   *   *
959   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
960   */   */
961  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient,
962            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
963  {  {
964          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
965    
966          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
967                  return LSCP_FAILED;                  return LSCP_FAILED;
968    
969          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n",
970                    pszFileName, iInstrIndex, iSamplerChannel);
971          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
972  }  }
973    
# Line 744  lscp_status_t lscp_load_engine ( lscp_cl Line 989  lscp_status_t lscp_load_engine ( lscp_cl
989          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
990                  return LSCP_FAILED;                  return LSCP_FAILED;
991    
992          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
993                    pszEngineName, iSamplerChannel);
994          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
995  }  }
996    
# Line 935  const char **lscp_list_available_engines Line 1181  const char **lscp_list_available_engines
1181   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the
1182   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1183   */   */
1184  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient,
1185            const char *pszEngineName )
1186  {  {
1187          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1188          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1002  lscp_channel_info_t *lscp_get_channel_in Line 1249  lscp_channel_info_t *lscp_get_channel_in
1249          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1250          char *pszToken;          char *pszToken;
1251          char *pch;          char *pch;
1252            struct _locale_t locale;
1253    
1254          if (pClient == NULL)          if (pClient == NULL)
1255                  return NULL;                  return NULL;
# Line 1014  lscp_channel_info_t *lscp_get_channel_in Line 1262  lscp_channel_info_t *lscp_get_channel_in
1262          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1263          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1264    
1265            _save_and_set_c_locale(&locale);
1266    
1267          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1268          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1269                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1038  lscp_channel_info_t *lscp_get_channel_in Line 1288  lscp_channel_info_t *lscp_get_channel_in
1288                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1289                                  if (pszToken) {                                  if (pszToken) {
1290                                          if (pChannelInfo->audio_routing)                                          if (pChannelInfo->audio_routing)
1291                                                  lscp_szsplit_destroy(pChannelInfo->audio_routing);                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1292                                          pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1293                                  }                                  }
1294                          }                          }
1295                          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 1348  lscp_channel_info_t *lscp_get_channel_in
1348                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1349                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1350                                  if (pszToken)                                  if (pszToken)
1351                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1352                          }                          }
1353                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1354                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1115  lscp_channel_info_t *lscp_get_channel_in Line 1365  lscp_channel_info_t *lscp_get_channel_in
1365          }          }
1366          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1367    
1368            _restore_locale(&locale);
1369    
1370          // Unlock this section up.          // Unlock this section up.
1371          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1372    
# Line 1258  int lscp_get_channel_stream_usage ( lscp Line 1510  int lscp_get_channel_stream_usage ( lscp
1510   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1511   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1512   */   */
1513  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient,
1514            lscp_usage_t usage_type, int iSamplerChannel )
1515  {  {
1516          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1517          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1331  lscp_buffer_fill_t *lscp_get_channel_buf Line 1584  lscp_buffer_fill_t *lscp_get_channel_buf
1584   *   *
1585   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1586   */   */
1587  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1588            int iSamplerChannel, const char *pszAudioDriver )
1589  {  {
1590          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1591    
1592          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1593                  return LSCP_FAILED;                  return LSCP_FAILED;
1594    
1595          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1596                    iSamplerChannel, pszAudioDriver);
1597          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1598  }  }
1599    
# Line 1353  lscp_status_t lscp_set_channel_audio_typ Line 1608  lscp_status_t lscp_set_channel_audio_typ
1608   *   *
1609   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1610   */   */
1611  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1612            int iSamplerChannel, int iAudioDevice )
1613  {  {
1614          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1615    
1616          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1617                  return LSCP_FAILED;                  return LSCP_FAILED;
1618    
1619          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1620                    iSamplerChannel, iAudioDevice);
1621          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1622  }  }
1623    
# Line 1376  lscp_status_t lscp_set_channel_audio_dev Line 1633  lscp_status_t lscp_set_channel_audio_dev
1633   *   *
1634   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1635   */   */
1636  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1637            int iSamplerChannel, int iAudioOut, int iAudioIn )
1638  {  {
1639          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1640    
1641          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1642                  return LSCP_FAILED;                  return LSCP_FAILED;
1643    
1644          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n",
1645                    iSamplerChannel, iAudioOut, iAudioIn);
1646          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1647  }  }
1648    
# Line 1398  lscp_status_t lscp_set_channel_audio_cha Line 1657  lscp_status_t lscp_set_channel_audio_cha
1657   *   *
1658   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1659   */   */
1660  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1661            int iSamplerChannel, const char *pszMidiDriver )
1662  {  {
1663          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1664    
1665          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1666                  return LSCP_FAILED;                  return LSCP_FAILED;
1667    
1668          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1669                    iSamplerChannel, pszMidiDriver);
1670          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1671  }  }
1672    
# Line 1420  lscp_status_t lscp_set_channel_midi_type Line 1681  lscp_status_t lscp_set_channel_midi_type
1681   *   *
1682   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1683   */   */
1684  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1685            int iSamplerChannel, int iMidiDevice )
1686  {  {
1687          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1688    
1689          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1690                  return LSCP_FAILED;                  return LSCP_FAILED;
1691    
1692          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1693                    iSamplerChannel, iMidiDevice);
1694          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1695  }  }
1696    
# Line 1442  lscp_status_t lscp_set_channel_midi_devi Line 1705  lscp_status_t lscp_set_channel_midi_devi
1705   *   *
1706   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1707   */   */
1708  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1709            int iSamplerChannel, int iMidiPort )
1710  {  {
1711          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1712    
1713          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1714                  return LSCP_FAILED;                  return LSCP_FAILED;
1715    
1716          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1717                    iSamplerChannel, iMidiPort);
1718          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1719  }  }
1720    
# Line 1465  lscp_status_t lscp_set_channel_midi_port Line 1730  lscp_status_t lscp_set_channel_midi_port
1730   *   *
1731   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1732   */   */
1733  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient,
1734            int iSamplerChannel, int iMidiChannel )
1735  {  {
1736          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1737    
# Line 1473  lscp_status_t lscp_set_channel_midi_chan Line 1739  lscp_status_t lscp_set_channel_midi_chan
1739                  return LSCP_FAILED;                  return LSCP_FAILED;
1740    
1741          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1742                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1743                            iSamplerChannel);
1744          else          else
1745                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1746                            iSamplerChannel, iMidiChannel);
1747          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1748  }  }
1749    
# Line 1492  lscp_status_t lscp_set_channel_midi_chan Line 1760  lscp_status_t lscp_set_channel_midi_chan
1760   *   *
1761   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1762   */   */
1763  lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient, int iSamplerChannel, int iMidiMap )  lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1764            int iSamplerChannel, int iMidiMap )
1765  {  {
1766          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1767    
# Line 1526  lscp_status_t lscp_set_channel_midi_map Line 1795  lscp_status_t lscp_set_channel_midi_map
1795   *   *
1796   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1797   */   */
1798  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient,
1799            int iSamplerChannel, float fVolume )
1800  {  {
1801          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1802            struct _locale_t locale;
1803    
1804          if (iSamplerChannel < 0 || fVolume < 0.0)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1805                  return LSCP_FAILED;                  return LSCP_FAILED;
1806    
1807          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1808            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1809                    iSamplerChannel, fVolume);
1810            _restore_locale(&locale);
1811    
1812          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1813  }  }
1814    
# Line 1550  lscp_status_t lscp_set_channel_volume ( Line 1825  lscp_status_t lscp_set_channel_volume (
1825   *   *
1826   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1827   */   */
1828  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1829            int iSamplerChannel, int iMute )
1830  {  {
1831          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1832    
1833          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1834                  return LSCP_FAILED;                  return LSCP_FAILED;
1835    
1836          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1837                    iSamplerChannel, iMute);
1838          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1839  }  }
1840    
# Line 1574  lscp_status_t lscp_set_channel_mute ( ls Line 1851  lscp_status_t lscp_set_channel_mute ( ls
1851   *   *
1852   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1853   */   */
1854  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient,
1855            int iSamplerChannel, int iSolo )
1856  {  {
1857          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1858    
1859          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1860                  return LSCP_FAILED;                  return LSCP_FAILED;
1861    
1862          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1863                    iSamplerChannel, iSolo);
1864          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1865  }  }
1866    
# Line 1617  lscp_status_t lscp_reset_channel ( lscp_ Line 1896  lscp_status_t lscp_reset_channel ( lscp_
1896   */   */
1897  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1898  {  {
1899            // Do actual whole sampler reset...
1900          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1901  }  }
1902    
# Line 1738  int lscp_get_total_voice_count_max ( lsc Line 2018  int lscp_get_total_voice_count_max ( lsc
2018    
2019    
2020  /**  /**
2021     *  Get global volume attenuation:
2022     *  GET VOLUME
2023     *
2024     *  @param pClient  Pointer to client instance structure.
2025     *
2026     *  @returns The global volume as positive floating point value usually in
2027     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2028     */
2029    float lscp_get_volume ( lscp_client_t *pClient )
2030    {
2031            float fVolume = 0.0f;
2032            struct _locale_t locale;
2033    
2034            if (pClient == NULL)
2035                    return 0.0f;
2036    
2037            // Lock this section up.
2038            lscp_mutex_lock(pClient->mutex);
2039    
2040            _save_and_set_c_locale(&locale);
2041    
2042            if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2043                    fVolume = _atof(lscp_client_get_result(pClient));
2044    
2045            _restore_locale(&locale);
2046    
2047            // Unlock this section down.
2048            lscp_mutex_unlock(pClient->mutex);
2049    
2050            return fVolume;
2051    }
2052    
2053    
2054    /**
2055     *  Setting global volume attenuation:
2056     *  SET VOLUME <volume>
2057     *
2058     *  @param pClient  Pointer to client instance structure.
2059     *  @param fVolume  Global volume parameter as positive floating point
2060     *                  value usually be in the range between 0.0 and 1.0,
2061     *                  that is for attenuating the overall volume.
2062     *
2063     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2064     */
2065    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2066    {
2067            char szQuery[LSCP_BUFSIZ];
2068            struct _locale_t locale;
2069    
2070            if (fVolume < 0.0f)
2071                    return LSCP_FAILED;
2072    
2073            _save_and_set_c_locale(&locale);
2074            sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2075            _restore_locale(&locale);
2076    
2077            return lscp_client_query(pClient, szQuery);
2078    }
2079    
2080    
2081    /**
2082     *  Get global voice limit setting:
2083     *  @code
2084     *  GET VOICES
2085     *  @endcode
2086     *  This value reflects the maximum amount of voices a sampler engine
2087     *  processes simultaniously before voice stealing kicks in.
2088     *
2089     *  @param pClient  Pointer to client instance structure.
2090     *
2091     *  @returns The current global maximum amount of voices limit or a
2092     *           negative value on error (e.g. if sampler doesn't support
2093     *           this command).
2094     */
2095    int lscp_get_voices ( lscp_client_t *pClient )
2096    {
2097            int iVoices = -1;
2098    
2099            if (pClient == NULL)
2100                    return -1;
2101    
2102            // Lock this section up.
2103            lscp_mutex_lock(pClient->mutex);
2104    
2105            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2106                    iVoices = atoi(lscp_client_get_result(pClient));
2107    
2108            // Unlock this section down.
2109            lscp_mutex_unlock(pClient->mutex);
2110    
2111            return iVoices;
2112    }
2113    
2114    
2115    /**
2116     *  Setting global voice limit setting:
2117     *  @code
2118     *  SET VOICES <max-voices>
2119     *  @endcode
2120     *  This value reflects the maximum amount of voices a sampler engine
2121     *  processes simultaniously before voice stealing kicks in. Note that
2122     *  this value will be passed to all sampler engine instances, that is
2123     *  the total amount of maximum voices on the running system is thus
2124     *  @param iMaxVoices multiplied with the current amount of sampler
2125     *  engine instances.
2126     *
2127     *  @param pClient     Pointer to client instance structure.
2128     *  @param iMaxVoices  Global voice limit setting as integer value larger
2129     *                     or equal to 1.
2130     *
2131     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2132     */
2133    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2134    {
2135            char szQuery[LSCP_BUFSIZ];
2136    
2137            if (iMaxVoices < 1)
2138                    return LSCP_FAILED;
2139    
2140            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2141            return lscp_client_query(pClient, szQuery);
2142    }
2143    
2144    
2145    /**
2146     *  Get global disk streams limit setting:
2147     *  @code
2148     *  GET STREAMS
2149     *  @endcode
2150     *  This value reflects the maximum amount of disk streams a sampler
2151     *  engine processes simultaniously.
2152     *
2153     *  @param pClient  Pointer to client instance structure.
2154     *
2155     *  @returns The current global maximum amount of disk streams limit
2156     *           or a negative value on error (e.g. if sampler doesn't
2157     *           support this command).
2158     */
2159    int lscp_get_streams ( lscp_client_t *pClient )
2160    {
2161            int iStreams = -1;
2162    
2163            if (pClient == NULL)
2164                    return -1;
2165    
2166            // Lock this section up.
2167            lscp_mutex_lock(pClient->mutex);
2168    
2169            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2170                    iStreams = atoi(lscp_client_get_result(pClient));
2171    
2172            // Unlock this section down.
2173            lscp_mutex_unlock(pClient->mutex);
2174    
2175            return iStreams;
2176    }
2177    
2178    
2179    /**
2180     *  Setting global disk streams limit setting:
2181     *  @code
2182     *  SET STREAMS <max-streams>
2183     *  @endcode
2184     *  This value reflects the maximum amount of dist streams a sampler
2185     *  engine instance processes simultaniously. Note that this value will
2186     *  be passed to all sampler engine instances, that is the total amount
2187     *  of maximum disk streams on the running system is thus
2188     *  @param iMaxStreams multiplied with the current amount of sampler
2189     *  engine instances.
2190     *
2191     *  @param pClient      Pointer to client instance structure.
2192     *  @param iMaxStreams  Global streams limit setting as positive integer
2193     *                      value (larger or equal to 0).
2194     *
2195     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2196     */
2197    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2198    {
2199            char szQuery[LSCP_BUFSIZ];
2200    
2201            if (iMaxStreams < 0)
2202                    return LSCP_FAILED;
2203    
2204            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2205            return lscp_client_query(pClient, szQuery);
2206    }
2207    
2208    
2209    /**
2210     *  Add an effect send to a sampler channel:
2211     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2212     *
2213     *  @param pClient          Pointer to client instance structure.
2214     *  @param iSamplerChannel  Sampler channel number.
2215     *  @param iMidiController  MIDI controller used to alter the effect,
2216     *                          usually a number between 0 and 127.
2217     *  @param pszFxName        Optional name for the effect send entity,
2218     *                          does not have to be unique.
2219     *
2220     *  @returns The new effect send number identifier, or -1 in case of failure.
2221     */
2222    int lscp_create_fxsend ( lscp_client_t *pClient,
2223            int iSamplerChannel, int iMidiController, const char *pszFxName )
2224    {
2225            int iFxSend = -1;
2226            char szQuery[LSCP_BUFSIZ];
2227    
2228            if (pClient == NULL)
2229                    return -1;
2230            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2231                    return -1;
2232    
2233            // Lock this section up.
2234            lscp_mutex_lock(pClient->mutex);
2235    
2236            sprintf(szQuery, "CREATE FX_SEND %d %d",
2237                    iSamplerChannel, iMidiController);
2238    
2239            if (pszFxName)
2240                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2241    
2242            strcat(szQuery, "\r\n");
2243    
2244            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2245                    iFxSend = atoi(lscp_client_get_result(pClient));
2246    
2247            // Unlock this section down.
2248            lscp_mutex_unlock(pClient->mutex);
2249    
2250            return iFxSend;
2251    }
2252    
2253    
2254    /**
2255     *  Remove an effect send from a sampler channel:
2256     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2257     *
2258     *  @param pClient          Pointer to client instance structure.
2259     *  @param iSamplerChannel  Sampler channel number.
2260     *  @param iFxSend          Effect send number.
2261     *
2262     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2263     */
2264    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2265            int iSamplerChannel, int iFxSend )
2266    {
2267            char szQuery[LSCP_BUFSIZ];
2268    
2269            if (iSamplerChannel < 0 || iFxSend < 0)
2270                    return LSCP_FAILED;
2271    
2272            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2273                    iSamplerChannel, iFxSend);
2274    
2275            return lscp_client_query(pClient, szQuery);
2276    }
2277    
2278    
2279    /**
2280     *  Get amount of effect sends on a sampler channel:
2281     *  GET FX_SENDS <sampler-channel>
2282     *
2283     *  @param pClient          Pointer to client instance structure.
2284     *  @param iSamplerChannel  Sampler channel number.
2285     *
2286     *  @returns The current total number of effect sends of the sampler channel
2287     *  on success, -1 otherwise.
2288     */
2289    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2290    {
2291            int iFxSends = -1;
2292            char szQuery[LSCP_BUFSIZ];
2293    
2294            if (pClient == NULL)
2295                    return -1;
2296            if (iSamplerChannel < 0)
2297                    return -1;
2298    
2299            // Lock this section up.
2300            lscp_mutex_lock(pClient->mutex);
2301    
2302            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2303    
2304            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2305                    iFxSends = atoi(lscp_client_get_result(pClient));
2306    
2307            // Unlock this section doen.
2308            lscp_mutex_unlock(pClient->mutex);
2309    
2310            return iFxSends;
2311    }
2312    
2313    
2314    /**
2315     *  List all effect sends on a sampler channel:
2316     *  LIST FX_SENDS <sampler-channel>
2317     *
2318     *  @param pClient          Pointer to client instance structure.
2319     *  @param iSamplerChannel  Sampler channel number.
2320     *
2321     *  @returns An array of the effect sends identifiers as positive integers,
2322     *  terminated with -1 on success, NULL otherwise.
2323     */
2324    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2325    {
2326            const char *pszSeps = ",";
2327            char szQuery[LSCP_BUFSIZ];
2328    
2329            if (pClient == NULL)
2330                    return NULL;
2331    
2332            // Lock this section up.
2333            lscp_mutex_lock(pClient->mutex);
2334    
2335            if (pClient->fxsends) {
2336                    lscp_isplit_destroy(pClient->fxsends);
2337                    pClient->fxsends = NULL;
2338            }
2339    
2340            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2341    
2342            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2343                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2344    
2345            // Unlock this section down.
2346            lscp_mutex_unlock(pClient->mutex);
2347    
2348            return pClient->fxsends;
2349    }
2350    
2351    
2352    /**
2353     *  Getting effect send information
2354     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2355     *
2356     *  @param pClient          Pointer to client instance structure.
2357     *  @param iSamplerChannel  Sampler channel number.
2358     *  @param iFxSend          Effect send number.
2359     *
2360     *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2361     *  information of the given FX send, or NULL in case of failure.
2362     */
2363    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2364            int iSamplerChannel, int iFxSend )
2365    {
2366            lscp_fxsend_info_t *pFxSendInfo;
2367            char szQuery[LSCP_BUFSIZ];
2368            const char *pszResult;
2369            const char *pszSeps = ":";
2370            const char *pszCrlf = "\r\n";
2371            char *pszToken;
2372            char *pch;
2373            struct _locale_t locale;
2374    
2375            if (pClient == NULL)
2376                    return NULL;
2377            if (iSamplerChannel < 0 || iFxSend < 0)
2378                    return NULL;
2379    
2380            // Lock this section up.
2381            lscp_mutex_lock(pClient->mutex);
2382    
2383            _save_and_set_c_locale(&locale);
2384    
2385            pFxSendInfo = &(pClient->fxsend_info);
2386            lscp_fxsend_info_reset(pFxSendInfo);
2387    
2388            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2389            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2390                    pszResult = lscp_client_get_result(pClient);
2391                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2392                    while (pszToken) {
2393                            if (strcasecmp(pszToken, "NAME") == 0) {
2394                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2395                                    if (pszToken)
2396                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2397                            }
2398                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2399                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2400                                    if (pszToken)
2401                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2402                            }
2403                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2404                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2405                                    if (pszToken) {
2406                                            if (pFxSendInfo->audio_routing)
2407                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2408                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2409                                    }
2410                            }
2411                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2412                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2413                                    if (pszToken)
2414                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2415                            }
2416                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2417                    }
2418            }
2419            else pFxSendInfo = NULL;
2420    
2421            _restore_locale(&locale);
2422    
2423            // Unlock this section up.
2424            lscp_mutex_unlock(pClient->mutex);
2425    
2426            return pFxSendInfo;
2427    }
2428    
2429    
2430    /**
2431     *  Alter effect send's name:
2432     *  @code
2433     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2434     *  @endcode
2435     *
2436     *  @param pClient          Pointer to client instance structure.
2437     *  @param iSamplerChannel  Sampler channel number.
2438     *  @param iFxSend          Effect send number.
2439     *  @param pszFxName        Effect send's new name.
2440     *
2441     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2442     */
2443    lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2444            int iSamplerChannel, int iFxSend, const char *pszFxName )
2445    {
2446            char szQuery[LSCP_BUFSIZ];
2447    
2448            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2449                    return LSCP_FAILED;
2450    
2451            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2452                    iSamplerChannel, iFxSend, pszFxName);
2453            return lscp_client_query(pClient, szQuery);
2454    }
2455    
2456    
2457    /**
2458     *  Alter effect send's audio routing:
2459     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2460     *    <audio-src> <audio-dst>
2461     *
2462     *  @param pClient          Pointer to client instance structure.
2463     *  @param iSamplerChannel  Sampler channel number.
2464     *  @param iFxSend          Effect send number.
2465     *  @param iAudioSrc        Audio output device channel to be routed from.
2466     *  @param iAudioDst        Audio output device channel to be routed into.
2467     *
2468     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2469     */
2470    lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2471            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2472    {
2473            char szQuery[LSCP_BUFSIZ];
2474    
2475            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2476                    return LSCP_FAILED;
2477    
2478            sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2479                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2480            return lscp_client_query(pClient, szQuery);
2481    }
2482    
2483    
2484    /**
2485     *  Alter effect send's MIDI controller:
2486     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2487     *
2488     *  @param pClient          Pointer to client instance structure.
2489     *  @param iSamplerChannel  Sampler channel number.
2490     *  @param iFxSend          Effect send number.
2491     *  @param iMidiController  MIDI controller used to alter the effect,
2492     *                          usually a number between 0 and 127.
2493     *
2494     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2495     */
2496    lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2497            int iSamplerChannel, int iFxSend, int iMidiController )
2498    {
2499            char szQuery[LSCP_BUFSIZ];
2500    
2501            if (iSamplerChannel < 0 || iFxSend < 0 ||
2502                    iMidiController < 0 || iMidiController > 127)
2503                    return LSCP_FAILED;
2504    
2505            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2506                    iSamplerChannel, iFxSend, iMidiController);
2507            return lscp_client_query(pClient, szQuery);
2508    }
2509    
2510    
2511    /**
2512     *  Alter effect send's audio level:
2513     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2514     *
2515     *  @param pClient          Pointer to client instance structure.
2516     *  @param iSamplerChannel  Sampler channel number.
2517     *  @param iFxSend          Effect send number.
2518     *  @param fLevel           Effect send volume level.
2519     *
2520     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2521     */
2522    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2523            int iSamplerChannel, int iFxSend, float fLevel )
2524    {
2525            char szQuery[LSCP_BUFSIZ];
2526            struct _locale_t locale;
2527    
2528            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2529                    return LSCP_FAILED;
2530    
2531            _save_and_set_c_locale(&locale);
2532            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2533                    iSamplerChannel, iFxSend, fLevel);
2534            _restore_locale(&locale);
2535    
2536            return lscp_client_query(pClient, szQuery);
2537    }
2538    
2539    
2540    /**
2541   *  Create a new MIDI instrument map:   *  Create a new MIDI instrument map:
2542   *  ADD MIDI_INSTRUMENT_MAP [<name>]   *  ADD MIDI_INSTRUMENT_MAP [<name>]
2543   *   *
# Line 1759  int lscp_add_midi_instrument_map ( lscp_ Line 2559  int lscp_add_midi_instrument_map ( lscp_
2559          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2560    
2561          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2562            
2563          if (pszMapName)          if (pszMapName)
2564                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2565    
# Line 1885  const char *lscp_get_midi_instrument_map Line 2685  const char *lscp_get_midi_instrument_map
2685    
2686          // Lock this section up.          // Lock this section up.
2687          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2688            
2689          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2690                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2691                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
# Line 1949  lscp_status_t lscp_set_midi_instrument_m Line 2749  lscp_status_t lscp_set_midi_instrument_m
2749   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2750   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2751   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2752   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2753   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2754   *                          1.0 for amplification.   *                          1.0 for amplification.
2755   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 1961  lscp_status_t lscp_set_midi_instrument_m Line 2761  lscp_status_t lscp_set_midi_instrument_m
2761   *   *
2762   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2763   */   */
2764  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient,
2765            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2766            const char *pszFileName, int iInstrIndex, float fVolume,
2767            lscp_load_mode_t load_mode, const char *pszName )
2768  {  {
2769          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2770            struct _locale_t locale;
2771    
2772          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2773                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 1977  lscp_status_t lscp_map_midi_instrument ( Line 2781  lscp_status_t lscp_map_midi_instrument (
2781          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2782                  fVolume = 1.0f;                  fVolume = 1.0f;
2783    
2784            _save_and_set_c_locale(&locale);
2785          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2786                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2787                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2788            _restore_locale(&locale);
2789    
2790          switch (load_mode) {          switch (load_mode) {
2791          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2014  lscp_status_t lscp_map_midi_instrument ( Line 2820  lscp_status_t lscp_map_midi_instrument (
2820   *   *
2821   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2822   */   */
2823  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient,
2824            lscp_midi_instrument_t *pMidiInstr )
2825  {  {
2826          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2827    
# Line 2107  lscp_midi_instrument_t *lscp_list_midi_i Line 2914  lscp_midi_instrument_t *lscp_list_midi_i
2914          strcat(szQuery, "\r\n");          strcat(szQuery, "\r\n");
2915    
2916          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2917                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));                  pClient->midi_instruments = lscp_midi_instruments_create(
2918                            lscp_client_get_result(pClient));
2919    
2920          // Unlock this section down.          // Unlock this section down.
2921          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 2127  lscp_midi_instrument_t *lscp_list_midi_i Line 2935  lscp_midi_instrument_t *lscp_list_midi_i
2935   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2936   *  or NULL in case of failure.   *  or NULL in case of failure.
2937   */   */
2938  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient,
2939            lscp_midi_instrument_t *pMidiInstr )
2940  {  {
2941          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2942          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 2136  lscp_midi_instrument_info_t *lscp_get_mi Line 2945  lscp_midi_instrument_info_t *lscp_get_mi
2945          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2946          char *pszToken;          char *pszToken;
2947          char *pch;          char *pch;
2948            struct _locale_t locale;
2949    
2950          if (pClient == NULL)          if (pClient == NULL)
2951                  return NULL;                  return NULL;
# Line 2148  lscp_midi_instrument_info_t *lscp_get_mi Line 2958  lscp_midi_instrument_info_t *lscp_get_mi
2958    
2959          // Lock this section up.          // Lock this section up.
2960          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2961            
2962            _save_and_set_c_locale(&locale);
2963    
2964          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2965          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2966    
# Line 2202  lscp_midi_instrument_info_t *lscp_get_mi Line 3014  lscp_midi_instrument_info_t *lscp_get_mi
3014                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3015                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3016                                  if (pszToken)                                  if (pszToken)
3017                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3018                          }                          }
3019                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3020                  }                  }
3021          }          }
3022          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3023    
3024            _restore_locale(&locale);
3025    
3026          // Unlock this section down.          // Unlock this section down.
3027          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3028    
# Line 2240  lscp_status_t lscp_clear_midi_instrument Line 3054  lscp_status_t lscp_clear_midi_instrument
3054    
3055          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
3056  }  }
3057    
3058    
3059    /**
3060     * Open an instrument editor application for the instrument
3061     * on the given sampler channel:
3062     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3063     *
3064     * @param pClient         Pointer to client instance structure.
3065     * @param iSamplerChannel Sampler Channel.
3066     *
3067     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3068     */
3069    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3070    {
3071            char szQuery[LSCP_BUFSIZ];
3072    
3073            if (iSamplerChannel < 0)
3074                    return LSCP_FAILED;
3075    
3076            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3077    
3078            return lscp_client_query(pClient, szQuery);
3079    }
3080    
3081    
3082  // end of client.c  // end of client.c

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

  ViewVC Help
Powered by ViewVC