/[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 963 by capela, Sun Dec 3 18:30:04 2006 UTC revision 3842 by capela, Thu Dec 17 08:36:44 2020 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-2020, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This library is free software; you can redistribute it and/or     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    #include <sys/time.h>
26    #ifdef WIN32
27    # include <errno.h>
28    #else
29    # include <sys/errno.h>
30    #endif
31    
32    
33  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
34  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
35    
36    
37    // Whether to use getaddrinfo() instead
38    // of deprecated gethostbyname()
39    #if !defined(WIN32)
40    #define USE_GETADDRINFO 1
41    #endif
42    
43    
44  // Local prototypes.  // Local prototypes.
45    
46  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
47    
48  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
49  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,
50            int iSubscribe, lscp_event_t event);
51    
52    
53    //-------------------------------------------------------------------------
54    // General helper functions.
55    
56    struct _locale_t {
57            char numeric[32+1];
58            char ctype[32+1];
59    };
60    
61    // we need to ensure a constant locale setting e.g. for parsing
62    // floating point numbers with atof(), as the floating point separator
63    // character varies by the invidual locale settings
64    static void _save_and_set_c_locale(struct _locale_t* locale)
65    {
66            locale->numeric[32] = locale->ctype[32] = 0;
67            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
68            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
69            setlocale(LC_NUMERIC, "C");
70            setlocale(LC_CTYPE, "C");
71    }
72    
73    // restore the original locale setting as nothing happened
74    static void _restore_locale(struct _locale_t* locale)
75    {
76            setlocale(LC_NUMERIC, locale->numeric);
77            setlocale(LC_CTYPE, locale->ctype);
78    }
79    
80    // seems the standard atof() function doesnt care much about locale
81    // runtime modifications, so we use this workaround
82    static float _atof(const char* txt) {
83            float f;
84            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
85            return f;
86    }
87    
88    
89  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 102  static void _lscp_client_evt_proc ( void
102          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
103          int    cchBuffer;          int    cchBuffer;
104          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
105          char * pszToken;          char  *pszToken;
106          char * pch;          char  *pch;
107          int     cchToken;          int    cchToken;
108    
109          lscp_event_t event;          lscp_event_t event;
110    
111  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 137  static void _lscp_client_evt_proc ( void
137                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
138                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
139                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
140                                  // Parse for the notification event message...                                  pch = achBuffer;
141                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
142                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
143                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
144                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
145                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
146                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
147                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
148                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
149                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
150                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
151                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
152                                                                  pClient,                                                          // Invoke the client event callback...
153                                                                  event,                                                          if ((*pClient->pfnCallback)(
154                                                                  pszToken,                                                                          pClient,
155                                                                  cchToken,                                                                          event,
156                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
157                                                          pClient->evt.iState = 0;                                                                          cchToken,
158                                                                            pClient->pvData) != LSCP_OK) {
159                                                                    pClient->evt.iState = 0;
160                                                            }
161                                                  }                                                  }
162                                          }                                          }
163                                  }                                  } while (*pch);
164                          } else {                          } else {
165                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
166                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
167                                    pClient->iErrno = -errno;
168                          }                          }
169                  }   // Check if select has in error.                  }   // Check if select has in error.
170                  else if (iSelect < 0) {                  else if (iSelect < 0) {
171                          lscp_socket_perror("_lscp_client_evt_proc: select");                          lscp_socket_perror("_lscp_client_evt_proc: select");
172                          pClient->evt.iState = 0;                          pClient->evt.iState = 0;
173                            pClient->iErrno = -errno;
174                  }                  }
175    
176                  // Finally, always signal the event.                  // Finally, always signal the event.
# Line 146  static lscp_status_t _lscp_client_evt_co Line 204  static lscp_status_t _lscp_client_evt_co
204          }          }
205    
206  #if defined(WIN32)  #if defined(WIN32)
207          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
208                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
209                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
210  #endif  #endif
211    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 233  static lscp_status_t _lscp_client_evt_co
233    
234    
235  // Subscribe to a single event.  // Subscribe to a single event.
236  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,
237            int iSubscribe, lscp_event_t event )
238  {  {
239          const char *pszEvent;          const char *pszEvent;
240          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 249  static lscp_status_t _lscp_client_evt_re
249                  return LSCP_FAILED;                  return LSCP_FAILED;
250    
251          // Build the query string...          // Build the query string...
252          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
253                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
254          // Just send data, forget result...          // Just send data, forget result...
255          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
256                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 219  const char* lscp_client_package (void) { Line 280  const char* lscp_client_package (void) {
280  /** Retrieve the current client library version string. */  /** Retrieve the current client library version string. */
281  const char* lscp_client_version (void) { return LSCP_VERSION; }  const char* lscp_client_version (void) { return LSCP_VERSION; }
282    
283  /** Retrieve the current client library build timestamp string. */  /** Retrieve the current client library build string. */
284  const char* lscp_client_build   (void) { return __DATE__ " " __TIME__; }  const char* lscp_client_build   (void) { return LSCP_BUILD; }
285    
286    
287  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 240  const char* lscp_client_build   (void) { Line 301  const char* lscp_client_build   (void) {
301   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
302   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
303   */   */
304  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,
305            lscp_client_proc_t pfnCallback, void *pvData )
306  {  {
307          lscp_client_t  *pClient;          lscp_client_t  *pClient;
308    #if defined(USE_GETADDRINFO)
309            char szPort[33];
310            struct addrinfo hints;
311            struct addrinfo *result, *res;
312    #else
313          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
314          struct sockaddr_in addr;          struct sockaddr_in addr;
315          int cAddr;          int cAddr;
316    #endif  /* !USE_GETADDRINFO */
317            lscp_socket_t sock;
318  #if defined(WIN32)  #if defined(WIN32)
319          int iSockOpt = (-1);          int iSockOpt = (-1);
320  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 324  lscp_client_t* lscp_client_create ( cons
324                  return NULL;                  return NULL;
325          }          }
326    
327    #if defined(USE_GETADDRINFO)
328    
329            // Convert port number to string/name...
330            snprintf(szPort, sizeof(szPort), "%d", iPort);
331    
332            // Obtain address(es) matching host/port...
333            memset(&hints, 0, sizeof(struct addrinfo));
334            hints.ai_family = AF_INET;
335            hints.ai_socktype = SOCK_STREAM;
336    
337            result = NULL;
338    
339            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
340                    lscp_socket_herror("lscp_client_create: getaddrinfo");
341                    return NULL;
342            }
343    
344    #else
345    
346            // Obtain host matching name...
347          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
348          if (pHost == NULL) {          if (pHost == NULL) {
349                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
350                  return NULL;                  return NULL;
351          }          }
352    
353    #endif  /* !USE_GETADDRINFO */
354    
355          // Allocate client descriptor...          // Allocate client descriptor...
356    
357          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 365  lscp_client_t* lscp_client_create ( cons
365          pClient->pvData = pvData;          pClient->pvData = pvData;
366    
367  #ifdef DEBUG  #ifdef DEBUG
368          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
369                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
370                     pClient, pszHost, iPort);
371  #endif  #endif
372    
373          // Prepare the command connection socket...          // Prepare the command connection socket...
374    
375    #if defined(USE_GETADDRINFO)
376    
377            // getaddrinfo() returns a list of address structures;
378            // try each address until we successfully connect(2);
379            // if socket or connect fails, we close the socket and
380            // try the next address...
381            sock = INVALID_SOCKET;
382    
383            for (res = result; res; res = res->ai_next) {
384                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
385                    if (sock == INVALID_SOCKET)
386                            continue;
387            #if defined(WIN32)
388                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
389                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
390                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
391            #endif
392            #ifdef DEBUG
393                    lscp_socket_getopts("lscp_client_create: cmd", sock);
394            #endif
395                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
396                            break;
397                    closesocket(sock);
398            }
399    
400            if (sock == INVALID_SOCKET) {
401                    lscp_socket_perror("lscp_client_create: cmd: socket");
402                    free(pClient);
403                    return NULL;
404            }
405    
406            if (res == NULL) {
407                    lscp_socket_perror("lscp_client_create: cmd: connect");
408                    free(pClient);
409                    return NULL;
410            }
411    
412            // Initialize the command socket agent struct...
413            lscp_socket_agent_init(&(pClient->cmd), sock,
414                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
415    
416            // No longer needed...
417            freeaddrinfo(result);
418    
419    #else
420    
421          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
422          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
423                  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 426  lscp_client_t* lscp_client_create ( cons
426          }          }
427    
428  #if defined(WIN32)  #if defined(WIN32)
429          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
430                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
431                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
432  #endif  #endif
433    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 451  lscp_client_t* lscp_client_create ( cons
451          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
452          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
453    
454    #endif  /* !USE_GETADDRINFO */
455    
456  #ifdef DEBUG  #ifdef DEBUG
457          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,
458                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
459                    pClient, pClient->cmd.sock,
460                    inet_ntoa(pClient->cmd.addr.sin_addr),
461                    ntohs(pClient->cmd.addr.sin_port));
462  #endif  #endif
463    
464          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 327  lscp_client_t* lscp_client_create ( cons Line 472  lscp_client_t* lscp_client_create ( cons
472          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
473          pClient->engines = NULL;          pClient->engines = NULL;
474          pClient->channels = NULL;          pClient->channels = NULL;
475            pClient->fxsends = NULL;
476          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
477            pClient->midi_maps = NULL;
478            pClient->midi_map_name = NULL;
479          lscp_driver_info_init(&(pClient->audio_driver_info));          lscp_driver_info_init(&(pClient->audio_driver_info));
480          lscp_driver_info_init(&(pClient->midi_driver_info));          lscp_driver_info_init(&(pClient->midi_driver_info));
481          lscp_device_info_init(&(pClient->audio_device_info));          lscp_device_info_init(&(pClient->audio_device_info));
# Line 341  lscp_client_t* lscp_client_create ( cons Line 489  lscp_client_t* lscp_client_create ( cons
489          lscp_server_info_init(&(pClient->server_info));          lscp_server_info_init(&(pClient->server_info));
490          lscp_engine_info_init(&(pClient->engine_info));          lscp_engine_info_init(&(pClient->engine_info));
491          lscp_channel_info_init(&(pClient->channel_info));          lscp_channel_info_init(&(pClient->channel_info));
492            lscp_fxsend_info_init(&(pClient->fxsend_info));
493          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
494          // Initialize error stuff.          // Initialize error stuff.
495          pClient->pszResult = NULL;          pClient->pszResult = NULL;
# Line 403  lscp_status_t lscp_client_destroy ( lscp Line 552  lscp_status_t lscp_client_destroy ( lscp
552    
553          // Free up all cached members.          // Free up all cached members.
554          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
555            lscp_fxsend_info_free(&(pClient->fxsend_info));
556          lscp_channel_info_free(&(pClient->channel_info));          lscp_channel_info_free(&(pClient->channel_info));
557          lscp_engine_info_free(&(pClient->engine_info));          lscp_engine_info_free(&(pClient->engine_info));
558          lscp_server_info_free(&(pClient->server_info));          lscp_server_info_free(&(pClient->server_info));
# Line 423  lscp_status_t lscp_client_destroy ( lscp Line 573  lscp_status_t lscp_client_destroy ( lscp
573          lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->midi_devices);
574          lscp_szsplit_destroy(pClient->engines);          lscp_szsplit_destroy(pClient->engines);
575          lscp_isplit_destroy(pClient->channels);          lscp_isplit_destroy(pClient->channels);
576            lscp_isplit_destroy(pClient->fxsends);
577          lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_midi_instruments_destroy(pClient->midi_instruments);
578            lscp_isplit_destroy(pClient->midi_maps);
579            if (pClient->midi_map_name)
580                    free(pClient->midi_map_name);
581          // Make them null.          // Make them null.
582          pClient->audio_drivers = NULL;          pClient->audio_drivers = NULL;
583          pClient->midi_drivers = NULL;          pClient->midi_drivers = NULL;
# Line 431  lscp_status_t lscp_client_destroy ( lscp Line 585  lscp_status_t lscp_client_destroy ( lscp
585          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
586          pClient->engines = NULL;          pClient->engines = NULL;
587          pClient->channels = NULL;          pClient->channels = NULL;
588            pClient->fxsends = NULL;
589          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
590            pClient->midi_maps = NULL;
591            pClient->midi_map_name = NULL;
592          // Free result error stuff.          // Free result error stuff.
593          lscp_client_set_result(pClient, NULL, 0);          lscp_client_set_result(pClient, NULL, 0);
594          // Free stream usage stuff.          // Free stream usage stuff.
# Line 491  int lscp_client_get_timeout ( lscp_clien Line 648  int lscp_client_get_timeout ( lscp_clien
648          return pClient->iTimeout;          return pClient->iTimeout;
649  }  }
650    
651    /**
652     *  Check whether connection to server is lost.
653     *
654     *  @param pClient  Pointer to client instance structure.
655     *
656     *  @returns @c true if client lost connection to server, @c false otherwise.
657     */
658    bool lscp_client_connection_lost ( lscp_client_t *pClient )
659    {
660        int err = lscp_client_get_errno(pClient);
661        if (err >= 0) return false;
662        return err == -EPIPE || err == -ECONNRESET || err == -ECONNABORTED;
663    }
664    
665    
666  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
667  // Client common protocol functions.  // Client common protocol functions.
# Line 512  lscp_status_t lscp_client_query ( lscp_c Line 683  lscp_status_t lscp_client_query ( lscp_c
683  {  {
684          lscp_status_t ret;          lscp_status_t ret;
685    
686            if (pClient == NULL)
687                    return LSCP_FAILED;
688    
689          // Lock this section up.          // Lock this section up.
690          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
691    
# Line 563  int lscp_client_get_errno ( lscp_client_ Line 737  int lscp_client_get_errno ( lscp_client_
737  // Client registration protocol functions.  // Client registration protocol functions.
738    
739  /**  /**
740   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
741   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
742   *      | CHANNEL_INFO | MISCELLANEOUS   *  for @e each event you want to subscribe. That is the old bitflag approach
743     *  was abondoned at this point. You can however still register all older
744     *  events with one lscp_client_subscribe() call at once. Thus, the old
745     *  behavior of this functions was not broken. Those older events are namely:
746     *  @code
747     *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
748     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
749     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
750     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
751     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
752     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
753     *      | MISCELLANEOUS
754     *  @endcode
755     *  The old events occupy the lower 16 bits (as bit flags), and all younger
756     *  events enumerate the whole upper 16 bits range. The new, enumerated
757     *  events are namely:
758     *  @code
759     *  SUBSCRIBE CHANNEL_MIDI
760     *  @endcode
761   *   *
762   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
763   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
764   *   *
765   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
766   */   */
767  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 )
768  {  {
769          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
770            lscp_event_t currentEvent;
771    
772          if (pClient == NULL)          if (pClient == NULL)
773                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 597  lscp_status_t lscp_client_subscribe ( ls Line 790  lscp_status_t lscp_client_subscribe ( ls
790                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
791          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
792                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
793            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
794                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
795            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
796                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
797            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
798                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
799            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
800                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
801            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
802                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
803            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
804                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
805            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
806                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
807            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
808                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
809            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
810                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
811          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
812                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
813            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
814            currentEvent = events & 0xffff0000;
815            if (ret == LSCP_OK && currentEvent) {
816                    switch (currentEvent) {
817                            case LSCP_EVENT_CHANNEL_MIDI:
818                            case LSCP_EVENT_DEVICE_MIDI:
819                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
820                                    break;
821                            default: // unknown "upper" event type
822                                    ret = LSCP_FAILED;
823                                    break;
824                    }
825            }
826    
827          // Unlock this section down.          // Unlock this section down.
828          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 608  lscp_status_t lscp_client_subscribe ( ls Line 832  lscp_status_t lscp_client_subscribe ( ls
832    
833    
834  /**  /**
835   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
836   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call
837   *      | CHANNEL_INFO | MISCELLANEOUS   *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
838     *  That is the old bitflag approach was abondoned at this point. You can
839     *  however still register all older events with one lscp_client_subscribe()
840     *  call at once. Thus, the old behavior of this functions was not broken.
841     *  Those older events are namely:
842     *  @code
843     *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
844     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
845     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
846     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
847     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
848     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
849     *      | MISCELLANEOUS
850     *  @endcode
851     *  The old events occupy the lower 16 bits (as bit flags), and all younger
852     *  events enumerate the whole upper 16 bits range. The new, enumerated
853     *  events are namely:
854     *  @code
855     *  UNSUBSCRIBE CHANNEL_MIDI
856     *  @endcode
857   *   *
858   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
859   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
860   *   *
861   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
862   */   */
863  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 )
864  {  {
865          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
866            lscp_event_t currentEvent;
867    
868          if (pClient == NULL)          if (pClient == NULL)
869                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 638  lscp_status_t lscp_client_unsubscribe ( Line 882  lscp_status_t lscp_client_unsubscribe (
882                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
883          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
884                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
885            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
886                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
887            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
888                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
889            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
890                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
891            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
892                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
893            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
894                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
895            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
896                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
897            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
898                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
899            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
900                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
901            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
902                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
903          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
904                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
905            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
906            currentEvent = events & 0xffff0000;
907            if (ret == LSCP_OK && currentEvent) {
908                    switch (currentEvent) {
909                            case LSCP_EVENT_CHANNEL_MIDI:
910                            case LSCP_EVENT_DEVICE_MIDI:
911                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
912                                    break;
913                            default: // unknown "upper" event type
914                                    ret = LSCP_FAILED;
915                                    break;
916                    }
917            }
918    
919          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
920          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 682  lscp_event_t lscp_client_get_events ( ls Line 957  lscp_event_t lscp_client_get_events ( ls
957   *   *
958   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
959   */   */
960  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,
961            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
962  {  {
963          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
964    
965          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
966                  return LSCP_FAILED;                  return LSCP_FAILED;
967    
968          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
969                    pszFileName, iInstrIndex, iSamplerChannel);
970          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
971  }  }
972    
# Line 705  lscp_status_t lscp_load_instrument ( lsc Line 982  lscp_status_t lscp_load_instrument ( lsc
982   *   *
983   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
984   */   */
985  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,
986            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
987  {  {
988          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
989    
990          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
991                  return LSCP_FAILED;                  return LSCP_FAILED;
992    
993          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",
994                    pszFileName, iInstrIndex, iSamplerChannel);
995          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
996  }  }
997    
# Line 734  lscp_status_t lscp_load_engine ( lscp_cl Line 1013  lscp_status_t lscp_load_engine ( lscp_cl
1013          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
1014                  return LSCP_FAILED;                  return LSCP_FAILED;
1015    
1016          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
1017                    pszEngineName, iSamplerChannel);
1018          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1019  }  }
1020    
# Line 752  int lscp_get_channels ( lscp_client_t *p Line 1032  int lscp_get_channels ( lscp_client_t *p
1032  {  {
1033          int iChannels = -1;          int iChannels = -1;
1034    
1035            if (pClient == NULL)
1036                    return -1;
1037    
1038          // Lock this section up.          // Lock this section up.
1039          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1040    
# Line 812  int lscp_add_channel ( lscp_client_t *pC Line 1095  int lscp_add_channel ( lscp_client_t *pC
1095  {  {
1096          int iSamplerChannel = -1;          int iSamplerChannel = -1;
1097    
1098            if (pClient == NULL)
1099                    return -1;
1100    
1101          // Lock this section up.          // Lock this section up.
1102          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1103    
# Line 859  int lscp_get_available_engines ( lscp_cl Line 1145  int lscp_get_available_engines ( lscp_cl
1145  {  {
1146          int iAvailableEngines = -1;          int iAvailableEngines = -1;
1147    
1148            if (pClient == NULL)
1149                    return -1;
1150    
1151          // Lock this section up.          // Lock this section up.
1152          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1153    
# Line 885  const char **lscp_list_available_engines Line 1174  const char **lscp_list_available_engines
1174  {  {
1175          const char *pszSeps = ",";          const char *pszSeps = ",";
1176    
1177            if (pClient == NULL)
1178                    return NULL;
1179    
1180          // Lock this section up.          // Lock this section up.
1181          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1182    
# Line 913  const char **lscp_list_available_engines Line 1205  const char **lscp_list_available_engines
1205   *  @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
1206   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1207   */   */
1208  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,
1209            const char *pszEngineName )
1210  {  {
1211          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1212          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 923  lscp_engine_info_t *lscp_get_engine_info Line 1216  lscp_engine_info_t *lscp_get_engine_info
1216          char *pszToken;          char *pszToken;
1217          char *pch;          char *pch;
1218    
1219            if (pClient == NULL)
1220                    return NULL;
1221          if (pszEngineName == NULL)          if (pszEngineName == NULL)
1222                  return NULL;                  return NULL;
1223    
# Line 978  lscp_channel_info_t *lscp_get_channel_in Line 1273  lscp_channel_info_t *lscp_get_channel_in
1273          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1274          char *pszToken;          char *pszToken;
1275          char *pch;          char *pch;
1276            struct _locale_t locale;
1277    
1278            if (pClient == NULL)
1279                    return NULL;
1280          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1281                  return NULL;                  return NULL;
1282    
# Line 988  lscp_channel_info_t *lscp_get_channel_in Line 1286  lscp_channel_info_t *lscp_get_channel_in
1286          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1287          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1288    
1289            _save_and_set_c_locale(&locale);
1290    
1291          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1292          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1293                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1012  lscp_channel_info_t *lscp_get_channel_in Line 1312  lscp_channel_info_t *lscp_get_channel_in
1312                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1313                                  if (pszToken) {                                  if (pszToken) {
1314                                          if (pChannelInfo->audio_routing)                                          if (pChannelInfo->audio_routing)
1315                                                  lscp_szsplit_destroy(pChannelInfo->audio_routing);                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1316                                          pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1317                                  }                                  }
1318                          }                          }
1319                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
# Line 1056  lscp_channel_info_t *lscp_get_channel_in Line 1356  lscp_channel_info_t *lscp_get_channel_in
1356                                                  pChannelInfo->midi_channel = atoi(pszToken);                                                  pChannelInfo->midi_channel = atoi(pszToken);
1357                                  }                                  }
1358                          }                          }
1359                            else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1360                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1361                                    if (pszToken) {
1362                                            pszToken = lscp_ltrim(pszToken);
1363                                            if (strcasecmp(pszToken, "NONE") == 0)
1364                                                    pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1365                                            else
1366                                            if (strcasecmp(pszToken, "DEFAULT") == 0)
1367                                                    pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1368                                            else
1369                                                    pChannelInfo->midi_map = atoi(pszToken);
1370                                    }
1371                            }
1372                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1373                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1374                                  if (pszToken)                                  if (pszToken)
1375                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1376                          }                          }
1377                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1378                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1076  lscp_channel_info_t *lscp_get_channel_in Line 1389  lscp_channel_info_t *lscp_get_channel_in
1389          }          }
1390          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1391    
1392            _restore_locale(&locale);
1393    
1394          // Unlock this section up.          // Unlock this section up.
1395          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1396    
# Line 1097  int lscp_get_channel_voice_count ( lscp_ Line 1412  int lscp_get_channel_voice_count ( lscp_
1412          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1413          int iVoiceCount = -1;          int iVoiceCount = -1;
1414    
1415            if (pClient == NULL)
1416                    return -1;
1417          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1418                  return iVoiceCount;                  return -1;
1419    
1420          // Lock this section up.          // Lock this section up.
1421          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1128  int lscp_get_channel_stream_count ( lscp Line 1445  int lscp_get_channel_stream_count ( lscp
1445          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1446          int iStreamCount = -1;          int iStreamCount = -1;
1447    
1448            if (pClient == NULL)
1449                    return -1;
1450          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1451                  return iStreamCount;                  return -1;
1452    
1453          // Lock this section up.          // Lock this section up.
1454          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1165  int lscp_get_channel_stream_usage ( lscp Line 1484  int lscp_get_channel_stream_usage ( lscp
1484          int   iStream;          int   iStream;
1485          int   iPercent;          int   iPercent;
1486    
1487            if (pClient == NULL)
1488                    return -1;
1489          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1490                  return iStreamUsage;                  return -1;
1491    
1492          // Lock this section up.          // Lock this section up.
1493          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1213  int lscp_get_channel_stream_usage ( lscp Line 1534  int lscp_get_channel_stream_usage ( lscp
1534   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1535   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1536   */   */
1537  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,
1538            lscp_usage_t usage_type, int iSamplerChannel )
1539  {  {
1540          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1541          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1227  lscp_buffer_fill_t *lscp_get_channel_buf Line 1549  lscp_buffer_fill_t *lscp_get_channel_buf
1549    
1550          // Retrieve a channel stream estimation.          // Retrieve a channel stream estimation.
1551          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1552          if (pClient->iStreamCount < 0)          if (iStreamCount < 0)
1553                  return NULL;                  return NULL;
1554    
1555          // Lock this section up.          // Lock this section up.
# Line 1286  lscp_buffer_fill_t *lscp_get_channel_buf Line 1608  lscp_buffer_fill_t *lscp_get_channel_buf
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_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1612            int iSamplerChannel, const char *pszAudioDriver )
1613  {  {
1614          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1615    
1616          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1617                  return LSCP_FAILED;                  return LSCP_FAILED;
1618    
1619          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1620                    iSamplerChannel, pszAudioDriver);
1621          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1622  }  }
1623    
# Line 1308  lscp_status_t lscp_set_channel_audio_typ Line 1632  lscp_status_t lscp_set_channel_audio_typ
1632   *   *
1633   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1634   */   */
1635  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,
1636            int iSamplerChannel, int iAudioDevice )
1637  {  {
1638          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1639    
1640          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1641                  return LSCP_FAILED;                  return LSCP_FAILED;
1642    
1643          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1644                    iSamplerChannel, iAudioDevice);
1645          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1646  }  }
1647    
# Line 1331  lscp_status_t lscp_set_channel_audio_dev Line 1657  lscp_status_t lscp_set_channel_audio_dev
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_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1661            int iSamplerChannel, int iAudioOut, int iAudioIn )
1662  {  {
1663          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1664    
1665          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1666                  return LSCP_FAILED;                  return LSCP_FAILED;
1667    
1668          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",
1669                    iSamplerChannel, iAudioOut, iAudioIn);
1670          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1671  }  }
1672    
# Line 1353  lscp_status_t lscp_set_channel_audio_cha Line 1681  lscp_status_t lscp_set_channel_audio_cha
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_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1685            int iSamplerChannel, const char *pszMidiDriver )
1686  {  {
1687          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1688    
1689          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1690                  return LSCP_FAILED;                  return LSCP_FAILED;
1691    
1692          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1693                    iSamplerChannel, pszMidiDriver);
1694          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1695  }  }
1696    
# Line 1375  lscp_status_t lscp_set_channel_midi_type Line 1705  lscp_status_t lscp_set_channel_midi_type
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_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1709            int iSamplerChannel, int iMidiDevice )
1710  {  {
1711          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1712    
1713          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1714                  return LSCP_FAILED;                  return LSCP_FAILED;
1715    
1716          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1717                    iSamplerChannel, iMidiDevice);
1718          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1719  }  }
1720    
# Line 1397  lscp_status_t lscp_set_channel_midi_devi Line 1729  lscp_status_t lscp_set_channel_midi_devi
1729   *   *
1730   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1731   */   */
1732  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,
1733            int iSamplerChannel, int iMidiPort )
1734  {  {
1735          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1736    
1737          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1738                  return LSCP_FAILED;                  return LSCP_FAILED;
1739    
1740          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1741                    iSamplerChannel, iMidiPort);
1742          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1743  }  }
1744    
# Line 1416  lscp_status_t lscp_set_channel_midi_port Line 1750  lscp_status_t lscp_set_channel_midi_port
1750   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
1751   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
1752   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or
1753   *                          LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.   *                          @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1754   *   *
1755   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1756   */   */
1757  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,
1758            int iSamplerChannel, int iMidiChannel )
1759  {  {
1760          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1761    
# Line 1428  lscp_status_t lscp_set_channel_midi_chan Line 1763  lscp_status_t lscp_set_channel_midi_chan
1763                  return LSCP_FAILED;                  return LSCP_FAILED;
1764    
1765          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1766                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1767                            iSamplerChannel);
1768          else          else
1769                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1770                            iSamplerChannel, iMidiChannel);
1771            return lscp_client_query(pClient, szQuery);
1772    }
1773    
1774    
1775    /**
1776     *  Setting MIDI instrument map:
1777     *  SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1778     *
1779     *  @param pClient          Pointer to client instance structure.
1780     *  @param iSamplerChannel  Sampler channel number.
1781     *  @param iMidiMap         MIDI instrument map number, or either
1782     *                          @ref LSCP_MIDI_MAP_NONE or
1783     *                          @ref LSCP_MIDI_MAP_DEFAULT .
1784     *
1785     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1786     */
1787    lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1788            int iSamplerChannel, int iMidiMap )
1789    {
1790            char szQuery[LSCP_BUFSIZ];
1791    
1792            if (iSamplerChannel < 0)
1793                    return LSCP_FAILED;
1794    
1795            sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1796            if (iMidiMap == LSCP_MIDI_MAP_NONE)
1797                    strcat(szQuery , "NONE");
1798            else
1799            if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1800                    strcat(szQuery , "DEFAULT");
1801            else
1802                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1803    
1804            strcat(szQuery, "\r\n");
1805    
1806          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1807  }  }
1808    
# Line 1447  lscp_status_t lscp_set_channel_midi_chan Line 1819  lscp_status_t lscp_set_channel_midi_chan
1819   *   *
1820   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1821   */   */
1822  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,
1823            int iSamplerChannel, float fVolume )
1824  {  {
1825          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1826            struct _locale_t locale;
1827    
1828          if (iSamplerChannel < 0 || fVolume < 0.0)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1829                  return LSCP_FAILED;                  return LSCP_FAILED;
1830    
1831          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1832            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1833                    iSamplerChannel, fVolume);
1834            _restore_locale(&locale);
1835    
1836          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1837  }  }
1838    
# Line 1471  lscp_status_t lscp_set_channel_volume ( Line 1849  lscp_status_t lscp_set_channel_volume (
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_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1853            int iSamplerChannel, int iMute )
1854  {  {
1855          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1856    
1857          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1858                  return LSCP_FAILED;                  return LSCP_FAILED;
1859    
1860          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1861                    iSamplerChannel, iMute);
1862          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1863  }  }
1864    
# Line 1495  lscp_status_t lscp_set_channel_mute ( ls Line 1875  lscp_status_t lscp_set_channel_mute ( ls
1875   *   *
1876   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1877   */   */
1878  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,
1879            int iSamplerChannel, int iSolo )
1880  {  {
1881          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1882    
1883          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1884                  return LSCP_FAILED;                  return LSCP_FAILED;
1885    
1886          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1887                    iSamplerChannel, iSolo);
1888          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1889  }  }
1890    
# Line 1538  lscp_status_t lscp_reset_channel ( lscp_ Line 1920  lscp_status_t lscp_reset_channel ( lscp_
1920   */   */
1921  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1922  {  {
1923            // Do actual whole sampler reset...
1924          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1925  }  }
1926    
# Line 1560  lscp_server_info_t *lscp_get_server_info Line 1943  lscp_server_info_t *lscp_get_server_info
1943          char *pszToken;          char *pszToken;
1944          char *pch;          char *pch;
1945    
1946            if (pClient == NULL)
1947                    return NULL;
1948    
1949          // Lock this section up.          // Lock this section up.
1950          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1951    
# Line 1580  lscp_server_info_t *lscp_get_server_info Line 1966  lscp_server_info_t *lscp_get_server_info
1966                                  if (pszToken)                                  if (pszToken)
1967                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1968                          }                          }
1969                            else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1970                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1971                                    if (pszToken)
1972                                            lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1973                            }
1974                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1975                  }                  }
1976          }          }
# Line 1605  int lscp_get_total_voice_count ( lscp_cl Line 1996  int lscp_get_total_voice_count ( lscp_cl
1996  {  {
1997          int iVoiceCount = -1;          int iVoiceCount = -1;
1998    
1999            if (pClient == NULL)
2000                    return -1;
2001    
2002          // Lock this section up.          // Lock this section up.
2003          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2004    
# Line 1631  int lscp_get_total_voice_count_max ( lsc Line 2025  int lscp_get_total_voice_count_max ( lsc
2025  {  {
2026          int iVoiceCount = -1;          int iVoiceCount = -1;
2027    
2028            if (pClient == NULL)
2029                    return -1;
2030    
2031          // Lock this section up.          // Lock this section up.
2032          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2033    
# Line 1645  int lscp_get_total_voice_count_max ( lsc Line 2042  int lscp_get_total_voice_count_max ( lsc
2042    
2043    
2044  /**  /**
2045     *  Get global volume attenuation:
2046     *  GET VOLUME
2047     *
2048     *  @param pClient  Pointer to client instance structure.
2049     *
2050     *  @returns The global volume as positive floating point value usually in
2051     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2052     */
2053    float lscp_get_volume ( lscp_client_t *pClient )
2054    {
2055            float fVolume = 0.0f;
2056            struct _locale_t locale;
2057    
2058            if (pClient == NULL)
2059                    return 0.0f;
2060    
2061            // Lock this section up.
2062            lscp_mutex_lock(pClient->mutex);
2063    
2064            _save_and_set_c_locale(&locale);
2065    
2066            if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2067                    fVolume = _atof(lscp_client_get_result(pClient));
2068    
2069            _restore_locale(&locale);
2070    
2071            // Unlock this section down.
2072            lscp_mutex_unlock(pClient->mutex);
2073    
2074            return fVolume;
2075    }
2076    
2077    
2078    /**
2079     *  Setting global volume attenuation:
2080     *  SET VOLUME <volume>
2081     *
2082     *  @param pClient  Pointer to client instance structure.
2083     *  @param fVolume  Global volume parameter as positive floating point
2084     *                  value usually be in the range between 0.0 and 1.0,
2085     *                  that is for attenuating the overall volume.
2086     *
2087     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2088     */
2089    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2090    {
2091            char szQuery[LSCP_BUFSIZ];
2092            struct _locale_t locale;
2093    
2094            if (fVolume < 0.0f)
2095                    return LSCP_FAILED;
2096    
2097            _save_and_set_c_locale(&locale);
2098            sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2099            _restore_locale(&locale);
2100    
2101            return lscp_client_query(pClient, szQuery);
2102    }
2103    
2104    
2105    /**
2106     *  Get global voice limit setting:
2107     *  @code
2108     *  GET VOICES
2109     *  @endcode
2110     *  This value reflects the maximum amount of voices a sampler engine
2111     *  processes simultaniously before voice stealing kicks in.
2112     *
2113     *  @param pClient  Pointer to client instance structure.
2114     *
2115     *  @returns The current global maximum amount of voices limit or a
2116     *           negative value on error (e.g. if sampler doesn't support
2117     *           this command).
2118     */
2119    int lscp_get_voices ( lscp_client_t *pClient )
2120    {
2121            int iVoices = -1;
2122    
2123            if (pClient == NULL)
2124                    return -1;
2125    
2126            // Lock this section up.
2127            lscp_mutex_lock(pClient->mutex);
2128    
2129            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2130                    iVoices = atoi(lscp_client_get_result(pClient));
2131    
2132            // Unlock this section down.
2133            lscp_mutex_unlock(pClient->mutex);
2134    
2135            return iVoices;
2136    }
2137    
2138    
2139    /**
2140     *  Setting global voice limit setting:
2141     *  @code
2142     *  SET VOICES <max-voices>
2143     *  @endcode
2144     *  This value reflects the maximum amount of voices a sampler engine
2145     *  processes simultaniously before voice stealing kicks in. Note that
2146     *  this value will be passed to all sampler engine instances, that is
2147     *  the total amount of maximum voices on the running system is thus
2148     *  @param iMaxVoices multiplied with the current amount of sampler
2149     *  engine instances.
2150     *
2151     *  @param pClient     Pointer to client instance structure.
2152     *  @param iMaxVoices  Global voice limit setting as integer value larger
2153     *                     or equal to 1.
2154     *
2155     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2156     */
2157    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2158    {
2159            char szQuery[LSCP_BUFSIZ];
2160    
2161            if (iMaxVoices < 1)
2162                    return LSCP_FAILED;
2163    
2164            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2165            return lscp_client_query(pClient, szQuery);
2166    }
2167    
2168    
2169    /**
2170     *  Get global disk streams limit setting:
2171     *  @code
2172     *  GET STREAMS
2173     *  @endcode
2174     *  This value reflects the maximum amount of disk streams a sampler
2175     *  engine processes simultaniously.
2176     *
2177     *  @param pClient  Pointer to client instance structure.
2178     *
2179     *  @returns The current global maximum amount of disk streams limit
2180     *           or a negative value on error (e.g. if sampler doesn't
2181     *           support this command).
2182     */
2183    int lscp_get_streams ( lscp_client_t *pClient )
2184    {
2185            int iStreams = -1;
2186    
2187            if (pClient == NULL)
2188                    return -1;
2189    
2190            // Lock this section up.
2191            lscp_mutex_lock(pClient->mutex);
2192    
2193            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2194                    iStreams = atoi(lscp_client_get_result(pClient));
2195    
2196            // Unlock this section down.
2197            lscp_mutex_unlock(pClient->mutex);
2198    
2199            return iStreams;
2200    }
2201    
2202    
2203    /**
2204     *  Setting global disk streams limit setting:
2205     *  @code
2206     *  SET STREAMS <max-streams>
2207     *  @endcode
2208     *  This value reflects the maximum amount of dist streams a sampler
2209     *  engine instance processes simultaniously. Note that this value will
2210     *  be passed to all sampler engine instances, that is the total amount
2211     *  of maximum disk streams on the running system is thus
2212     *  @param iMaxStreams multiplied with the current amount of sampler
2213     *  engine instances.
2214     *
2215     *  @param pClient      Pointer to client instance structure.
2216     *  @param iMaxStreams  Global streams limit setting as positive integer
2217     *                      value (larger or equal to 0).
2218     *
2219     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2220     */
2221    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2222    {
2223            char szQuery[LSCP_BUFSIZ];
2224    
2225            if (iMaxStreams < 0)
2226                    return LSCP_FAILED;
2227    
2228            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2229            return lscp_client_query(pClient, szQuery);
2230    }
2231    
2232    
2233    /**
2234     *  Add an effect send to a sampler channel:
2235     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2236     *
2237     *  @param pClient          Pointer to client instance structure.
2238     *  @param iSamplerChannel  Sampler channel number.
2239     *  @param iMidiController  MIDI controller used to alter the effect,
2240     *                          usually a number between 0 and 127.
2241     *  @param pszFxName        Optional name for the effect send entity,
2242     *                          does not have to be unique.
2243     *
2244     *  @returns The new effect send number identifier, or -1 in case of failure.
2245     */
2246    int lscp_create_fxsend ( lscp_client_t *pClient,
2247            int iSamplerChannel, int iMidiController, const char *pszFxName )
2248    {
2249            int iFxSend = -1;
2250            char szQuery[LSCP_BUFSIZ];
2251    
2252            if (pClient == NULL)
2253                    return -1;
2254            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2255                    return -1;
2256    
2257            // Lock this section up.
2258            lscp_mutex_lock(pClient->mutex);
2259    
2260            sprintf(szQuery, "CREATE FX_SEND %d %d",
2261                    iSamplerChannel, iMidiController);
2262    
2263            if (pszFxName)
2264                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2265    
2266            strcat(szQuery, "\r\n");
2267    
2268            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2269                    iFxSend = atoi(lscp_client_get_result(pClient));
2270    
2271            // Unlock this section down.
2272            lscp_mutex_unlock(pClient->mutex);
2273    
2274            return iFxSend;
2275    }
2276    
2277    
2278    /**
2279     *  Remove an effect send from a sampler channel:
2280     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2281     *
2282     *  @param pClient          Pointer to client instance structure.
2283     *  @param iSamplerChannel  Sampler channel number.
2284     *  @param iFxSend          Effect send number.
2285     *
2286     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2287     */
2288    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2289            int iSamplerChannel, int iFxSend )
2290    {
2291            char szQuery[LSCP_BUFSIZ];
2292    
2293            if (iSamplerChannel < 0 || iFxSend < 0)
2294                    return LSCP_FAILED;
2295    
2296            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2297                    iSamplerChannel, iFxSend);
2298    
2299            return lscp_client_query(pClient, szQuery);
2300    }
2301    
2302    
2303    /**
2304     *  Get amount of effect sends on a sampler channel:
2305     *  GET FX_SENDS <sampler-channel>
2306     *
2307     *  @param pClient          Pointer to client instance structure.
2308     *  @param iSamplerChannel  Sampler channel number.
2309     *
2310     *  @returns The current total number of effect sends of the sampler channel
2311     *  on success, -1 otherwise.
2312     */
2313    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2314    {
2315            int iFxSends = -1;
2316            char szQuery[LSCP_BUFSIZ];
2317    
2318            if (pClient == NULL)
2319                    return -1;
2320            if (iSamplerChannel < 0)
2321                    return -1;
2322    
2323            // Lock this section up.
2324            lscp_mutex_lock(pClient->mutex);
2325    
2326            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2327    
2328            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2329                    iFxSends = atoi(lscp_client_get_result(pClient));
2330    
2331            // Unlock this section doen.
2332            lscp_mutex_unlock(pClient->mutex);
2333    
2334            return iFxSends;
2335    }
2336    
2337    
2338    /**
2339     *  List all effect sends on a sampler channel:
2340     *  LIST FX_SENDS <sampler-channel>
2341     *
2342     *  @param pClient          Pointer to client instance structure.
2343     *  @param iSamplerChannel  Sampler channel number.
2344     *
2345     *  @returns An array of the effect sends identifiers as positive integers,
2346     *  terminated with -1 on success, NULL otherwise.
2347     */
2348    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2349    {
2350            const char *pszSeps = ",";
2351            char szQuery[LSCP_BUFSIZ];
2352    
2353            if (pClient == NULL)
2354                    return NULL;
2355    
2356            // Lock this section up.
2357            lscp_mutex_lock(pClient->mutex);
2358    
2359            if (pClient->fxsends) {
2360                    lscp_isplit_destroy(pClient->fxsends);
2361                    pClient->fxsends = NULL;
2362            }
2363    
2364            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2365    
2366            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2367                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2368    
2369            // Unlock this section down.
2370            lscp_mutex_unlock(pClient->mutex);
2371    
2372            return pClient->fxsends;
2373    }
2374    
2375    
2376    /**
2377     *  Getting effect send information
2378     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2379     *
2380     *  @param pClient          Pointer to client instance structure.
2381     *  @param iSamplerChannel  Sampler channel number.
2382     *  @param iFxSend          Effect send number.
2383     *
2384     *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2385     *  information of the given FX send, or NULL in case of failure.
2386     */
2387    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2388            int iSamplerChannel, int iFxSend )
2389    {
2390            lscp_fxsend_info_t *pFxSendInfo;
2391            char szQuery[LSCP_BUFSIZ];
2392            const char *pszResult;
2393            const char *pszSeps = ":";
2394            const char *pszCrlf = "\r\n";
2395            char *pszToken;
2396            char *pch;
2397            struct _locale_t locale;
2398    
2399            if (pClient == NULL)
2400                    return NULL;
2401            if (iSamplerChannel < 0 || iFxSend < 0)
2402                    return NULL;
2403    
2404            // Lock this section up.
2405            lscp_mutex_lock(pClient->mutex);
2406    
2407            _save_and_set_c_locale(&locale);
2408    
2409            pFxSendInfo = &(pClient->fxsend_info);
2410            lscp_fxsend_info_reset(pFxSendInfo);
2411    
2412            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2413            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2414                    pszResult = lscp_client_get_result(pClient);
2415                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2416                    while (pszToken) {
2417                            if (strcasecmp(pszToken, "NAME") == 0) {
2418                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2419                                    if (pszToken)
2420                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2421                            }
2422                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2423                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2424                                    if (pszToken)
2425                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2426                            }
2427                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2428                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2429                                    if (pszToken) {
2430                                            if (pFxSendInfo->audio_routing)
2431                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2432                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2433                                    }
2434                            }
2435                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2436                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2437                                    if (pszToken)
2438                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2439                            }
2440                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2441                    }
2442            }
2443            else pFxSendInfo = NULL;
2444    
2445            _restore_locale(&locale);
2446    
2447            // Unlock this section up.
2448            lscp_mutex_unlock(pClient->mutex);
2449    
2450            return pFxSendInfo;
2451    }
2452    
2453    
2454    /**
2455     *  Alter effect send's name:
2456     *  @code
2457     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2458     *  @endcode
2459     *
2460     *  @param pClient          Pointer to client instance structure.
2461     *  @param iSamplerChannel  Sampler channel number.
2462     *  @param iFxSend          Effect send number.
2463     *  @param pszFxName        Effect send's new name.
2464     *
2465     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2466     */
2467    lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2468            int iSamplerChannel, int iFxSend, const char *pszFxName )
2469    {
2470            char szQuery[LSCP_BUFSIZ];
2471    
2472            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2473                    return LSCP_FAILED;
2474    
2475            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2476                    iSamplerChannel, iFxSend, pszFxName);
2477            return lscp_client_query(pClient, szQuery);
2478    }
2479    
2480    
2481    /**
2482     *  Alter effect send's audio routing:
2483     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2484     *    <audio-src> <audio-dst>
2485     *
2486     *  @param pClient          Pointer to client instance structure.
2487     *  @param iSamplerChannel  Sampler channel number.
2488     *  @param iFxSend          Effect send number.
2489     *  @param iAudioSrc        Audio output device channel to be routed from.
2490     *  @param iAudioDst        Audio output device channel to be routed into.
2491     *
2492     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2493     */
2494    lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2495            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2496    {
2497            char szQuery[LSCP_BUFSIZ];
2498    
2499            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2500                    return LSCP_FAILED;
2501    
2502            sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2503                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2504            return lscp_client_query(pClient, szQuery);
2505    }
2506    
2507    
2508    /**
2509     *  Alter effect send's MIDI controller:
2510     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2511     *
2512     *  @param pClient          Pointer to client instance structure.
2513     *  @param iSamplerChannel  Sampler channel number.
2514     *  @param iFxSend          Effect send number.
2515     *  @param iMidiController  MIDI controller used to alter the effect,
2516     *                          usually a number between 0 and 127.
2517     *
2518     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2519     */
2520    lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2521            int iSamplerChannel, int iFxSend, int iMidiController )
2522    {
2523            char szQuery[LSCP_BUFSIZ];
2524    
2525            if (iSamplerChannel < 0 || iFxSend < 0 ||
2526                    iMidiController < 0 || iMidiController > 127)
2527                    return LSCP_FAILED;
2528    
2529            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2530                    iSamplerChannel, iFxSend, iMidiController);
2531            return lscp_client_query(pClient, szQuery);
2532    }
2533    
2534    
2535    /**
2536     *  Alter effect send's audio level:
2537     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2538     *
2539     *  @param pClient          Pointer to client instance structure.
2540     *  @param iSamplerChannel  Sampler channel number.
2541     *  @param iFxSend          Effect send number.
2542     *  @param fLevel           Effect send volume level.
2543     *
2544     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2545     */
2546    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2547            int iSamplerChannel, int iFxSend, float fLevel )
2548    {
2549            char szQuery[LSCP_BUFSIZ];
2550            struct _locale_t locale;
2551    
2552            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2553                    return LSCP_FAILED;
2554    
2555            _save_and_set_c_locale(&locale);
2556            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2557                    iSamplerChannel, iFxSend, fLevel);
2558            _restore_locale(&locale);
2559    
2560            return lscp_client_query(pClient, szQuery);
2561    }
2562    
2563    
2564    /**
2565     *  Create a new MIDI instrument map:
2566     *  ADD MIDI_INSTRUMENT_MAP [<name>]
2567     *
2568     *  @param pClient      Pointer to client instance structure.
2569     *  @param pszMapName   MIDI instrument map name (optional)
2570     *
2571     *  @returns The new MIDI instrument map number identifier,
2572     *  or -1 in case of failure.
2573     */
2574    int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
2575    {
2576            int iMidiMap = -1;
2577            char szQuery[LSCP_BUFSIZ];
2578    
2579            if (pClient == NULL)
2580                    return -1;
2581    
2582            // Lock this section up.
2583            lscp_mutex_lock(pClient->mutex);
2584    
2585            strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2586    
2587            if (pszMapName)
2588                    sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2589    
2590            strcat(szQuery, "\r\n");
2591    
2592            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2593                    iMidiMap = atoi(lscp_client_get_result(pClient));
2594    
2595            // Unlock this section down.
2596            lscp_mutex_unlock(pClient->mutex);
2597    
2598            return iMidiMap;
2599    }
2600    
2601    
2602    /**
2603     *  Delete one particular or all MIDI instrument maps:
2604     *  REMOVE MIDI_INSTRUMENT_MAP <midi-map>
2605     *
2606     *  @param pClient  Pointer to client instance structure.
2607     *  @param iMidiMap MIDI instrument map number.
2608     *
2609     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2610     */
2611    lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
2612    {
2613            char szQuery[LSCP_BUFSIZ];
2614    
2615            if (iMidiMap < 0)
2616                    return LSCP_FAILED;
2617    
2618            sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
2619    
2620            return lscp_client_query(pClient, szQuery);
2621    }
2622    
2623    
2624    /**
2625     *  Get amount of existing MIDI instrument maps:
2626     *  GET MIDI_INSTRUMENT_MAPS
2627     *
2628     *  @param pClient  Pointer to client instance structure.
2629     *
2630     *  @returns The current total number of MIDI instrument maps
2631     *  on success, -1 otherwise.
2632     */
2633    int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
2634    {
2635            int iMidiMaps = -1;
2636    
2637            if (pClient == NULL)
2638                    return -1;
2639    
2640            // Lock this section up.
2641            lscp_mutex_lock(pClient->mutex);
2642    
2643            if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2644                    iMidiMaps = atoi(lscp_client_get_result(pClient));
2645    
2646            // Unlock this section doen.
2647            lscp_mutex_unlock(pClient->mutex);
2648    
2649            return iMidiMaps;
2650    }
2651    
2652    
2653    /**
2654     *  Getting all created MIDI instrument maps:
2655     *  LIST MIDI_INSTRUMENT_MAPS
2656     *
2657     *  @param pClient  Pointer to client instance structure.
2658     *
2659     *  @returns An array of the MIDI instrument map identifiers as positive
2660     *  integers, terminated with -1 on success, NULL otherwise.
2661     */
2662    int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
2663    {
2664            const char *pszSeps = ",";
2665    
2666            if (pClient == NULL)
2667                    return NULL;
2668    
2669            // Lock this section up.
2670            lscp_mutex_lock(pClient->mutex);
2671    
2672            if (pClient->midi_maps) {
2673                    lscp_isplit_destroy(pClient->midi_maps);
2674                    pClient->midi_maps = NULL;
2675            }
2676    
2677            if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2678                    pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2679    
2680            // Unlock this section down.
2681            lscp_mutex_unlock(pClient->mutex);
2682    
2683            return pClient->midi_maps;
2684    }
2685    
2686    
2687    /**
2688     *  Getting a MIDI instrument map name:
2689     *  GET MIDI_INSTRUMENT_MAP INFO <midi-map>
2690     *
2691     *  @param pClient  Pointer to client instance structure.
2692     *  @param iMidiMap MIDI instrument map number.
2693     *
2694     *  @returns The MIDI instrument map name on success, NULL on failure.
2695     */
2696    const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
2697    {
2698            char szQuery[LSCP_BUFSIZ];
2699            const char *pszResult;
2700            const char *pszSeps = ":";
2701            const char *pszCrlf = "\r\n";
2702            char *pszToken;
2703            char *pch;
2704    
2705            if (pClient == NULL)
2706                    return NULL;
2707            if (iMidiMap < 0)
2708                    return NULL;
2709    
2710            // Lock this section up.
2711            lscp_mutex_lock(pClient->mutex);
2712    
2713            if (pClient->midi_map_name) {
2714                    free(pClient->midi_map_name);
2715                    pClient->midi_map_name = NULL;
2716            }
2717    
2718            sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
2719            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2720                    pszResult = lscp_client_get_result(pClient);
2721                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2722                    while (pszToken) {
2723                            if (strcasecmp(pszToken, "NAME") == 0) {
2724                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2725                                    if (pszToken)
2726                                            lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
2727                            }
2728                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2729                    }
2730            }
2731    
2732            // Unlock this section down.
2733            lscp_mutex_unlock(pClient->mutex);
2734    
2735            return pClient->midi_map_name;
2736    }
2737    
2738    
2739    /**
2740     *  Renaming a MIDI instrument map:
2741     *  SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
2742     *
2743     *  @param pClient      Pointer to client instance structure.
2744     *  @param iMidiMap     MIDI instrument map number.
2745     *  @param pszMapName   MIDI instrument map name.
2746     *
2747     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2748     */
2749    lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
2750    {
2751            char szQuery[LSCP_BUFSIZ];
2752    
2753            if (iMidiMap < 0)
2754                    return LSCP_FAILED;
2755            if (pszMapName == NULL)
2756                    return LSCP_FAILED;
2757    
2758            sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
2759                    iMidiMap, pszMapName);
2760    
2761            return lscp_client_query(pClient, szQuery);
2762    }
2763    
2764    
2765    /**
2766   *  Create or replace a MIDI instrumnet map entry:   *  Create or replace a MIDI instrumnet map entry:
2767   *  MAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2768   *      <engine-name> <filename> <instr-index> <volume> <load-mode> [<name>]   *      <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
2769   *   *
2770   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2771   *  @param pMidiInstr       MIDI instrument bank and program parameter key.   *  @param pMidiInstr       MIDI instrument bank and program parameter key.
# Line 1655  int lscp_get_total_voice_count_max ( lsc Line 2773  int lscp_get_total_voice_count_max ( lsc
2773   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2774   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2775   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2776   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2777   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2778   *                          1.0 for amplification.   *                          1.0 for amplification.
2779   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 1663  int lscp_get_total_voice_count_max ( lsc Line 2781  int lscp_get_total_voice_count_max ( lsc
2781   *                          @ref LSCP_LOAD_ON_DEMAND, or   *                          @ref LSCP_LOAD_ON_DEMAND, or
2782   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or
2783   *                          @ref LSCP_LOAD_PERSISTENT.   *                          @ref LSCP_LOAD_PERSISTENT.
2784   *  @param pszName          Instrument custom name for the map entry.   *  @param pszName         Instrument custom name for the map entry (optional).
2785   *   *
2786   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2787   */   */
2788  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,
2789            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2790            const char *pszFileName, int iInstrIndex, float fVolume,
2791            lscp_load_mode_t load_mode, const char *pszName )
2792  {  {
2793          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2794            struct _locale_t locale;
2795    
2796          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pMidiInstr->map < 0)
2797                  return LSCP_FAILED;                  return LSCP_FAILED;
2798          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2799                  return LSCP_FAILED;                  return LSCP_FAILED;
2800          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2801                  return LSCP_FAILED;                  return LSCP_FAILED;
2802          if (pszEngineName == NULL || pszFileName == NULL)          if (pszEngineName == NULL || pszFileName == NULL)
2803                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 1683  lscp_status_t lscp_map_midi_instrument ( Line 2805  lscp_status_t lscp_map_midi_instrument (
2805          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2806                  fVolume = 1.0f;                  fVolume = 1.0f;
2807    
2808            _save_and_set_c_locale(&locale);
2809          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2810                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2811                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2812            _restore_locale(&locale);
2813    
2814          switch (load_mode) {          switch (load_mode) {
2815          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 1713  lscp_status_t lscp_map_midi_instrument ( Line 2837  lscp_status_t lscp_map_midi_instrument (
2837    
2838  /**  /**
2839   *  Remove an entry from the MIDI instrument map:   *  Remove an entry from the MIDI instrument map:
2840   *  UNMAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2841   *   *
2842   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2843   *  @param pMidiInstr   MIDI instrument bank and program parameter key.   *  @param pMidiInstr   MIDI instrument bank and program parameter key.
2844   *   *
2845   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2846   */   */
2847  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,
2848            lscp_midi_instrument_t *pMidiInstr )
2849  {  {
2850          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2851    
2852          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pMidiInstr->map < 0)
2853                  return LSCP_FAILED;                  return LSCP_FAILED;
2854          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2855                  return LSCP_FAILED;                  return LSCP_FAILED;
2856          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2857                  return LSCP_FAILED;                  return LSCP_FAILED;
2858    
2859          sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",          sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2860                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2861    
2862          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2863  }  }
# Line 1740  lscp_status_t lscp_unmap_midi_instrument Line 2865  lscp_status_t lscp_unmap_midi_instrument
2865    
2866  /**  /**
2867   *  Get the total count of MIDI instrument map entries:   *  Get the total count of MIDI instrument map entries:
2868   *  GET MIDI_INSTRUMENTS   *  GET MIDI_INSTRUMENTS ALL|<midi-map>
2869   *   *
2870   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2871     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2872   *   *
2873   *  @returns The current total number of MIDI instrument map entries   *  @returns The current total number of MIDI instrument map entries
2874   *  on success, -1 otherwise.   *  on success, -1 otherwise.
2875   */   */
2876  int lscp_get_midi_instruments ( lscp_client_t *pClient )  int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2877  {  {
2878          int iInstruments = -1;          int iInstruments = -1;
2879            char szQuery[LSCP_BUFSIZ];
2880    
2881            if (pClient == NULL)
2882                    return -1;
2883    
2884          // Lock this section up.          // Lock this section up.
2885          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2886    
2887          if (lscp_client_call(pClient, "GET MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
2888    
2889            if (iMidiMap < 0)
2890                    strcat(szQuery, "ALL");
2891            else
2892                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2893    
2894            strcat(szQuery, "\r\n");
2895    
2896            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2897                  iInstruments = atoi(lscp_client_get_result(pClient));                  iInstruments = atoi(lscp_client_get_result(pClient));
2898    
2899          // Unlock this section down.          // Unlock this section down.
# Line 1766  int lscp_get_midi_instruments ( lscp_cli Line 2905  int lscp_get_midi_instruments ( lscp_cli
2905    
2906  /**  /**
2907   *  Getting indeces of all MIDI instrument map entries:   *  Getting indeces of all MIDI instrument map entries:
2908   *  LIST MIDI_INSTRUMENTS   *  LIST MIDI_INSTRUMENTS ALL|<midi-map>
2909   *   *
2910   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2911     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2912   *   *
2913   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the
2914   *  {-1,-1,-1} triplet, NULL otherwise.   *  {-1,-1,-1} triplet, NULL otherwise.
2915   */   */
2916  lscp_midi_instrument_t *lscp_list_midi_instruments ( lscp_client_t *pClient )  lscp_midi_instrument_t *lscp_list_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2917  {  {
2918            char szQuery[LSCP_BUFSIZ];
2919    
2920          if (pClient == NULL)          if (pClient == NULL)
2921                  return NULL;                  return NULL;
2922    
# Line 1786  lscp_midi_instrument_t *lscp_list_midi_i Line 2928  lscp_midi_instrument_t *lscp_list_midi_i
2928                  pClient->midi_instruments = NULL;                  pClient->midi_instruments = NULL;
2929          }          }
2930    
2931          if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
2932                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));  
2933            if (iMidiMap < 0)
2934                    strcat(szQuery, "ALL");
2935            else
2936                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2937    
2938            strcat(szQuery, "\r\n");
2939    
2940            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2941                    pClient->midi_instruments = lscp_midi_instruments_create(
2942                            lscp_client_get_result(pClient));
2943    
2944          // Unlock this section down.          // Unlock this section down.
2945          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1798  lscp_midi_instrument_t *lscp_list_midi_i Line 2950  lscp_midi_instrument_t *lscp_list_midi_i
2950    
2951  /**  /**
2952   *  Getting information about a MIDI instrument map entry:   *  Getting information about a MIDI instrument map entry:
2953   *  GET MIDI_INSTRUMENT INFO <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2954   *   *
2955   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2956   *  @param pMidiInstr   MIDI instrument bank and program parameter key.   *  @param pMidiInstr   MIDI instrument bank and program parameter key.
# Line 1807  lscp_midi_instrument_t *lscp_list_midi_i Line 2959  lscp_midi_instrument_t *lscp_list_midi_i
2959   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2960   *  or NULL in case of failure.   *  or NULL in case of failure.
2961   */   */
2962  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,
2963            lscp_midi_instrument_t *pMidiInstr )
2964  {  {
2965          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2966          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1816  lscp_midi_instrument_info_t *lscp_get_mi Line 2969  lscp_midi_instrument_info_t *lscp_get_mi
2969          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2970          char *pszToken;          char *pszToken;
2971          char *pch;          char *pch;
2972            struct _locale_t locale;
2973    
2974          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pClient == NULL)
2975                    return NULL;
2976            if (pMidiInstr->map < 0)
2977                  return NULL;                  return NULL;
2978          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2979                  return NULL;                  return NULL;
2980          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2981                  return NULL;                  return NULL;
2982    
2983          // Lock this section up.          // Lock this section up.
2984          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2985            
2986            _save_and_set_c_locale(&locale);
2987    
2988          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2989          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2990    
2991          sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",          sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2992                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2993          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2994                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
2995                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
# Line 1880  lscp_midi_instrument_info_t *lscp_get_mi Line 3038  lscp_midi_instrument_info_t *lscp_get_mi
3038                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3039                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3040                                  if (pszToken)                                  if (pszToken)
3041                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3042                          }                          }
3043                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3044                  }                  }
3045          }          }
3046          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3047    
3048            _restore_locale(&locale);
3049    
3050          // Unlock this section down.          // Unlock this section down.
3051          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3052    
# Line 1896  lscp_midi_instrument_info_t *lscp_get_mi Line 3056  lscp_midi_instrument_info_t *lscp_get_mi
3056    
3057  /**  /**
3058   *  Clear the MIDI instrumnet map:   *  Clear the MIDI instrumnet map:
3059   *  CLEAR MIDI_INSTRUMENTS   *  CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
3060   *   *
3061   *  @param pClient         Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
3062   *  @param iSamplerChannel  Sampler channel number.   *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
3063   *   *
3064   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
3065   */   */
3066  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient )  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient, int iMidiMap )
3067    {
3068            char szQuery[LSCP_BUFSIZ];
3069    
3070            strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
3071    
3072            if (iMidiMap < 0)
3073                    strcat(szQuery, "ALL");
3074            else
3075                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
3076    
3077            strcat(szQuery, "\r\n");
3078    
3079            return lscp_client_query(pClient, szQuery);
3080    }
3081    
3082    
3083    /**
3084     * Open an instrument editor application for the instrument
3085     * on the given sampler channel:
3086     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3087     *
3088     * @param pClient         Pointer to client instance structure.
3089     * @param iSamplerChannel Sampler Channel.
3090     *
3091     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3092     */
3093    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3094  {  {
3095          return lscp_client_query(pClient, "CLEAR MIDI_INSTRUMENTS\r\n");          char szQuery[LSCP_BUFSIZ];
3096    
3097            if (iSamplerChannel < 0)
3098                    return LSCP_FAILED;
3099    
3100            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3101    
3102            return lscp_client_query(pClient, szQuery);
3103  }  }
3104    
3105    

Legend:
Removed from v.963  
changed lines
  Added in v.3842

  ViewVC Help
Powered by ViewVC