/[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 2424 by capela, Sun Feb 24 19:02:30 2013 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2013, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This library is free software; you can redistribute it and/or     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    
26  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
27  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
28    
29    
30    // Whether to use getaddrinfo() instead
31    // of deprecated gethostbyname()
32    #if !defined(WIN32)
33    #define USE_GETADDRINFO 1
34    #endif
35    
36    
37  // Local prototypes.  // Local prototypes.
38    
39  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
40    
41  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
42  static lscp_status_t    _lscp_client_evt_request    (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);  static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
43            int iSubscribe, lscp_event_t event);
44    
45    
46    //-------------------------------------------------------------------------
47    // General helper functions.
48    
49    struct _locale_t {
50            char numeric[32];
51            char ctype[32];
52    };
53    
54    // we need to ensure a constant locale setting e.g. for parsing
55    // floating point numbers with atof(), as the floating point separator
56    // character varies by the invidual locale settings
57    static void _save_and_set_c_locale(struct _locale_t* locale)
58    {
59            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
60            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
61            setlocale(LC_NUMERIC, "C");
62            setlocale(LC_CTYPE, "C");
63    }
64    
65    // restore the original locale setting as nothing happened
66    static void _restore_locale(struct _locale_t* locale)
67    {
68            setlocale(LC_NUMERIC, locale->numeric);
69            setlocale(LC_CTYPE, locale->ctype);
70    }
71    
72    // seems the standard atof() function doesnt care much about locale
73    // runtime modifications, so we use this workaround
74    static float _atof(const char* txt) {
75            float f;
76            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
77            return f;
78    }
79    
80    
81  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 50  static void _lscp_client_evt_proc ( void Line 94  static void _lscp_client_evt_proc ( void
94          char   achBuffer[LSCP_BUFSIZ];          char   achBuffer[LSCP_BUFSIZ];
95          int    cchBuffer;          int    cchBuffer;
96          const char *pszSeps = ":\r\n";          const char *pszSeps = ":\r\n";
97          char * pszToken;          char  *pszToken;
98          char * pch;          char  *pch;
99          int     cchToken;          int    cchToken;
100    
101          lscp_event_t event;          lscp_event_t event;
102    
103  #ifdef DEBUG  #ifdef DEBUG
# Line 84  static void _lscp_client_evt_proc ( void Line 129  static void _lscp_client_evt_proc ( void
129                          if (cchBuffer > 0) {                          if (cchBuffer > 0) {
130                                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
131                                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
132                                  // Parse for the notification event message...                                  pch = achBuffer;
133                                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
134                                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
135                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
136                                          event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
137                                          // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
138                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
139                                          cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
140                                          // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
141                                          if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
142                                                  // Invoke the client event callback...                                                  // Double-check if we're really up to it...
143                                                  if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
144                                                                  pClient,                                                          // Invoke the client event callback...
145                                                                  event,                                                          if ((*pClient->pfnCallback)(
146                                                                  pszToken,                                                                          pClient,
147                                                                  cchToken,                                                                          event,
148                                                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
149                                                          pClient->evt.iState = 0;                                                                          cchToken,
150                                                                            pClient->pvData) != LSCP_OK) {
151                                                                    pClient->evt.iState = 0;
152                                                            }
153                                                  }                                                  }
154                                          }                                          }
155                                  }                                  } while (*pch);
156                          } else {                          } else {
157                                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
158                                  pClient->evt.iState = 0;                                  pClient->evt.iState = 0;
# Line 146  static lscp_status_t _lscp_client_evt_co Line 194  static lscp_status_t _lscp_client_evt_co
194          }          }
195    
196  #if defined(WIN32)  #if defined(WIN32)
197          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
198                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
199                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
200  #endif  #endif
201    
# Line 174  static lscp_status_t _lscp_client_evt_co Line 223  static lscp_status_t _lscp_client_evt_co
223    
224    
225  // Subscribe to a single event.  // Subscribe to a single event.
226  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
227            int iSubscribe, lscp_event_t event )
228  {  {
229          const char *pszEvent;          const char *pszEvent;
230          char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
# Line 189  static lscp_status_t _lscp_client_evt_re Line 239  static lscp_status_t _lscp_client_evt_re
239                  return LSCP_FAILED;                  return LSCP_FAILED;
240    
241          // Build the query string...          // Build the query string...
242          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
243                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
244          // Just send data, forget result...          // Just send data, forget result...
245          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
246                  lscp_socket_perror("_lscp_client_evt_request: send");                  lscp_socket_perror("_lscp_client_evt_request: send");
# Line 240  const char* lscp_client_build   (void) { Line 291  const char* lscp_client_build   (void) {
291   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
292   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
293   */   */
294  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort,
295            lscp_client_proc_t pfnCallback, void *pvData )
296  {  {
297          lscp_client_t  *pClient;          lscp_client_t  *pClient;
298    #if defined(USE_GETADDRINFO)
299            char szPort[33];
300            struct addrinfo hints;
301            struct addrinfo *result, *res;
302    #else
303          struct hostent *pHost;          struct hostent *pHost;
         lscp_socket_t sock;  
304          struct sockaddr_in addr;          struct sockaddr_in addr;
305          int cAddr;          int cAddr;
306    #endif  /* !USE_GETADDRINFO */
307            lscp_socket_t sock;
308  #if defined(WIN32)  #if defined(WIN32)
309          int iSockOpt = (-1);          int iSockOpt = (-1);
310  #endif  #endif
# Line 256  lscp_client_t* lscp_client_create ( cons Line 314  lscp_client_t* lscp_client_create ( cons
314                  return NULL;                  return NULL;
315          }          }
316    
317    #if defined(USE_GETADDRINFO)
318    
319            // Convert port number to string/name...
320            snprintf(szPort, sizeof(szPort), "%d", iPort);
321    
322            // Obtain address(es) matching host/port...
323            memset(&hints, 0, sizeof(struct addrinfo));
324            hints.ai_family = AF_INET;
325            hints.ai_socktype = SOCK_STREAM;
326    
327            result = NULL;
328    
329            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
330                    lscp_socket_herror("lscp_client_create: getaddrinfo");
331                    return NULL;
332            }
333    
334    #else
335    
336            // Obtain host matching name...
337          pHost = gethostbyname(pszHost);          pHost = gethostbyname(pszHost);
338          if (pHost == NULL) {          if (pHost == NULL) {
339                  lscp_socket_herror("lscp_client_create: gethostbyname");                  lscp_socket_herror("lscp_client_create: gethostbyname");
340                  return NULL;                  return NULL;
341          }          }
342    
343    #endif  /* !USE_GETADDRINFO */
344    
345          // Allocate client descriptor...          // Allocate client descriptor...
346    
347          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));          pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
# Line 275  lscp_client_t* lscp_client_create ( cons Line 355  lscp_client_t* lscp_client_create ( cons
355          pClient->pvData = pvData;          pClient->pvData = pvData;
356    
357  #ifdef DEBUG  #ifdef DEBUG
358          fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
359                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
360                     pClient, pszHost, iPort);
361  #endif  #endif
362    
363          // Prepare the command connection socket...          // Prepare the command connection socket...
364    
365    #if defined(USE_GETADDRINFO)
366    
367            // getaddrinfo() returns a list of address structures;
368            // try each address until we successfully connect(2);
369            // if socket or connect fails, we close the socket and
370            // try the next address...
371            sock = INVALID_SOCKET;
372    
373            for (res = result; res; res = res->ai_next) {
374                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
375                    if (sock == INVALID_SOCKET)
376                            continue;
377            #if defined(WIN32)
378                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
379                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
380                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
381            #endif
382            #ifdef DEBUG
383                    lscp_socket_getopts("lscp_client_create: cmd", sock);
384            #endif
385                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
386                            break;
387                    closesocket(sock);
388            }
389    
390            if (sock == INVALID_SOCKET) {
391                    lscp_socket_perror("lscp_client_create: cmd: socket");
392                    free(pClient);
393                    return NULL;
394            }
395    
396            if (res == NULL) {
397                    lscp_socket_perror("lscp_client_create: cmd: connect");
398                    free(pClient);
399                    return NULL;
400            }
401    
402            // Initialize the command socket agent struct...
403            lscp_socket_agent_init(&(pClient->cmd), sock,
404                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
405    
406            // No longer needed...
407            freeaddrinfo(result);
408    
409    #else
410    
411          sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
412          if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
413                  lscp_socket_perror("lscp_client_create: cmd: socket");                  lscp_socket_perror("lscp_client_create: cmd: socket");
# Line 288  lscp_client_t* lscp_client_create ( cons Line 416  lscp_client_t* lscp_client_create ( cons
416          }          }
417    
418  #if defined(WIN32)  #if defined(WIN32)
419          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
420                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
421                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                  lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
422  #endif  #endif
423    
# Line 312  lscp_client_t* lscp_client_create ( cons Line 441  lscp_client_t* lscp_client_create ( cons
441          // Initialize the command socket agent struct...          // Initialize the command socket agent struct...
442          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
443    
444    #endif  /* !USE_GETADDRINFO */
445    
446  #ifdef DEBUG  #ifdef DEBUG
447          fprintf(stderr, "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->cmd.sock, inet_ntoa(pClient->cmd.addr.sin_addr), ntohs(pClient->cmd.addr.sin_port));          fprintf(stderr,
448                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
449                    pClient, pClient->cmd.sock,
450                    inet_ntoa(pClient->cmd.addr.sin_addr),
451                    ntohs(pClient->cmd.addr.sin_port));
452  #endif  #endif
453    
454          // Initialize the event service socket struct...          // Initialize the event service socket struct...
# Line 327  lscp_client_t* lscp_client_create ( cons Line 462  lscp_client_t* lscp_client_create ( cons
462          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
463          pClient->engines = NULL;          pClient->engines = NULL;
464          pClient->channels = NULL;          pClient->channels = NULL;
465            pClient->fxsends = NULL;
466          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
467            pClient->midi_maps = NULL;
468            pClient->midi_map_name = NULL;
469          lscp_driver_info_init(&(pClient->audio_driver_info));          lscp_driver_info_init(&(pClient->audio_driver_info));
470          lscp_driver_info_init(&(pClient->midi_driver_info));          lscp_driver_info_init(&(pClient->midi_driver_info));
471          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 479  lscp_client_t* lscp_client_create ( cons
479          lscp_server_info_init(&(pClient->server_info));          lscp_server_info_init(&(pClient->server_info));
480          lscp_engine_info_init(&(pClient->engine_info));          lscp_engine_info_init(&(pClient->engine_info));
481          lscp_channel_info_init(&(pClient->channel_info));          lscp_channel_info_init(&(pClient->channel_info));
482            lscp_fxsend_info_init(&(pClient->fxsend_info));
483          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
484          // Initialize error stuff.          // Initialize error stuff.
485          pClient->pszResult = NULL;          pClient->pszResult = NULL;
# Line 403  lscp_status_t lscp_client_destroy ( lscp Line 542  lscp_status_t lscp_client_destroy ( lscp
542    
543          // Free up all cached members.          // Free up all cached members.
544          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
545            lscp_fxsend_info_free(&(pClient->fxsend_info));
546          lscp_channel_info_free(&(pClient->channel_info));          lscp_channel_info_free(&(pClient->channel_info));
547          lscp_engine_info_free(&(pClient->engine_info));          lscp_engine_info_free(&(pClient->engine_info));
548          lscp_server_info_free(&(pClient->server_info));          lscp_server_info_free(&(pClient->server_info));
# Line 423  lscp_status_t lscp_client_destroy ( lscp Line 563  lscp_status_t lscp_client_destroy ( lscp
563          lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->midi_devices);
564          lscp_szsplit_destroy(pClient->engines);          lscp_szsplit_destroy(pClient->engines);
565          lscp_isplit_destroy(pClient->channels);          lscp_isplit_destroy(pClient->channels);
566            lscp_isplit_destroy(pClient->fxsends);
567          lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_midi_instruments_destroy(pClient->midi_instruments);
568            lscp_isplit_destroy(pClient->midi_maps);
569            if (pClient->midi_map_name)
570                    free(pClient->midi_map_name);
571          // Make them null.          // Make them null.
572          pClient->audio_drivers = NULL;          pClient->audio_drivers = NULL;
573          pClient->midi_drivers = NULL;          pClient->midi_drivers = NULL;
# Line 431  lscp_status_t lscp_client_destroy ( lscp Line 575  lscp_status_t lscp_client_destroy ( lscp
575          pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
576          pClient->engines = NULL;          pClient->engines = NULL;
577          pClient->channels = NULL;          pClient->channels = NULL;
578            pClient->fxsends = NULL;
579          pClient->midi_instruments = NULL;          pClient->midi_instruments = NULL;
580            pClient->midi_maps = NULL;
581            pClient->midi_map_name = NULL;
582          // Free result error stuff.          // Free result error stuff.
583          lscp_client_set_result(pClient, NULL, 0);          lscp_client_set_result(pClient, NULL, 0);
584          // Free stream usage stuff.          // Free stream usage stuff.
# Line 512  lscp_status_t lscp_client_query ( lscp_c Line 659  lscp_status_t lscp_client_query ( lscp_c
659  {  {
660          lscp_status_t ret;          lscp_status_t ret;
661    
662            if (pClient == NULL)
663                    return LSCP_FAILED;
664    
665          // Lock this section up.          // Lock this section up.
666          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
667    
# Line 563  int lscp_client_get_errno ( lscp_client_ Line 713  int lscp_client_get_errno ( lscp_client_
713  // Client registration protocol functions.  // Client registration protocol functions.
714    
715  /**  /**
716   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
717   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
718   *      | CHANNEL_INFO | MISCELLANEOUS   *  for @e each event you want to subscribe. That is the old bitflag approach
719     *  was abondoned at this point. You can however still register all older
720     *  events with one lscp_client_subscribe() call at once. Thus, the old
721     *  behavior of this functions was not broken. Those older events are namely:
722     *  @code
723     *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
724     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
725     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
726     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
727     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
728     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
729     *      | MISCELLANEOUS
730     *  @endcode
731     *  The old events occupy the lower 16 bits (as bit flags), and all younger
732     *  events enumerate the whole upper 16 bits range. The new, enumerated
733     *  events are namely:
734     *  @code
735     *  SUBSCRIBE CHANNEL_MIDI
736     *  @endcode
737   *   *
738   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
739   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
740   *   *
741   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
742   */   */
743  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
744  {  {
745          lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
746            lscp_event_t currentEvent;
747    
748          if (pClient == NULL)          if (pClient == NULL)
749                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 597  lscp_status_t lscp_client_subscribe ( ls Line 766  lscp_status_t lscp_client_subscribe ( ls
766                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
767          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
768                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
769            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
770                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
771            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
772                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
773            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
774                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
775            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
776                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
777            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
778                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
779            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
780                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
781            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
782                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
783            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
784                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
785            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
786                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
787          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
788                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
789            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
790            currentEvent = events & 0xffff0000;
791            if (ret == LSCP_OK && currentEvent) {
792                    switch (currentEvent) {
793                            case LSCP_EVENT_CHANNEL_MIDI:
794                            case LSCP_EVENT_DEVICE_MIDI:
795                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
796                                    break;
797                            default: // unknown "upper" event type
798                                    ret = LSCP_FAILED;
799                                    break;
800                    }
801            }
802    
803          // Unlock this section down.          // Unlock this section down.
804          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 608  lscp_status_t lscp_client_subscribe ( ls Line 808  lscp_status_t lscp_client_subscribe ( ls
808    
809    
810  /**  /**
811   *  Deregister frontend from receiving UDP event messages anymore:   *  Deregister frontend from receiving UDP event messages anymore.
812   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call
813   *      | CHANNEL_INFO | MISCELLANEOUS   *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
814     *  That is the old bitflag approach was abondoned at this point. You can
815     *  however still register all older events with one lscp_client_subscribe()
816     *  call at once. Thus, the old behavior of this functions was not broken.
817     *  Those older events are namely:
818     *  @code
819     *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
820     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
821     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
822     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
823     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
824     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
825     *      | MISCELLANEOUS
826     *  @endcode
827     *  The old events occupy the lower 16 bits (as bit flags), and all younger
828     *  events enumerate the whole upper 16 bits range. The new, enumerated
829     *  events are namely:
830     *  @code
831     *  UNSUBSCRIBE CHANNEL_MIDI
832     *  @endcode
833   *   *
834   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
835   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
836   *   *
837   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
838   */   */
839  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
840  {  {
841          lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
842            lscp_event_t currentEvent;
843    
844          if (pClient == NULL)          if (pClient == NULL)
845                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 638  lscp_status_t lscp_client_unsubscribe ( Line 858  lscp_status_t lscp_client_unsubscribe (
858                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
859          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
860                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
861            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
862                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
863            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
864                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
865            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
866                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
867            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
868                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
869            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
870                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
871            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
872                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
873            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
874                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
875            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
876                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
877            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
878                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
879          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
880                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
881            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
882            currentEvent = events & 0xffff0000;
883            if (ret == LSCP_OK && currentEvent) {
884                    switch (currentEvent) {
885                            case LSCP_EVENT_CHANNEL_MIDI:
886                            case LSCP_EVENT_DEVICE_MIDI:
887                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
888                                    break;
889                            default: // unknown "upper" event type
890                                    ret = LSCP_FAILED;
891                                    break;
892                    }
893            }
894    
895          // If necessary, close the alternate connection...          // If necessary, close the alternate connection...
896          if (pClient->events == LSCP_EVENT_NONE)          if (pClient->events == LSCP_EVENT_NONE)
# Line 682  lscp_event_t lscp_client_get_events ( ls Line 933  lscp_event_t lscp_client_get_events ( ls
933   *   *
934   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
935   */   */
936  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient,
937            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
938  {  {
939          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
940    
941          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
942                  return LSCP_FAILED;                  return LSCP_FAILED;
943    
944          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
945                    pszFileName, iInstrIndex, iSamplerChannel);
946          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
947  }  }
948    
# Line 705  lscp_status_t lscp_load_instrument ( lsc Line 958  lscp_status_t lscp_load_instrument ( lsc
958   *   *
959   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
960   */   */
961  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient,
962            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
963  {  {
964          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
965    
966          if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
967                  return LSCP_FAILED;                  return LSCP_FAILED;
968    
969          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n",
970                    pszFileName, iInstrIndex, iSamplerChannel);
971          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
972  }  }
973    
# Line 734  lscp_status_t lscp_load_engine ( lscp_cl Line 989  lscp_status_t lscp_load_engine ( lscp_cl
989          if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
990                  return LSCP_FAILED;                  return LSCP_FAILED;
991    
992          sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
993                    pszEngineName, iSamplerChannel);
994          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
995  }  }
996    
# Line 752  int lscp_get_channels ( lscp_client_t *p Line 1008  int lscp_get_channels ( lscp_client_t *p
1008  {  {
1009          int iChannels = -1;          int iChannels = -1;
1010    
1011            if (pClient == NULL)
1012                    return -1;
1013    
1014          // Lock this section up.          // Lock this section up.
1015          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1016    
# Line 812  int lscp_add_channel ( lscp_client_t *pC Line 1071  int lscp_add_channel ( lscp_client_t *pC
1071  {  {
1072          int iSamplerChannel = -1;          int iSamplerChannel = -1;
1073    
1074            if (pClient == NULL)
1075                    return -1;
1076    
1077          // Lock this section up.          // Lock this section up.
1078          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1079    
# Line 859  int lscp_get_available_engines ( lscp_cl Line 1121  int lscp_get_available_engines ( lscp_cl
1121  {  {
1122          int iAvailableEngines = -1;          int iAvailableEngines = -1;
1123    
1124            if (pClient == NULL)
1125                    return -1;
1126    
1127          // Lock this section up.          // Lock this section up.
1128          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1129    
# Line 885  const char **lscp_list_available_engines Line 1150  const char **lscp_list_available_engines
1150  {  {
1151          const char *pszSeps = ",";          const char *pszSeps = ",";
1152    
1153            if (pClient == NULL)
1154                    return NULL;
1155    
1156          // Lock this section up.          // Lock this section up.
1157          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1158    
# Line 913  const char **lscp_list_available_engines Line 1181  const char **lscp_list_available_engines
1181   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the
1182   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1183   */   */
1184  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient,
1185            const char *pszEngineName )
1186  {  {
1187          lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1188          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 923  lscp_engine_info_t *lscp_get_engine_info Line 1192  lscp_engine_info_t *lscp_get_engine_info
1192          char *pszToken;          char *pszToken;
1193          char *pch;          char *pch;
1194    
1195            if (pClient == NULL)
1196                    return NULL;
1197          if (pszEngineName == NULL)          if (pszEngineName == NULL)
1198                  return NULL;                  return NULL;
1199    
# Line 978  lscp_channel_info_t *lscp_get_channel_in Line 1249  lscp_channel_info_t *lscp_get_channel_in
1249          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1250          char *pszToken;          char *pszToken;
1251          char *pch;          char *pch;
1252            struct _locale_t locale;
1253    
1254            if (pClient == NULL)
1255                    return NULL;
1256          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1257                  return NULL;                  return NULL;
1258    
# Line 988  lscp_channel_info_t *lscp_get_channel_in Line 1262  lscp_channel_info_t *lscp_get_channel_in
1262          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1263          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1264    
1265            _save_and_set_c_locale(&locale);
1266    
1267          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1268          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1269                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1012  lscp_channel_info_t *lscp_get_channel_in Line 1288  lscp_channel_info_t *lscp_get_channel_in
1288                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1289                                  if (pszToken) {                                  if (pszToken) {
1290                                          if (pChannelInfo->audio_routing)                                          if (pChannelInfo->audio_routing)
1291                                                  lscp_szsplit_destroy(pChannelInfo->audio_routing);                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1292                                          pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1293                                  }                                  }
1294                          }                          }
1295                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
# Line 1056  lscp_channel_info_t *lscp_get_channel_in Line 1332  lscp_channel_info_t *lscp_get_channel_in
1332                                                  pChannelInfo->midi_channel = atoi(pszToken);                                                  pChannelInfo->midi_channel = atoi(pszToken);
1333                                  }                                  }
1334                          }                          }
1335                            else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1336                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1337                                    if (pszToken) {
1338                                            pszToken = lscp_ltrim(pszToken);
1339                                            if (strcasecmp(pszToken, "NONE") == 0)
1340                                                    pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1341                                            else
1342                                            if (strcasecmp(pszToken, "DEFAULT") == 0)
1343                                                    pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1344                                            else
1345                                                    pChannelInfo->midi_map = atoi(pszToken);
1346                                    }
1347                            }
1348                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1349                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1350                                  if (pszToken)                                  if (pszToken)
1351                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1352                          }                          }
1353                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1354                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1076  lscp_channel_info_t *lscp_get_channel_in Line 1365  lscp_channel_info_t *lscp_get_channel_in
1365          }          }
1366          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1367    
1368            _restore_locale(&locale);
1369    
1370          // Unlock this section up.          // Unlock this section up.
1371          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1372    
# Line 1097  int lscp_get_channel_voice_count ( lscp_ Line 1388  int lscp_get_channel_voice_count ( lscp_
1388          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1389          int iVoiceCount = -1;          int iVoiceCount = -1;
1390    
1391            if (pClient == NULL)
1392                    return -1;
1393          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1394                  return iVoiceCount;                  return -1;
1395    
1396          // Lock this section up.          // Lock this section up.
1397          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1128  int lscp_get_channel_stream_count ( lscp Line 1421  int lscp_get_channel_stream_count ( lscp
1421          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1422          int iStreamCount = -1;          int iStreamCount = -1;
1423    
1424            if (pClient == NULL)
1425                    return -1;
1426          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1427                  return iStreamCount;                  return -1;
1428    
1429          // Lock this section up.          // Lock this section up.
1430          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1165  int lscp_get_channel_stream_usage ( lscp Line 1460  int lscp_get_channel_stream_usage ( lscp
1460          int   iStream;          int   iStream;
1461          int   iPercent;          int   iPercent;
1462    
1463            if (pClient == NULL)
1464                    return -1;
1465          if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1466                  return iStreamUsage;                  return -1;
1467    
1468          // Lock this section up.          // Lock this section up.
1469          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
# Line 1213  int lscp_get_channel_stream_usage ( lscp Line 1510  int lscp_get_channel_stream_usage ( lscp
1510   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1511   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1512   */   */
1513  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient,
1514            lscp_usage_t usage_type, int iSamplerChannel )
1515  {  {
1516          lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1517          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1227  lscp_buffer_fill_t *lscp_get_channel_buf Line 1525  lscp_buffer_fill_t *lscp_get_channel_buf
1525    
1526          // Retrieve a channel stream estimation.          // Retrieve a channel stream estimation.
1527          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1528          if (pClient->iStreamCount < 0)          if (iStreamCount < 0)
1529                  return NULL;                  return NULL;
1530    
1531          // Lock this section up.          // Lock this section up.
# Line 1286  lscp_buffer_fill_t *lscp_get_channel_buf Line 1584  lscp_buffer_fill_t *lscp_get_channel_buf
1584   *   *
1585   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1586   */   */
1587  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1588            int iSamplerChannel, const char *pszAudioDriver )
1589  {  {
1590          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1591    
1592          if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1593                  return LSCP_FAILED;                  return LSCP_FAILED;
1594    
1595          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1596                    iSamplerChannel, pszAudioDriver);
1597          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1598  }  }
1599    
# Line 1308  lscp_status_t lscp_set_channel_audio_typ Line 1608  lscp_status_t lscp_set_channel_audio_typ
1608   *   *
1609   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1610   */   */
1611  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1612            int iSamplerChannel, int iAudioDevice )
1613  {  {
1614          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1615    
1616          if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1617                  return LSCP_FAILED;                  return LSCP_FAILED;
1618    
1619          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1620                    iSamplerChannel, iAudioDevice);
1621          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1622  }  }
1623    
# Line 1331  lscp_status_t lscp_set_channel_audio_dev Line 1633  lscp_status_t lscp_set_channel_audio_dev
1633   *   *
1634   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1635   */   */
1636  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1637            int iSamplerChannel, int iAudioOut, int iAudioIn )
1638  {  {
1639          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1640    
1641          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1642                  return LSCP_FAILED;                  return LSCP_FAILED;
1643    
1644          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n",
1645                    iSamplerChannel, iAudioOut, iAudioIn);
1646          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1647  }  }
1648    
# Line 1353  lscp_status_t lscp_set_channel_audio_cha Line 1657  lscp_status_t lscp_set_channel_audio_cha
1657   *   *
1658   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1659   */   */
1660  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1661            int iSamplerChannel, const char *pszMidiDriver )
1662  {  {
1663          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1664    
1665          if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1666                  return LSCP_FAILED;                  return LSCP_FAILED;
1667    
1668          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1669                    iSamplerChannel, pszMidiDriver);
1670          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1671  }  }
1672    
# Line 1375  lscp_status_t lscp_set_channel_midi_type Line 1681  lscp_status_t lscp_set_channel_midi_type
1681   *   *
1682   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1683   */   */
1684  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1685            int iSamplerChannel, int iMidiDevice )
1686  {  {
1687          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1688    
1689          if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1690                  return LSCP_FAILED;                  return LSCP_FAILED;
1691    
1692          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1693                    iSamplerChannel, iMidiDevice);
1694          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1695  }  }
1696    
# Line 1397  lscp_status_t lscp_set_channel_midi_devi Line 1705  lscp_status_t lscp_set_channel_midi_devi
1705   *   *
1706   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1707   */   */
1708  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1709            int iSamplerChannel, int iMidiPort )
1710  {  {
1711          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1712    
1713          if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1714                  return LSCP_FAILED;                  return LSCP_FAILED;
1715    
1716          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1717                    iSamplerChannel, iMidiPort);
1718          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1719  }  }
1720    
# Line 1416  lscp_status_t lscp_set_channel_midi_port Line 1726  lscp_status_t lscp_set_channel_midi_port
1726   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
1727   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
1728   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or
1729   *                          LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.   *                          @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1730   *   *
1731   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1732   */   */
1733  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient,
1734            int iSamplerChannel, int iMidiChannel )
1735  {  {
1736          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1737    
# Line 1428  lscp_status_t lscp_set_channel_midi_chan Line 1739  lscp_status_t lscp_set_channel_midi_chan
1739                  return LSCP_FAILED;                  return LSCP_FAILED;
1740    
1741          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1742                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1743                            iSamplerChannel);
1744            else
1745                    sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1746                            iSamplerChannel, iMidiChannel);
1747            return lscp_client_query(pClient, szQuery);
1748    }
1749    
1750    
1751    /**
1752     *  Setting MIDI instrument map:
1753     *  SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1754     *
1755     *  @param pClient          Pointer to client instance structure.
1756     *  @param iSamplerChannel  Sampler channel number.
1757     *  @param iMidiMap         MIDI instrument map number, or either
1758     *                          @ref LSCP_MIDI_MAP_NONE or
1759     *                          @ref LSCP_MIDI_MAP_DEFAULT .
1760     *
1761     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1762     */
1763    lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1764            int iSamplerChannel, int iMidiMap )
1765    {
1766            char szQuery[LSCP_BUFSIZ];
1767    
1768            if (iSamplerChannel < 0)
1769                    return LSCP_FAILED;
1770    
1771            sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1772            if (iMidiMap == LSCP_MIDI_MAP_NONE)
1773                    strcat(szQuery , "NONE");
1774            else
1775            if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1776                    strcat(szQuery , "DEFAULT");
1777          else          else
1778                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);                  sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1779    
1780            strcat(szQuery, "\r\n");
1781    
1782          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1783  }  }
1784    
# Line 1447  lscp_status_t lscp_set_channel_midi_chan Line 1795  lscp_status_t lscp_set_channel_midi_chan
1795   *   *
1796   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1797   */   */
1798  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient,
1799            int iSamplerChannel, float fVolume )
1800  {  {
1801          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1802            struct _locale_t locale;
1803    
1804          if (iSamplerChannel < 0 || fVolume < 0.0)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1805                  return LSCP_FAILED;                  return LSCP_FAILED;
1806    
1807          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1808            sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1809                    iSamplerChannel, fVolume);
1810            _restore_locale(&locale);
1811    
1812          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1813  }  }
1814    
# Line 1471  lscp_status_t lscp_set_channel_volume ( Line 1825  lscp_status_t lscp_set_channel_volume (
1825   *   *
1826   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1827   */   */
1828  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1829            int iSamplerChannel, int iMute )
1830  {  {
1831          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1832    
1833          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1834                  return LSCP_FAILED;                  return LSCP_FAILED;
1835    
1836          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1837                    iSamplerChannel, iMute);
1838          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1839  }  }
1840    
# Line 1495  lscp_status_t lscp_set_channel_mute ( ls Line 1851  lscp_status_t lscp_set_channel_mute ( ls
1851   *   *
1852   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1853   */   */
1854  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient,
1855            int iSamplerChannel, int iSolo )
1856  {  {
1857          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1858    
1859          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1860                  return LSCP_FAILED;                  return LSCP_FAILED;
1861    
1862          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1863                    iSamplerChannel, iSolo);
1864          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1865  }  }
1866    
# Line 1538  lscp_status_t lscp_reset_channel ( lscp_ Line 1896  lscp_status_t lscp_reset_channel ( lscp_
1896   */   */
1897  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1898  {  {
1899            // Do actual whole sampler reset...
1900          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1901  }  }
1902    
# Line 1560  lscp_server_info_t *lscp_get_server_info Line 1919  lscp_server_info_t *lscp_get_server_info
1919          char *pszToken;          char *pszToken;
1920          char *pch;          char *pch;
1921    
1922            if (pClient == NULL)
1923                    return NULL;
1924    
1925          // Lock this section up.          // Lock this section up.
1926          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1927    
# Line 1580  lscp_server_info_t *lscp_get_server_info Line 1942  lscp_server_info_t *lscp_get_server_info
1942                                  if (pszToken)                                  if (pszToken)
1943                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1944                          }                          }
1945                            else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1946                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1947                                    if (pszToken)
1948                                            lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1949                            }
1950                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1951                  }                  }
1952          }          }
# Line 1605  int lscp_get_total_voice_count ( lscp_cl Line 1972  int lscp_get_total_voice_count ( lscp_cl
1972  {  {
1973          int iVoiceCount = -1;          int iVoiceCount = -1;
1974    
1975            if (pClient == NULL)
1976                    return -1;
1977    
1978          // Lock this section up.          // Lock this section up.
1979          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1980    
# Line 1631  int lscp_get_total_voice_count_max ( lsc Line 2001  int lscp_get_total_voice_count_max ( lsc
2001  {  {
2002          int iVoiceCount = -1;          int iVoiceCount = -1;
2003    
2004            if (pClient == NULL)
2005                    return -1;
2006    
2007          // Lock this section up.          // Lock this section up.
2008          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2009    
# Line 1645  int lscp_get_total_voice_count_max ( lsc Line 2018  int lscp_get_total_voice_count_max ( lsc
2018    
2019    
2020  /**  /**
2021     *  Get global volume attenuation:
2022     *  GET VOLUME
2023     *
2024     *  @param pClient  Pointer to client instance structure.
2025     *
2026     *  @returns The global volume as positive floating point value usually in
2027     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2028     */
2029    float lscp_get_volume ( lscp_client_t *pClient )
2030    {
2031            float fVolume = 0.0f;
2032            struct _locale_t locale;
2033    
2034            if (pClient == NULL)
2035                    return 0.0f;
2036    
2037            // Lock this section up.
2038            lscp_mutex_lock(pClient->mutex);
2039    
2040            _save_and_set_c_locale(&locale);
2041    
2042            if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2043                    fVolume = _atof(lscp_client_get_result(pClient));
2044    
2045            _restore_locale(&locale);
2046    
2047            // Unlock this section down.
2048            lscp_mutex_unlock(pClient->mutex);
2049    
2050            return fVolume;
2051    }
2052    
2053    
2054    /**
2055     *  Setting global volume attenuation:
2056     *  SET VOLUME <volume>
2057     *
2058     *  @param pClient  Pointer to client instance structure.
2059     *  @param fVolume  Global volume parameter as positive floating point
2060     *                  value usually be in the range between 0.0 and 1.0,
2061     *                  that is for attenuating the overall volume.
2062     *
2063     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2064     */
2065    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2066    {
2067            char szQuery[LSCP_BUFSIZ];
2068            struct _locale_t locale;
2069    
2070            if (fVolume < 0.0f)
2071                    return LSCP_FAILED;
2072    
2073            _save_and_set_c_locale(&locale);
2074            sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2075            _restore_locale(&locale);
2076    
2077            return lscp_client_query(pClient, szQuery);
2078    }
2079    
2080    
2081    /**
2082     *  Get global voice limit setting:
2083     *  @code
2084     *  GET VOICES
2085     *  @endcode
2086     *  This value reflects the maximum amount of voices a sampler engine
2087     *  processes simultaniously before voice stealing kicks in.
2088     *
2089     *  @param pClient  Pointer to client instance structure.
2090     *
2091     *  @returns The current global maximum amount of voices limit or a
2092     *           negative value on error (e.g. if sampler doesn't support
2093     *           this command).
2094     */
2095    int lscp_get_voices ( lscp_client_t *pClient )
2096    {
2097            int iVoices = -1;
2098    
2099            if (pClient == NULL)
2100                    return -1;
2101    
2102            // Lock this section up.
2103            lscp_mutex_lock(pClient->mutex);
2104    
2105            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2106                    iVoices = atoi(lscp_client_get_result(pClient));
2107    
2108            // Unlock this section down.
2109            lscp_mutex_unlock(pClient->mutex);
2110    
2111            return iVoices;
2112    }
2113    
2114    
2115    /**
2116     *  Setting global voice limit setting:
2117     *  @code
2118     *  SET VOICES <max-voices>
2119     *  @endcode
2120     *  This value reflects the maximum amount of voices a sampler engine
2121     *  processes simultaniously before voice stealing kicks in. Note that
2122     *  this value will be passed to all sampler engine instances, that is
2123     *  the total amount of maximum voices on the running system is thus
2124     *  @param iMaxVoices multiplied with the current amount of sampler
2125     *  engine instances.
2126     *
2127     *  @param pClient     Pointer to client instance structure.
2128     *  @param iMaxVoices  Global voice limit setting as integer value larger
2129     *                     or equal to 1.
2130     *
2131     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2132     */
2133    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2134    {
2135            char szQuery[LSCP_BUFSIZ];
2136    
2137            if (iMaxVoices < 1)
2138                    return LSCP_FAILED;
2139    
2140            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2141            return lscp_client_query(pClient, szQuery);
2142    }
2143    
2144    
2145    /**
2146     *  Get global disk streams limit setting:
2147     *  @code
2148     *  GET STREAMS
2149     *  @endcode
2150     *  This value reflects the maximum amount of disk streams a sampler
2151     *  engine processes simultaniously.
2152     *
2153     *  @param pClient  Pointer to client instance structure.
2154     *
2155     *  @returns The current global maximum amount of disk streams limit
2156     *           or a negative value on error (e.g. if sampler doesn't
2157     *           support this command).
2158     */
2159    int lscp_get_streams ( lscp_client_t *pClient )
2160    {
2161            int iStreams = -1;
2162    
2163            if (pClient == NULL)
2164                    return -1;
2165    
2166            // Lock this section up.
2167            lscp_mutex_lock(pClient->mutex);
2168    
2169            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2170                    iStreams = atoi(lscp_client_get_result(pClient));
2171    
2172            // Unlock this section down.
2173            lscp_mutex_unlock(pClient->mutex);
2174    
2175            return iStreams;
2176    }
2177    
2178    
2179    /**
2180     *  Setting global disk streams limit setting:
2181     *  @code
2182     *  SET STREAMS <max-streams>
2183     *  @endcode
2184     *  This value reflects the maximum amount of dist streams a sampler
2185     *  engine instance processes simultaniously. Note that this value will
2186     *  be passed to all sampler engine instances, that is the total amount
2187     *  of maximum disk streams on the running system is thus
2188     *  @param iMaxStreams multiplied with the current amount of sampler
2189     *  engine instances.
2190     *
2191     *  @param pClient      Pointer to client instance structure.
2192     *  @param iMaxStreams  Global streams limit setting as positive integer
2193     *                      value (larger or equal to 0).
2194     *
2195     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2196     */
2197    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2198    {
2199            char szQuery[LSCP_BUFSIZ];
2200    
2201            if (iMaxStreams < 0)
2202                    return LSCP_FAILED;
2203    
2204            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2205            return lscp_client_query(pClient, szQuery);
2206    }
2207    
2208    
2209    /**
2210     *  Add an effect send to a sampler channel:
2211     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2212     *
2213     *  @param pClient          Pointer to client instance structure.
2214     *  @param iSamplerChannel  Sampler channel number.
2215     *  @param iMidiController  MIDI controller used to alter the effect,
2216     *                          usually a number between 0 and 127.
2217     *  @param pszFxName        Optional name for the effect send entity,
2218     *                          does not have to be unique.
2219     *
2220     *  @returns The new effect send number identifier, or -1 in case of failure.
2221     */
2222    int lscp_create_fxsend ( lscp_client_t *pClient,
2223            int iSamplerChannel, int iMidiController, const char *pszFxName )
2224    {
2225            int iFxSend = -1;
2226            char szQuery[LSCP_BUFSIZ];
2227    
2228            if (pClient == NULL)
2229                    return -1;
2230            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2231                    return -1;
2232    
2233            // Lock this section up.
2234            lscp_mutex_lock(pClient->mutex);
2235    
2236            sprintf(szQuery, "CREATE FX_SEND %d %d",
2237                    iSamplerChannel, iMidiController);
2238    
2239            if (pszFxName)
2240                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2241    
2242            strcat(szQuery, "\r\n");
2243    
2244            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2245                    iFxSend = atoi(lscp_client_get_result(pClient));
2246    
2247            // Unlock this section down.
2248            lscp_mutex_unlock(pClient->mutex);
2249    
2250            return iFxSend;
2251    }
2252    
2253    
2254    /**
2255     *  Remove an effect send from a sampler channel:
2256     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2257     *
2258     *  @param pClient          Pointer to client instance structure.
2259     *  @param iSamplerChannel  Sampler channel number.
2260     *  @param iFxSend          Effect send number.
2261     *
2262     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2263     */
2264    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2265            int iSamplerChannel, int iFxSend )
2266    {
2267            char szQuery[LSCP_BUFSIZ];
2268    
2269            if (iSamplerChannel < 0 || iFxSend < 0)
2270                    return LSCP_FAILED;
2271    
2272            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2273                    iSamplerChannel, iFxSend);
2274    
2275            return lscp_client_query(pClient, szQuery);
2276    }
2277    
2278    
2279    /**
2280     *  Get amount of effect sends on a sampler channel:
2281     *  GET FX_SENDS <sampler-channel>
2282     *
2283     *  @param pClient          Pointer to client instance structure.
2284     *  @param iSamplerChannel  Sampler channel number.
2285     *
2286     *  @returns The current total number of effect sends of the sampler channel
2287     *  on success, -1 otherwise.
2288     */
2289    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2290    {
2291            int iFxSends = -1;
2292            char szQuery[LSCP_BUFSIZ];
2293    
2294            if (pClient == NULL)
2295                    return -1;
2296            if (iSamplerChannel < 0)
2297                    return -1;
2298    
2299            // Lock this section up.
2300            lscp_mutex_lock(pClient->mutex);
2301    
2302            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2303    
2304            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2305                    iFxSends = atoi(lscp_client_get_result(pClient));
2306    
2307            // Unlock this section doen.
2308            lscp_mutex_unlock(pClient->mutex);
2309    
2310            return iFxSends;
2311    }
2312    
2313    
2314    /**
2315     *  List all effect sends on a sampler channel:
2316     *  LIST FX_SENDS <sampler-channel>
2317     *
2318     *  @param pClient          Pointer to client instance structure.
2319     *  @param iSamplerChannel  Sampler channel number.
2320     *
2321     *  @returns An array of the effect sends identifiers as positive integers,
2322     *  terminated with -1 on success, NULL otherwise.
2323     */
2324    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2325    {
2326            const char *pszSeps = ",";
2327            char szQuery[LSCP_BUFSIZ];
2328    
2329            if (pClient == NULL)
2330                    return NULL;
2331    
2332            // Lock this section up.
2333            lscp_mutex_lock(pClient->mutex);
2334    
2335            if (pClient->fxsends) {
2336                    lscp_isplit_destroy(pClient->fxsends);
2337                    pClient->fxsends = NULL;
2338            }
2339    
2340            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2341    
2342            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2343                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2344    
2345            // Unlock this section down.
2346            lscp_mutex_unlock(pClient->mutex);
2347    
2348            return pClient->fxsends;
2349    }
2350    
2351    
2352    /**
2353     *  Getting effect send information
2354     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2355     *
2356     *  @param pClient          Pointer to client instance structure.
2357     *  @param iSamplerChannel  Sampler channel number.
2358     *  @param iFxSend          Effect send number.
2359     *
2360     *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2361     *  information of the given FX send, or NULL in case of failure.
2362     */
2363    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2364            int iSamplerChannel, int iFxSend )
2365    {
2366            lscp_fxsend_info_t *pFxSendInfo;
2367            char szQuery[LSCP_BUFSIZ];
2368            const char *pszResult;
2369            const char *pszSeps = ":";
2370            const char *pszCrlf = "\r\n";
2371            char *pszToken;
2372            char *pch;
2373            struct _locale_t locale;
2374    
2375            if (pClient == NULL)
2376                    return NULL;
2377            if (iSamplerChannel < 0 || iFxSend < 0)
2378                    return NULL;
2379    
2380            // Lock this section up.
2381            lscp_mutex_lock(pClient->mutex);
2382    
2383            _save_and_set_c_locale(&locale);
2384    
2385            pFxSendInfo = &(pClient->fxsend_info);
2386            lscp_fxsend_info_reset(pFxSendInfo);
2387    
2388            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2389            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2390                    pszResult = lscp_client_get_result(pClient);
2391                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2392                    while (pszToken) {
2393                            if (strcasecmp(pszToken, "NAME") == 0) {
2394                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2395                                    if (pszToken)
2396                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2397                            }
2398                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2399                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2400                                    if (pszToken)
2401                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2402                            }
2403                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2404                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2405                                    if (pszToken) {
2406                                            if (pFxSendInfo->audio_routing)
2407                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2408                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2409                                    }
2410                            }
2411                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2412                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2413                                    if (pszToken)
2414                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2415                            }
2416                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2417                    }
2418            }
2419            else pFxSendInfo = NULL;
2420    
2421            _restore_locale(&locale);
2422    
2423            // Unlock this section up.
2424            lscp_mutex_unlock(pClient->mutex);
2425    
2426            return pFxSendInfo;
2427    }
2428    
2429    
2430    /**
2431     *  Alter effect send's name:
2432     *  @code
2433     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2434     *  @endcode
2435     *
2436     *  @param pClient          Pointer to client instance structure.
2437     *  @param iSamplerChannel  Sampler channel number.
2438     *  @param iFxSend          Effect send number.
2439     *  @param pszFxName        Effect send's new name.
2440     *
2441     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2442     */
2443    lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2444            int iSamplerChannel, int iFxSend, const char *pszFxName )
2445    {
2446            char szQuery[LSCP_BUFSIZ];
2447    
2448            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2449                    return LSCP_FAILED;
2450    
2451            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2452                    iSamplerChannel, iFxSend, pszFxName);
2453            return lscp_client_query(pClient, szQuery);
2454    }
2455    
2456    
2457    /**
2458     *  Alter effect send's audio routing:
2459     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2460     *    <audio-src> <audio-dst>
2461     *
2462     *  @param pClient          Pointer to client instance structure.
2463     *  @param iSamplerChannel  Sampler channel number.
2464     *  @param iFxSend          Effect send number.
2465     *  @param iAudioSrc        Audio output device channel to be routed from.
2466     *  @param iAudioDst        Audio output device channel to be routed into.
2467     *
2468     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2469     */
2470    lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2471            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2472    {
2473            char szQuery[LSCP_BUFSIZ];
2474    
2475            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2476                    return LSCP_FAILED;
2477    
2478            sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2479                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2480            return lscp_client_query(pClient, szQuery);
2481    }
2482    
2483    
2484    /**
2485     *  Alter effect send's MIDI controller:
2486     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2487     *
2488     *  @param pClient          Pointer to client instance structure.
2489     *  @param iSamplerChannel  Sampler channel number.
2490     *  @param iFxSend          Effect send number.
2491     *  @param iMidiController  MIDI controller used to alter the effect,
2492     *                          usually a number between 0 and 127.
2493     *
2494     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2495     */
2496    lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2497            int iSamplerChannel, int iFxSend, int iMidiController )
2498    {
2499            char szQuery[LSCP_BUFSIZ];
2500    
2501            if (iSamplerChannel < 0 || iFxSend < 0 ||
2502                    iMidiController < 0 || iMidiController > 127)
2503                    return LSCP_FAILED;
2504    
2505            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2506                    iSamplerChannel, iFxSend, iMidiController);
2507            return lscp_client_query(pClient, szQuery);
2508    }
2509    
2510    
2511    /**
2512     *  Alter effect send's audio level:
2513     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2514     *
2515     *  @param pClient          Pointer to client instance structure.
2516     *  @param iSamplerChannel  Sampler channel number.
2517     *  @param iFxSend          Effect send number.
2518     *  @param fLevel           Effect send volume level.
2519     *
2520     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2521     */
2522    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2523            int iSamplerChannel, int iFxSend, float fLevel )
2524    {
2525            char szQuery[LSCP_BUFSIZ];
2526            struct _locale_t locale;
2527    
2528            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2529                    return LSCP_FAILED;
2530    
2531            _save_and_set_c_locale(&locale);
2532            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2533                    iSamplerChannel, iFxSend, fLevel);
2534            _restore_locale(&locale);
2535    
2536            return lscp_client_query(pClient, szQuery);
2537    }
2538    
2539    
2540    /**
2541     *  Create a new MIDI instrument map:
2542     *  ADD MIDI_INSTRUMENT_MAP [<name>]
2543     *
2544     *  @param pClient      Pointer to client instance structure.
2545     *  @param pszMapName   MIDI instrument map name (optional)
2546     *
2547     *  @returns The new MIDI instrument map number identifier,
2548     *  or -1 in case of failure.
2549     */
2550    int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
2551    {
2552            int iMidiMap = -1;
2553            char szQuery[LSCP_BUFSIZ];
2554    
2555            if (pClient == NULL)
2556                    return -1;
2557    
2558            // Lock this section up.
2559            lscp_mutex_lock(pClient->mutex);
2560    
2561            strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2562    
2563            if (pszMapName)
2564                    sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2565    
2566            strcat(szQuery, "\r\n");
2567    
2568            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2569                    iMidiMap = atoi(lscp_client_get_result(pClient));
2570    
2571            // Unlock this section down.
2572            lscp_mutex_unlock(pClient->mutex);
2573    
2574            return iMidiMap;
2575    }
2576    
2577    
2578    /**
2579     *  Delete one particular or all MIDI instrument maps:
2580     *  REMOVE MIDI_INSTRUMENT_MAP <midi-map>
2581     *
2582     *  @param pClient  Pointer to client instance structure.
2583     *  @param iMidiMap MIDI instrument map number.
2584     *
2585     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2586     */
2587    lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
2588    {
2589            char szQuery[LSCP_BUFSIZ];
2590    
2591            if (iMidiMap < 0)
2592                    return LSCP_FAILED;
2593    
2594            sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
2595    
2596            return lscp_client_query(pClient, szQuery);
2597    }
2598    
2599    
2600    /**
2601     *  Get amount of existing MIDI instrument maps:
2602     *  GET MIDI_INSTRUMENT_MAPS
2603     *
2604     *  @param pClient  Pointer to client instance structure.
2605     *
2606     *  @returns The current total number of MIDI instrument maps
2607     *  on success, -1 otherwise.
2608     */
2609    int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
2610    {
2611            int iMidiMaps = -1;
2612    
2613            if (pClient == NULL)
2614                    return -1;
2615    
2616            // Lock this section up.
2617            lscp_mutex_lock(pClient->mutex);
2618    
2619            if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2620                    iMidiMaps = atoi(lscp_client_get_result(pClient));
2621    
2622            // Unlock this section doen.
2623            lscp_mutex_unlock(pClient->mutex);
2624    
2625            return iMidiMaps;
2626    }
2627    
2628    
2629    /**
2630     *  Getting all created MIDI instrument maps:
2631     *  LIST MIDI_INSTRUMENT_MAPS
2632     *
2633     *  @param pClient  Pointer to client instance structure.
2634     *
2635     *  @returns An array of the MIDI instrument map identifiers as positive
2636     *  integers, terminated with -1 on success, NULL otherwise.
2637     */
2638    int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
2639    {
2640            const char *pszSeps = ",";
2641    
2642            if (pClient == NULL)
2643                    return NULL;
2644    
2645            // Lock this section up.
2646            lscp_mutex_lock(pClient->mutex);
2647    
2648            if (pClient->midi_maps) {
2649                    lscp_isplit_destroy(pClient->midi_maps);
2650                    pClient->midi_maps = NULL;
2651            }
2652    
2653            if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2654                    pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2655    
2656            // Unlock this section down.
2657            lscp_mutex_unlock(pClient->mutex);
2658    
2659            return pClient->midi_maps;
2660    }
2661    
2662    
2663    /**
2664     *  Getting a MIDI instrument map name:
2665     *  GET MIDI_INSTRUMENT_MAP INFO <midi-map>
2666     *
2667     *  @param pClient  Pointer to client instance structure.
2668     *  @param iMidiMap MIDI instrument map number.
2669     *
2670     *  @returns The MIDI instrument map name on success, NULL on failure.
2671     */
2672    const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
2673    {
2674            char szQuery[LSCP_BUFSIZ];
2675            const char *pszResult;
2676            const char *pszSeps = ":";
2677            const char *pszCrlf = "\r\n";
2678            char *pszToken;
2679            char *pch;
2680    
2681            if (pClient == NULL)
2682                    return NULL;
2683            if (iMidiMap < 0)
2684                    return NULL;
2685    
2686            // Lock this section up.
2687            lscp_mutex_lock(pClient->mutex);
2688    
2689            if (pClient->midi_map_name) {
2690                    free(pClient->midi_map_name);
2691                    pClient->midi_map_name = NULL;
2692            }
2693    
2694            sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
2695            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2696                    pszResult = lscp_client_get_result(pClient);
2697                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2698                    while (pszToken) {
2699                            if (strcasecmp(pszToken, "NAME") == 0) {
2700                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2701                                    if (pszToken)
2702                                            lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
2703                            }
2704                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2705                    }
2706            }
2707    
2708            // Unlock this section down.
2709            lscp_mutex_unlock(pClient->mutex);
2710    
2711            return pClient->midi_map_name;
2712    }
2713    
2714    
2715    /**
2716     *  Renaming a MIDI instrument map:
2717     *  SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
2718     *
2719     *  @param pClient      Pointer to client instance structure.
2720     *  @param iMidiMap     MIDI instrument map number.
2721     *  @param pszMapName   MIDI instrument map name.
2722     *
2723     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2724     */
2725    lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
2726    {
2727            char szQuery[LSCP_BUFSIZ];
2728    
2729            if (iMidiMap < 0)
2730                    return LSCP_FAILED;
2731            if (pszMapName == NULL)
2732                    return LSCP_FAILED;
2733    
2734            sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
2735                    iMidiMap, pszMapName);
2736    
2737            return lscp_client_query(pClient, szQuery);
2738    }
2739    
2740    
2741    /**
2742   *  Create or replace a MIDI instrumnet map entry:   *  Create or replace a MIDI instrumnet map entry:
2743   *  MAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2744   *      <engine-name> <filename> <instr-index> <volume> <load-mode> [<name>]   *      <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
2745   *   *
2746   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2747   *  @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 2749  int lscp_get_total_voice_count_max ( lsc
2749   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2750   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2751   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2752   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2753   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2754   *                          1.0 for amplification.   *                          1.0 for amplification.
2755   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 1663  int lscp_get_total_voice_count_max ( lsc Line 2757  int lscp_get_total_voice_count_max ( lsc
2757   *                          @ref LSCP_LOAD_ON_DEMAND, or   *                          @ref LSCP_LOAD_ON_DEMAND, or
2758   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or
2759   *                          @ref LSCP_LOAD_PERSISTENT.   *                          @ref LSCP_LOAD_PERSISTENT.
2760   *  @param pszName          Instrument custom name for the map entry.   *  @param pszName         Instrument custom name for the map entry (optional).
2761   *   *
2762   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2763   */   */
2764  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient,
2765            lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2766            const char *pszFileName, int iInstrIndex, float fVolume,
2767            lscp_load_mode_t load_mode, const char *pszName )
2768  {  {
2769          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2770            struct _locale_t locale;
2771    
2772          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pMidiInstr->map < 0)
2773                  return LSCP_FAILED;                  return LSCP_FAILED;
2774          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2775                  return LSCP_FAILED;                  return LSCP_FAILED;
2776          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2777                  return LSCP_FAILED;                  return LSCP_FAILED;
2778          if (pszEngineName == NULL || pszFileName == NULL)          if (pszEngineName == NULL || pszFileName == NULL)
2779                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 1683  lscp_status_t lscp_map_midi_instrument ( Line 2781  lscp_status_t lscp_map_midi_instrument (
2781          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2782                  fVolume = 1.0f;                  fVolume = 1.0f;
2783    
2784            _save_and_set_c_locale(&locale);
2785          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2786                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2787                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2788            _restore_locale(&locale);
2789    
2790          switch (load_mode) {          switch (load_mode) {
2791          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 1713  lscp_status_t lscp_map_midi_instrument ( Line 2813  lscp_status_t lscp_map_midi_instrument (
2813    
2814  /**  /**
2815   *  Remove an entry from the MIDI instrument map:   *  Remove an entry from the MIDI instrument map:
2816   *  UNMAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2817   *   *
2818   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2819   *  @param pMidiInstr   MIDI instrument bank and program parameter key.   *  @param pMidiInstr   MIDI instrument bank and program parameter key.
2820   *   *
2821   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2822   */   */
2823  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient,
2824            lscp_midi_instrument_t *pMidiInstr )
2825  {  {
2826          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2827    
2828          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pMidiInstr->map < 0)
2829                  return LSCP_FAILED;                  return LSCP_FAILED;
2830          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2831                  return LSCP_FAILED;                  return LSCP_FAILED;
2832          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2833                  return LSCP_FAILED;                  return LSCP_FAILED;
2834    
2835          sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",          sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2836                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2837    
2838          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2839  }  }
# Line 1740  lscp_status_t lscp_unmap_midi_instrument Line 2841  lscp_status_t lscp_unmap_midi_instrument
2841    
2842  /**  /**
2843   *  Get the total count of MIDI instrument map entries:   *  Get the total count of MIDI instrument map entries:
2844   *  GET MIDI_INSTRUMENTS   *  GET MIDI_INSTRUMENTS ALL|<midi-map>
2845   *   *
2846   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2847     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2848   *   *
2849   *  @returns The current total number of MIDI instrument map entries   *  @returns The current total number of MIDI instrument map entries
2850   *  on success, -1 otherwise.   *  on success, -1 otherwise.
2851   */   */
2852  int lscp_get_midi_instruments ( lscp_client_t *pClient )  int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2853  {  {
2854          int iInstruments = -1;          int iInstruments = -1;
2855            char szQuery[LSCP_BUFSIZ];
2856    
2857            if (pClient == NULL)
2858                    return -1;
2859    
2860          // Lock this section up.          // Lock this section up.
2861          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2862    
2863          if (lscp_client_call(pClient, "GET MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
2864    
2865            if (iMidiMap < 0)
2866                    strcat(szQuery, "ALL");
2867            else
2868                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2869    
2870            strcat(szQuery, "\r\n");
2871    
2872            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2873                  iInstruments = atoi(lscp_client_get_result(pClient));                  iInstruments = atoi(lscp_client_get_result(pClient));
2874    
2875          // Unlock this section down.          // Unlock this section down.
# Line 1766  int lscp_get_midi_instruments ( lscp_cli Line 2881  int lscp_get_midi_instruments ( lscp_cli
2881    
2882  /**  /**
2883   *  Getting indeces of all MIDI instrument map entries:   *  Getting indeces of all MIDI instrument map entries:
2884   *  LIST MIDI_INSTRUMENTS   *  LIST MIDI_INSTRUMENTS ALL|<midi-map>
2885   *   *
2886   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2887     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2888   *   *
2889   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the
2890   *  {-1,-1,-1} triplet, NULL otherwise.   *  {-1,-1,-1} triplet, NULL otherwise.
2891   */   */
2892  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 )
2893  {  {
2894            char szQuery[LSCP_BUFSIZ];
2895    
2896          if (pClient == NULL)          if (pClient == NULL)
2897                  return NULL;                  return NULL;
2898    
# Line 1786  lscp_midi_instrument_t *lscp_list_midi_i Line 2904  lscp_midi_instrument_t *lscp_list_midi_i
2904                  pClient->midi_instruments = NULL;                  pClient->midi_instruments = NULL;
2905          }          }
2906    
2907          if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
2908                  pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));  
2909            if (iMidiMap < 0)
2910                    strcat(szQuery, "ALL");
2911            else
2912                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2913    
2914            strcat(szQuery, "\r\n");
2915    
2916            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2917                    pClient->midi_instruments = lscp_midi_instruments_create(
2918                            lscp_client_get_result(pClient));
2919    
2920          // Unlock this section down.          // Unlock this section down.
2921          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1798  lscp_midi_instrument_t *lscp_list_midi_i Line 2926  lscp_midi_instrument_t *lscp_list_midi_i
2926    
2927  /**  /**
2928   *  Getting information about a MIDI instrument map entry:   *  Getting information about a MIDI instrument map entry:
2929   *  GET MIDI_INSTRUMENT INFO <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2930   *   *
2931   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2932   *  @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 2935  lscp_midi_instrument_t *lscp_list_midi_i
2935   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2936   *  or NULL in case of failure.   *  or NULL in case of failure.
2937   */   */
2938  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient,
2939            lscp_midi_instrument_t *pMidiInstr )
2940  {  {
2941          lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2942          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
# Line 1816  lscp_midi_instrument_info_t *lscp_get_mi Line 2945  lscp_midi_instrument_info_t *lscp_get_mi
2945          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2946          char *pszToken;          char *pszToken;
2947          char *pch;          char *pch;
2948            struct _locale_t locale;
2949    
2950          if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pClient == NULL)
2951                    return NULL;
2952            if (pMidiInstr->map < 0)
2953                  return NULL;                  return NULL;
2954          if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2955                  return NULL;                  return NULL;
2956          if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2957                  return NULL;                  return NULL;
2958    
2959          // Lock this section up.          // Lock this section up.
2960          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2961            
2962            _save_and_set_c_locale(&locale);
2963    
2964          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2965          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2966    
2967          sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",          sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2968                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2969          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2970                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
2971                  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 3014  lscp_midi_instrument_info_t *lscp_get_mi
3014                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3015                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3016                                  if (pszToken)                                  if (pszToken)
3017                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3018                          }                          }
3019                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3020                  }                  }
3021          }          }
3022          else pInstrInfo = NULL;          else pInstrInfo = NULL;
3023    
3024            _restore_locale(&locale);
3025    
3026          // Unlock this section down.          // Unlock this section down.
3027          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
3028    
# Line 1896  lscp_midi_instrument_info_t *lscp_get_mi Line 3032  lscp_midi_instrument_info_t *lscp_get_mi
3032    
3033  /**  /**
3034   *  Clear the MIDI instrumnet map:   *  Clear the MIDI instrumnet map:
3035   *  CLEAR MIDI_INSTRUMENTS   *  CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
3036   *   *
3037   *  @param pClient         Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
3038   *  @param iSamplerChannel  Sampler channel number.   *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
3039   *   *
3040   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
3041   */   */
3042  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient )  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient, int iMidiMap )
3043    {
3044            char szQuery[LSCP_BUFSIZ];
3045    
3046            strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
3047    
3048            if (iMidiMap < 0)
3049                    strcat(szQuery, "ALL");
3050            else
3051                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
3052    
3053            strcat(szQuery, "\r\n");
3054    
3055            return lscp_client_query(pClient, szQuery);
3056    }
3057    
3058    
3059    /**
3060     * Open an instrument editor application for the instrument
3061     * on the given sampler channel:
3062     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3063     *
3064     * @param pClient         Pointer to client instance structure.
3065     * @param iSamplerChannel Sampler Channel.
3066     *
3067     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3068     */
3069    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3070  {  {
3071          return lscp_client_query(pClient, "CLEAR MIDI_INSTRUMENTS\r\n");          char szQuery[LSCP_BUFSIZ];
3072    
3073            if (iSamplerChannel < 0)
3074                    return LSCP_FAILED;
3075    
3076            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3077    
3078            return lscp_client_query(pClient, szQuery);
3079  }  }
3080    
3081    

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

  ViewVC Help
Powered by ViewVC