/[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 948 by capela, Tue Nov 28 15:31:20 2006 UTC revision 3664 by schoenebeck, Sun Dec 22 12:53:26 2019 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This library is free software; you can redistribute it and/or     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    #include <sys/time.h>
26    #include <sys/errno.h>
27    
28  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
29  #define LSCP_TIMEOUT_MSECS  500  #define LSCP_TIMEOUT_MSECS  500
30    
31    
32    // Whether to use getaddrinfo() instead
33    // of deprecated gethostbyname()
34    #if !defined(WIN32)
35    #define USE_GETADDRINFO 1
36    #endif
37    
38    
39  // Local prototypes.  // Local prototypes.
40    
41  static void             _lscp_client_evt_proc       (void *pvClient);  static void _lscp_client_evt_proc (void *pvClient);
42    
43  static lscp_status_t    _lscp_client_evt_connect    (lscp_client_t *pClient);  static lscp_status_t _lscp_client_evt_connect (lscp_client_t *pClient);
44  static lscp_status_t    _lscp_client_evt_request    (lscp_client_t *pClient, int iSubscribe, lscp_event_t event);  static lscp_status_t _lscp_client_evt_request (lscp_client_t *pClient,
45            int iSubscribe, lscp_event_t event);
46    
47    
48    //-------------------------------------------------------------------------
49    // General helper functions.
50    
51    struct _locale_t {
52            char numeric[32];
53            char ctype[32];
54    };
55    
56    // we need to ensure a constant locale setting e.g. for parsing
57    // floating point numbers with atof(), as the floating point separator
58    // character varies by the invidual locale settings
59    static void _save_and_set_c_locale(struct _locale_t* locale)
60    {
61            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
62            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
63            setlocale(LC_NUMERIC, "C");
64            setlocale(LC_CTYPE, "C");
65    }
66    
67    // restore the original locale setting as nothing happened
68    static void _restore_locale(struct _locale_t* locale)
69    {
70            setlocale(LC_NUMERIC, locale->numeric);
71            setlocale(LC_CTYPE, locale->ctype);
72    }
73    
74    // seems the standard atof() function doesnt care much about locale
75    // runtime modifications, so we use this workaround
76    static float _atof(const char* txt) {
77            float f;
78            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
79            return f;
80    }
81    
82    
83  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 39  static lscp_status_t    _lscp_client_evt Line 85  static lscp_status_t    _lscp_client_evt
85    
86  static void _lscp_client_evt_proc ( void *pvClient )  static void _lscp_client_evt_proc ( void *pvClient )
87  {  {
88      lscp_client_t *pClient = (lscp_client_t *) pvClient;          lscp_client_t *pClient = (lscp_client_t *) pvClient;
89    
90            fd_set fds;                         // File descriptor list for select().
91            int    fd, fdmax;                   // Maximum file descriptor number.
92            struct timeval tv;                  // For specifying a timeout value.
93            int    iSelect;                     // Holds select return status.
94            int    iTimeout;
95    
96            char   achBuffer[LSCP_BUFSIZ];
97            int    cchBuffer;
98            const char *pszSeps = ":\r\n";
99            char  *pszToken;
100            char  *pch;
101            int    cchToken;
102    
103      fd_set fds;                         // File descriptor list for select().          lscp_event_t event;
     int    fd, fdmax;                   // Maximum file descriptor number.  
     struct timeval tv;                  // For specifying a timeout value.  
     int    iSelect;                     // Holds select return status.  
     int    iTimeout;  
   
     char   achBuffer[LSCP_BUFSIZ];  
     int    cchBuffer;  
     const char *pszSeps = ":\r\n";  
     char * pszToken;  
     char * pch;  
     int     cchToken;  
     lscp_event_t event;  
104    
105  #ifdef DEBUG  #ifdef DEBUG
106      fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");          fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
107  #endif  #endif
108    
109      while (pClient->evt.iState) {          while (pClient->evt.iState) {
110    
111          // Prepare for waiting on select...                  // Prepare for waiting on select...
112          fd = (int) pClient->evt.sock;                  fd = (int) pClient->evt.sock;
113          FD_ZERO(&fds);                  FD_ZERO(&fds);
114          FD_SET((unsigned int) fd, &fds);                  FD_SET((unsigned int) fd, &fds);
115          fdmax = fd;                  fdmax = fd;
116    
117          // Use the timeout (x10) select feature ...                  // Use the timeout (x10) select feature ...
118          iTimeout = 10 * pClient->iTimeout;                  iTimeout = 10 * pClient->iTimeout;
119          if (iTimeout >= 1000) {                  if (iTimeout >= 1000) {
120              tv.tv_sec = iTimeout / 1000;                          tv.tv_sec = iTimeout / 1000;
121              iTimeout -= tv.tv_sec * 1000;                          iTimeout -= tv.tv_sec * 1000;
122          }                  }
123          else tv.tv_sec = 0;                  else tv.tv_sec = 0;
124          tv.tv_usec = iTimeout * 1000;                  tv.tv_usec = iTimeout * 1000;
125    
126          // Wait for event...                  // Wait for event...
127          iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);                  iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
128          if (iSelect > 0 && FD_ISSET(fd, &fds)) {                  if (iSelect > 0 && FD_ISSET(fd, &fds)) {
129              // May recv now...                          // May recv now...
130              cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);                          cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
131              if (cchBuffer > 0) {                          if (cchBuffer > 0) {
132                  // Make sure received buffer it's null terminated.                                  // Make sure received buffer it's null terminated.
133                  achBuffer[cchBuffer] = (char) 0;                                  achBuffer[cchBuffer] = (char) 0;
134                  // Parse for the notification event message...                                  pch = achBuffer;
135                  pszToken = lscp_strtok(achBuffer, pszSeps, &(pch)); // Have "NOTIFY".                                  do {
136                  if (strcasecmp(pszToken, "NOTIFY") == 0) {                                          // Parse for the notification event message...
137                      pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
138                      event    = lscp_event_from_text(pszToken);                                          if (strcasecmp(pszToken, "NOTIFY") == 0) {
139                      // And pick the rest of data...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
140                      pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  event    = lscp_event_from_text(pszToken);
141                      cchToken = (pszToken == NULL ? 0 : strlen(pszToken));                                                  // And pick the rest of data...
142                      // Double-check if we're really up to it...                                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
143                      if (pClient->events & event) {                                                  cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
144                          // Invoke the client event callback...                                                  // Double-check if we're really up to it...
145                          if ((*pClient->pfnCallback)(                                                  if (pClient->events & event) {
146                                  pClient,                                                          // Invoke the client event callback...
147                                  event,                                                          if ((*pClient->pfnCallback)(
148                                  pszToken,                                                                          pClient,
149                                  cchToken,                                                                          event,
150                                  pClient->pvData) != LSCP_OK) {                                                                          pszToken,
151                              pClient->evt.iState = 0;                                                                          cchToken,
152                          }                                                                          pClient->pvData) != LSCP_OK) {
153                      }                                                                  pClient->evt.iState = 0;
154                  }                                                          }
155              } else {                                                  }
156                  lscp_socket_perror("_lscp_client_evt_proc: recv");                                          }
157                  pClient->evt.iState = 0;                                  } while (*pch);
158              }                          } else {
159          }   // Check if select has in error.                                  lscp_socket_perror("_lscp_client_evt_proc: recv");
160          else if (iSelect < 0) {                                  pClient->evt.iState = 0;
161              lscp_socket_perror("_lscp_client_evt_proc: select");                                  pClient->iErrno = -errno;
162              pClient->evt.iState = 0;                          }
163          }                  }   // Check if select has in error.
164                    else if (iSelect < 0) {
165          // Finally, always signal the event.                          lscp_socket_perror("_lscp_client_evt_proc: select");
166          lscp_cond_signal(pClient->cond);                          pClient->evt.iState = 0;
167      }                          pClient->iErrno = -errno;
168                    }
169    
170                    // Finally, always signal the event.
171                    lscp_cond_signal(pClient->cond);
172            }
173    
174  #ifdef DEBUG  #ifdef DEBUG
175      fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");          fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
176  #endif  #endif
177  }  }
178    
# Line 131  static void _lscp_client_evt_proc ( void Line 183  static void _lscp_client_evt_proc ( void
183  // Open the event service socket connection.  // Open the event service socket connection.
184  static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )  static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
185  {  {
186      lscp_socket_t sock;          lscp_socket_t sock;
187      struct sockaddr_in addr;          struct sockaddr_in addr;
188      int cAddr;          int cAddr;
189  #if defined(WIN32)  #if defined(WIN32)
190      int iSockOpt = (-1);          int iSockOpt = (-1);
191  #endif  #endif
192    
193      // Prepare the event connection socket...          // Prepare the event connection socket...
194      sock = socket(AF_INET, SOCK_STREAM, 0);          sock = socket(AF_INET, SOCK_STREAM, 0);
195      if (sock == INVALID_SOCKET) {          if (sock == INVALID_SOCKET) {
196          lscp_socket_perror("_lscp_client_evt_connect: socket");                  lscp_socket_perror("_lscp_client_evt_connect: socket");
197          return LSCP_FAILED;                  return LSCP_FAILED;
198      }          }
199    
200  #if defined(WIN32)  #if defined(WIN32)
201      if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
202          lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");                          (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
203                    lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
204  #endif  #endif
205    
206  #ifdef DEBUG  #ifdef DEBUG
207      lscp_socket_getopts("_lscp_client_evt_connect:", sock);          lscp_socket_getopts("_lscp_client_evt_connect:", sock);
208  #endif  #endif
209    
210      // Use same address of the command connection.          // Use same address of the command connection.
211      cAddr = sizeof(struct sockaddr_in);          cAddr = sizeof(struct sockaddr_in);
212      memmove((char *) &addr, &(pClient->cmd.addr), cAddr);          memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
213    
214      // Start the connection...          // Start the connection...
215      if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {          if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
216          lscp_socket_perror("_lscp_client_evt_connect: connect");                  lscp_socket_perror("_lscp_client_evt_connect: connect");
217          closesocket(sock);                  closesocket(sock);
218          return LSCP_FAILED;                  return LSCP_FAILED;
219      }          }
220    
221      // Set our socket agent struct...          // Set our socket agent struct...
222      lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);          lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
223    
224      // And finally the service thread...          // And finally the service thread...
225      return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);          return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
226  }  }
227    
228    
229  // Subscribe to a single event.  // Subscribe to a single event.
230  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient, int iSubscribe, lscp_event_t event )  static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
231            int iSubscribe, lscp_event_t event )
232  {  {
233      const char *pszEvent;          const char *pszEvent;
234      char  szQuery[LSCP_BUFSIZ];          char  szQuery[LSCP_BUFSIZ];
235      int   cchQuery;          int   cchQuery;
236    
237      if (pClient == NULL)          if (pClient == NULL)
238          return LSCP_FAILED;                  return LSCP_FAILED;
239    
240      // Which (single) event?          // Which (single) event?
241      pszEvent = lscp_event_to_text(event);          pszEvent = lscp_event_to_text(event);
242      if (pszEvent == NULL)          if (pszEvent == NULL)
243          return LSCP_FAILED;                  return LSCP_FAILED;
244    
245      // Build the query string...          // Build the query string...
246      cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n", (iSubscribe == 0 ? "UN" : ""), pszEvent);          cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
247      // Just send data, forget result...                  (iSubscribe == 0 ? "UN" : ""), pszEvent);
248      if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {          // Just send data, forget result...
249          lscp_socket_perror("_lscp_client_evt_request: send");          if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
250          return LSCP_FAILED;                  lscp_socket_perror("_lscp_client_evt_request: send");
251      }                  return LSCP_FAILED;
252            }
253      // Wait on response.  
254      lscp_cond_wait(pClient->cond, pClient->mutex);          // Wait on response.
255            lscp_cond_wait(pClient->cond, pClient->mutex);
256      // Update as naively as we can...  
257      if (iSubscribe)          // Update as naively as we can...
258          pClient->events |=  event;          if (iSubscribe)
259      else                  pClient->events |=  event;
260          pClient->events &= ~event;          else
261                    pClient->events &= ~event;
262    
263      return LSCP_OK;          return LSCP_OK;
264  }  }
265    
266    
# Line 219  const char* lscp_client_package (void) { Line 274  const char* lscp_client_package (void) {
274  /** Retrieve the current client library version string. */  /** Retrieve the current client library version string. */
275  const char* lscp_client_version (void) { return LSCP_VERSION; }  const char* lscp_client_version (void) { return LSCP_VERSION; }
276    
277  /** Retrieve the current client library build timestamp string. */  /** Retrieve the current client library build string. */
278  const char* lscp_client_build   (void) { return __DATE__ " " __TIME__; }  const char* lscp_client_build   (void) { return LSCP_BUILD; }
279    
280    
281  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
# Line 240  const char* lscp_client_build   (void) { Line 295  const char* lscp_client_build   (void) {
295   *  @returns The new client instance pointer if successfull, which shall be   *  @returns The new client instance pointer if successfull, which shall be
296   *  used on all subsequent client calls, NULL otherwise.   *  used on all subsequent client calls, NULL otherwise.
297   */   */
298  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort, lscp_client_proc_t pfnCallback, void *pvData )  lscp_client_t* lscp_client_create ( const char *pszHost, int iPort,
299            lscp_client_proc_t pfnCallback, void *pvData )
300  {  {
301      lscp_client_t  *pClient;          lscp_client_t  *pClient;
302      struct hostent *pHost;  #if defined(USE_GETADDRINFO)
303      lscp_socket_t sock;          char szPort[33];
304      struct sockaddr_in addr;          struct addrinfo hints;
305      int cAddr;          struct addrinfo *result, *res;
306    #else
307            struct hostent *pHost;
308            struct sockaddr_in addr;
309            int cAddr;
310    #endif  /* !USE_GETADDRINFO */
311            lscp_socket_t sock;
312  #if defined(WIN32)  #if defined(WIN32)
313      int iSockOpt = (-1);          int iSockOpt = (-1);
314  #endif  #endif
315    
316      if (pfnCallback == NULL) {          if (pfnCallback == NULL) {
317          fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");                  fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
318          return NULL;                  return NULL;
319      }          }
320    
321      pHost = gethostbyname(pszHost);  #if defined(USE_GETADDRINFO)
322      if (pHost == NULL) {  
323          lscp_socket_herror("lscp_client_create: gethostbyname");          // Convert port number to string/name...
324          return NULL;          snprintf(szPort, sizeof(szPort), "%d", iPort);
325      }  
326            // Obtain address(es) matching host/port...
327      // Allocate client descriptor...          memset(&hints, 0, sizeof(struct addrinfo));
328            hints.ai_family = AF_INET;
329      pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));          hints.ai_socktype = SOCK_STREAM;
330      if (pClient == NULL) {  
331          fprintf(stderr, "lscp_client_create: Out of memory.\n");          result = NULL;
332          return NULL;  
333      }          if (getaddrinfo(pszHost, szPort, &hints, &result)) {
334      memset(pClient, 0, sizeof(lscp_client_t));                  lscp_socket_herror("lscp_client_create: getaddrinfo");
335                    return NULL;
336            }
337    
338    #else
339    
340            // Obtain host matching name...
341            pHost = gethostbyname(pszHost);
342            if (pHost == NULL) {
343                    lscp_socket_herror("lscp_client_create: gethostbyname");
344                    return NULL;
345            }
346    
347    #endif  /* !USE_GETADDRINFO */
348    
349            // Allocate client descriptor...
350    
351            pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));
352            if (pClient == NULL) {
353                    fprintf(stderr, "lscp_client_create: Out of memory.\n");
354                    return NULL;
355            }
356            memset(pClient, 0, sizeof(lscp_client_t));
357    
358      pClient->pfnCallback = pfnCallback;          pClient->pfnCallback = pfnCallback;
359      pClient->pvData = pvData;          pClient->pvData = pvData;
360    
361  #ifdef DEBUG  #ifdef DEBUG
362      fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);          fprintf(stderr,
363                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
364                     pClient, pszHost, iPort);
365  #endif  #endif
366    
367      // Prepare the command connection socket...          // Prepare the command connection socket...
368    
369      sock = socket(AF_INET, SOCK_STREAM, 0);  #if defined(USE_GETADDRINFO)
370      if (sock == INVALID_SOCKET) {  
371          lscp_socket_perror("lscp_client_create: cmd: socket");          // getaddrinfo() returns a list of address structures;
372          free(pClient);          // try each address until we successfully connect(2);
373          return NULL;          // if socket or connect fails, we close the socket and
374      }          // try the next address...
375            sock = INVALID_SOCKET;
376    
377            for (res = result; res; res = res->ai_next) {
378                    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
379                    if (sock == INVALID_SOCKET)
380                            continue;
381            #if defined(WIN32)
382                    if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
383                                    (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
384                            lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
385            #endif
386            #ifdef DEBUG
387                    lscp_socket_getopts("lscp_client_create: cmd", sock);
388            #endif
389                    if (connect(sock, res->ai_addr, res->ai_addrlen) != SOCKET_ERROR)
390                            break;
391                    closesocket(sock);
392            }
393    
394            if (sock == INVALID_SOCKET) {
395                    lscp_socket_perror("lscp_client_create: cmd: socket");
396                    free(pClient);
397                    return NULL;
398            }
399    
400            if (res == NULL) {
401                    lscp_socket_perror("lscp_client_create: cmd: connect");
402                    free(pClient);
403                    return NULL;
404            }
405    
406            // Initialize the command socket agent struct...
407            lscp_socket_agent_init(&(pClient->cmd), sock,
408                    (struct sockaddr_in *) res->ai_addr, res->ai_addrlen);
409    
410            // No longer needed...
411            freeaddrinfo(result);
412    
413    #else
414    
415            sock = socket(AF_INET, SOCK_STREAM, 0);
416            if (sock == INVALID_SOCKET) {
417                    lscp_socket_perror("lscp_client_create: cmd: socket");
418                    free(pClient);
419                    return NULL;
420            }
421    
422  #if defined(WIN32)  #if defined(WIN32)
423      if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
424          lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");                          (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
425                    lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
426  #endif  #endif
427    
428  #ifdef DEBUG  #ifdef DEBUG
429      lscp_socket_getopts("lscp_client_create: cmd", sock);          lscp_socket_getopts("lscp_client_create: cmd", sock);
430  #endif  #endif
431    
432      cAddr = sizeof(struct sockaddr_in);          cAddr = sizeof(struct sockaddr_in);
433      memset((char *) &addr, 0, cAddr);          memset((char *) &addr, 0, cAddr);
434      addr.sin_family = pHost->h_addrtype;          addr.sin_family = pHost->h_addrtype;
435      memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);          memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
436      addr.sin_port = htons((short) iPort);          addr.sin_port = htons((short) iPort);
437    
438      if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {          if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
439          lscp_socket_perror("lscp_client_create: cmd: connect");                  lscp_socket_perror("lscp_client_create: cmd: connect");
440          closesocket(sock);                  closesocket(sock);
441          free(pClient);                  free(pClient);
442          return NULL;                  return NULL;
443      }          }
444    
445            // Initialize the command socket agent struct...
446            lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
447    
448      // Initialize the command socket agent struct...  #endif  /* !USE_GETADDRINFO */
     lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);  
449    
450  #ifdef DEBUG  #ifdef DEBUG
451      fprintf(stderr, "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->cmd.sock, inet_ntoa(pClient->cmd.addr.sin_addr), ntohs(pClient->cmd.addr.sin_port));          fprintf(stderr,
452                    "lscp_client_create: cmd: pClient=%p: sock=%d addr=%s port=%d.\n",
453                    pClient, pClient->cmd.sock,
454                    inet_ntoa(pClient->cmd.addr.sin_addr),
455                    ntohs(pClient->cmd.addr.sin_port));
456  #endif  #endif
457    
458      // Initialize the event service socket struct...          // Initialize the event service socket struct...
459      lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);          lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
460      // No events subscribed, yet.          // No events subscribed, yet.
461      pClient->events = LSCP_EVENT_NONE;          pClient->events = LSCP_EVENT_NONE;
462      // Initialize cached members.          // Initialize cached members.
463      pClient->audio_drivers = NULL;          pClient->audio_drivers = NULL;
464      pClient->midi_drivers = NULL;          pClient->midi_drivers = NULL;
465      pClient->audio_devices = NULL;          pClient->audio_devices = NULL;
466      pClient->midi_devices = NULL;          pClient->midi_devices = NULL;
467      pClient->engines = NULL;          pClient->engines = NULL;
468      pClient->channels = NULL;          pClient->channels = NULL;
469      pClient->midi_instruments = NULL;          pClient->fxsends = NULL;
470      lscp_driver_info_init(&(pClient->audio_driver_info));          pClient->midi_instruments = NULL;
471      lscp_driver_info_init(&(pClient->midi_driver_info));          pClient->midi_maps = NULL;
472      lscp_device_info_init(&(pClient->audio_device_info));          pClient->midi_map_name = NULL;
473      lscp_device_info_init(&(pClient->midi_device_info));          lscp_driver_info_init(&(pClient->audio_driver_info));
474      lscp_param_info_init(&(pClient->audio_param_info));          lscp_driver_info_init(&(pClient->midi_driver_info));
475      lscp_param_info_init(&(pClient->midi_param_info));          lscp_device_info_init(&(pClient->audio_device_info));
476      lscp_device_port_info_init(&(pClient->audio_channel_info));          lscp_device_info_init(&(pClient->midi_device_info));
477      lscp_device_port_info_init(&(pClient->midi_port_info));          lscp_param_info_init(&(pClient->audio_param_info));
478      lscp_param_info_init(&(pClient->audio_channel_param_info));          lscp_param_info_init(&(pClient->midi_param_info));
479      lscp_param_info_init(&(pClient->midi_port_param_info));          lscp_device_port_info_init(&(pClient->audio_channel_info));
480      lscp_server_info_init(&(pClient->server_info));          lscp_device_port_info_init(&(pClient->midi_port_info));
481      lscp_engine_info_init(&(pClient->engine_info));          lscp_param_info_init(&(pClient->audio_channel_param_info));
482      lscp_channel_info_init(&(pClient->channel_info));          lscp_param_info_init(&(pClient->midi_port_param_info));
483      lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));          lscp_server_info_init(&(pClient->server_info));
484      // Initialize error stuff.          lscp_engine_info_init(&(pClient->engine_info));
485      pClient->pszResult = NULL;          lscp_channel_info_init(&(pClient->channel_info));
486      pClient->iErrno = -1;          lscp_fxsend_info_init(&(pClient->fxsend_info));
487      // Stream usage stuff.          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
488      pClient->buffer_fill = NULL;          // Initialize error stuff.
489      pClient->iStreamCount = 0;          pClient->pszResult = NULL;
490      // Default timeout value.          pClient->iErrno = -1;
491      pClient->iTimeout = LSCP_TIMEOUT_MSECS;          // Stream usage stuff.
492            pClient->buffer_fill = NULL;
493            pClient->iStreamCount = 0;
494            // Default timeout value.
495            pClient->iTimeout = LSCP_TIMEOUT_MSECS;
496          pClient->iTimeoutCount = 0;          pClient->iTimeoutCount = 0;
497    
498      // Initialize the transaction mutex.          // Initialize the transaction mutex.
499      lscp_mutex_init(pClient->mutex);          lscp_mutex_init(pClient->mutex);
500      lscp_cond_init(pClient->cond);          lscp_cond_init(pClient->cond);
501    
502      // Finally we've some success...          // Finally we've some success...
503      return pClient;          return pClient;
504  }  }
505    
506    
# Line 368  lscp_client_t* lscp_client_create ( cons Line 511  lscp_client_t* lscp_client_create ( cons
511   */   */
512  lscp_status_t lscp_client_join ( lscp_client_t *pClient )  lscp_status_t lscp_client_join ( lscp_client_t *pClient )
513  {  {
514      if (pClient == NULL)          if (pClient == NULL)
515          return LSCP_FAILED;                  return LSCP_FAILED;
516    
517  #ifdef DEBUG  #ifdef DEBUG
518      fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);          fprintf(stderr, "lscp_client_join: pClient=%p.\n", pClient);
519  #endif  #endif
520    
521  //  lscp_socket_agent_join(&(pClient->evt));  //  lscp_socket_agent_join(&(pClient->evt));
522      lscp_socket_agent_join(&(pClient->cmd));          lscp_socket_agent_join(&(pClient->cmd));
523    
524      return LSCP_OK;          return LSCP_OK;
525  }  }
526    
527    
# Line 391  lscp_status_t lscp_client_join ( lscp_cl Line 534  lscp_status_t lscp_client_join ( lscp_cl
534   */   */
535  lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )  lscp_status_t lscp_client_destroy ( lscp_client_t *pClient )
536  {  {
537      if (pClient == NULL)          if (pClient == NULL)
538          return LSCP_FAILED;                  return LSCP_FAILED;
539    
540  #ifdef DEBUG  #ifdef DEBUG
541      fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);          fprintf(stderr, "lscp_client_destroy: pClient=%p.\n", pClient);
542  #endif  #endif
543    
544      // Lock this section up.          // Lock this section up.
545      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
546    
547      // Free up all cached members.          // Free up all cached members.
548      lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));          lscp_midi_instrument_info_free(&(pClient->midi_instrument_info));
549      lscp_channel_info_free(&(pClient->channel_info));          lscp_fxsend_info_free(&(pClient->fxsend_info));
550      lscp_engine_info_free(&(pClient->engine_info));          lscp_channel_info_free(&(pClient->channel_info));
551      lscp_server_info_free(&(pClient->server_info));          lscp_engine_info_free(&(pClient->engine_info));
552      lscp_param_info_free(&(pClient->midi_port_param_info));          lscp_server_info_free(&(pClient->server_info));
553      lscp_param_info_free(&(pClient->audio_channel_param_info));          lscp_param_info_free(&(pClient->midi_port_param_info));
554      lscp_device_port_info_free(&(pClient->midi_port_info));          lscp_param_info_free(&(pClient->audio_channel_param_info));
555      lscp_device_port_info_free(&(pClient->audio_channel_info));          lscp_device_port_info_free(&(pClient->midi_port_info));
556      lscp_param_info_free(&(pClient->midi_param_info));          lscp_device_port_info_free(&(pClient->audio_channel_info));
557      lscp_param_info_free(&(pClient->audio_param_info));          lscp_param_info_free(&(pClient->midi_param_info));
558      lscp_device_info_free(&(pClient->midi_device_info));          lscp_param_info_free(&(pClient->audio_param_info));
559      lscp_device_info_free(&(pClient->audio_device_info));          lscp_device_info_free(&(pClient->midi_device_info));
560      lscp_driver_info_free(&(pClient->midi_driver_info));          lscp_device_info_free(&(pClient->audio_device_info));
561      lscp_driver_info_free(&(pClient->audio_driver_info));          lscp_driver_info_free(&(pClient->midi_driver_info));
562      // Free available engine table.          lscp_driver_info_free(&(pClient->audio_driver_info));
563      lscp_szsplit_destroy(pClient->audio_drivers);          // Free available engine table.
564      lscp_szsplit_destroy(pClient->midi_drivers);          lscp_szsplit_destroy(pClient->audio_drivers);
565      lscp_isplit_destroy(pClient->audio_devices);          lscp_szsplit_destroy(pClient->midi_drivers);
566      lscp_isplit_destroy(pClient->midi_devices);          lscp_isplit_destroy(pClient->audio_devices);
567      lscp_szsplit_destroy(pClient->engines);          lscp_isplit_destroy(pClient->midi_devices);
568      lscp_isplit_destroy(pClient->channels);          lscp_szsplit_destroy(pClient->engines);
569      lscp_midi_instruments_destroy(pClient->midi_instruments);          lscp_isplit_destroy(pClient->channels);
570      // Make them null.          lscp_isplit_destroy(pClient->fxsends);
571      pClient->audio_drivers = NULL;          lscp_midi_instruments_destroy(pClient->midi_instruments);
572      pClient->midi_drivers = NULL;          lscp_isplit_destroy(pClient->midi_maps);
573      pClient->audio_devices = NULL;          if (pClient->midi_map_name)
574      pClient->midi_devices = NULL;                  free(pClient->midi_map_name);
575      pClient->engines = NULL;          // Make them null.
576      pClient->channels = NULL;          pClient->audio_drivers = NULL;
577      pClient->midi_instruments = NULL;          pClient->midi_drivers = NULL;
578      // Free result error stuff.          pClient->audio_devices = NULL;
579      lscp_client_set_result(pClient, NULL, 0);          pClient->midi_devices = NULL;
580      // Free stream usage stuff.          pClient->engines = NULL;
581      if (pClient->buffer_fill)          pClient->channels = NULL;
582          free(pClient->buffer_fill);          pClient->fxsends = NULL;
583      pClient->buffer_fill = NULL;          pClient->midi_instruments = NULL;
584      pClient->iStreamCount = 0;          pClient->midi_maps = NULL;
585      pClient->iTimeout = 0;          pClient->midi_map_name = NULL;
586            // Free result error stuff.
587      // Free socket agents.          lscp_client_set_result(pClient, NULL, 0);
588      lscp_socket_agent_free(&(pClient->evt));          // Free stream usage stuff.
589      lscp_socket_agent_free(&(pClient->cmd));          if (pClient->buffer_fill)
590                    free(pClient->buffer_fill);
591      // Last but not least, free good ol'transaction mutex.          pClient->buffer_fill = NULL;
592      lscp_mutex_unlock(pClient->mutex);          pClient->iStreamCount = 0;
593      lscp_mutex_destroy(pClient->mutex);          pClient->iTimeout = 0;
594      lscp_cond_destroy(pClient->cond);  
595            // Free socket agents.
596            lscp_socket_agent_free(&(pClient->evt));
597            lscp_socket_agent_free(&(pClient->cmd));
598    
599            // Last but not least, free good ol'transaction mutex.
600            lscp_mutex_unlock(pClient->mutex);
601            lscp_mutex_destroy(pClient->mutex);
602            lscp_cond_destroy(pClient->cond);
603    
604      free(pClient);          free(pClient);
605    
606      return LSCP_OK;          return LSCP_OK;
607  }  }
608    
609    
# Line 466  lscp_status_t lscp_client_destroy ( lscp Line 617  lscp_status_t lscp_client_destroy ( lscp
617   */   */
618  lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )  lscp_status_t lscp_client_set_timeout ( lscp_client_t *pClient, int iTimeout )
619  {  {
620      if (pClient == NULL)          if (pClient == NULL)
621          return LSCP_FAILED;                  return LSCP_FAILED;
622      if (iTimeout < 0)          if (iTimeout < 0)
623          return LSCP_FAILED;                  return LSCP_FAILED;
624    
625      pClient->iTimeout = iTimeout;          pClient->iTimeout = iTimeout;
626      return LSCP_OK;          return LSCP_OK;
627  }  }
628    
629    
# Line 485  lscp_status_t lscp_client_set_timeout ( Line 636  lscp_status_t lscp_client_set_timeout (
636   */   */
637  int lscp_client_get_timeout ( lscp_client_t *pClient )  int lscp_client_get_timeout ( lscp_client_t *pClient )
638  {  {
639      if (pClient == NULL)          if (pClient == NULL)
640          return -1;                  return -1;
641    
642      return pClient->iTimeout;          return pClient->iTimeout;
643    }
644    
645    /**
646     *  Check whether connection to server is lost.
647     *
648     *  @param pClient  Pointer to client instance structure.
649     *
650     *  @returns @c true if client lost connection to server, @c false otherwise.
651     */
652    bool lscp_client_connection_lost ( lscp_client_t *pClient )
653    {
654        int err = lscp_client_get_errno(pClient);
655        if (err >= 0) return false;
656        return err == -EPIPE || err == -ECONNRESET || err == -ECONNABORTED;
657  }  }
658    
659    
# Line 510  int lscp_client_get_timeout ( lscp_clien Line 675  int lscp_client_get_timeout ( lscp_clien
675   */   */
676  lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )  lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery )
677  {  {
678      lscp_status_t ret;          lscp_status_t ret;
679    
680            if (pClient == NULL)
681                    return LSCP_FAILED;
682    
683      // Lock this section up.          // Lock this section up.
684      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
685    
686      // Just make the now guarded call.          // Just make the now guarded call.
687      ret = lscp_client_call(pClient, pszQuery, 0);          ret = lscp_client_call(pClient, pszQuery, 0);
688    
689      // Unlock this section down.          // Unlock this section down.
690      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
691    
692      return ret;          return ret;
693  }  }
694    
695  /**  /**
# Line 535  lscp_status_t lscp_client_query ( lscp_c Line 703  lscp_status_t lscp_client_query ( lscp_c
703   */   */
704  const char *lscp_client_get_result ( lscp_client_t *pClient )  const char *lscp_client_get_result ( lscp_client_t *pClient )
705  {  {
706      if (pClient == NULL)          if (pClient == NULL)
707          return NULL;                  return NULL;
708    
709      return pClient->pszResult;          return pClient->pszResult;
710  }  }
711    
712    
# Line 552  const char *lscp_client_get_result ( lsc Line 720  const char *lscp_client_get_result ( lsc
720   */   */
721  int lscp_client_get_errno ( lscp_client_t *pClient )  int lscp_client_get_errno ( lscp_client_t *pClient )
722  {  {
723      if (pClient == NULL)          if (pClient == NULL)
724          return -1;                  return -1;
725    
726      return pClient->iErrno;          return pClient->iErrno;
727  }  }
728    
729    
# Line 563  int lscp_client_get_errno ( lscp_client_ Line 731  int lscp_client_get_errno ( lscp_client_
731  // Client registration protocol functions.  // Client registration protocol functions.
732    
733  /**  /**
734   *  Register frontend for receiving event messages:   *  Register frontend for receiving event messages by the sampler backend.
735   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
736   *      | CHANNEL_INFO | MISCELLANEOUS   *  for @e each event you want to subscribe. That is the old bitflag approach
737     *  was abondoned at this point. You can however still register all older
738     *  events with one lscp_client_subscribe() call at once. Thus, the old
739     *  behavior of this functions was not broken. Those older events are namely:
740     *  @code
741     *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
742     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
743     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
744     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
745     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
746     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
747     *      | MISCELLANEOUS
748     *  @endcode
749     *  The old events occupy the lower 16 bits (as bit flags), and all younger
750     *  events enumerate the whole upper 16 bits range. The new, enumerated
751     *  events are namely:
752     *  @code
753     *  SUBSCRIBE CHANNEL_MIDI
754     *  @endcode
755   *   *
756   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
757   *  @param events   Bit-wise OR'ed event flags to subscribe.   *  @param events   LSCP event to subscribe.
758   *   *
759   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
760   */   */
761  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
762  {  {
763      lscp_status_t ret = LSCP_FAILED;          lscp_status_t ret = LSCP_OK;
764            lscp_event_t currentEvent;
     if (pClient == NULL)  
         return LSCP_FAILED;  
   
     // Lock this section up.  
     lscp_mutex_lock(pClient->mutex);  
   
     // If applicable, start the alternate connection...  
     if (pClient->events == LSCP_EVENT_NONE)  
         ret = _lscp_client_evt_connect(pClient);  
   
     // Send the subscription commands.  
     if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);  
     if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);  
     if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);  
     if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);  
     if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);  
     if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))  
         ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);  
765    
766      // Unlock this section down.          if (pClient == NULL)
767      lscp_mutex_unlock(pClient->mutex);                  return LSCP_FAILED;
   
     return ret;  
 }  
768    
769            // Lock this section up.
770            lscp_mutex_lock(pClient->mutex);
771    
772  /**          // If applicable, start the alternate connection...
773   *  Deregister frontend from receiving UDP event messages anymore:          if (pClient->events == LSCP_EVENT_NONE)
774   *  SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL                  ret = _lscp_client_evt_connect(pClient);
775   *      | CHANNEL_INFO | MISCELLANEOUS  
776            // Send the subscription commands.
777            if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
778                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);
779            if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
780                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
781            if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
782                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_STREAM_COUNT);
783            if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
784                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_BUFFER_FILL);
785            if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
786                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_INFO);
787            if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
788                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_TOTAL_VOICE_COUNT);
789            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
790                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
791            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
792                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
793            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
794                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
795            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
796                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
797            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
798                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
799            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
800                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
801            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
802                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
803            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
804                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
805            if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
806                    ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_MISCELLANEOUS);
807            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
808            currentEvent = events & 0xffff0000;
809            if (ret == LSCP_OK && currentEvent) {
810                    switch (currentEvent) {
811                            case LSCP_EVENT_CHANNEL_MIDI:
812                            case LSCP_EVENT_DEVICE_MIDI:
813                                    ret = _lscp_client_evt_request(pClient, 1, currentEvent);
814                                    break;
815                            default: // unknown "upper" event type
816                                    ret = LSCP_FAILED;
817                                    break;
818                    }
819            }
820    
821            // Unlock this section down.
822            lscp_mutex_unlock(pClient->mutex);
823    
824            return ret;
825    }
826    
827    
828    /**
829     *  Deregister frontend from receiving UDP event messages anymore.
830     *  @e Caution: since liblscp v0.5.5.4 you have to call
831     *  lscp_client_unsubscribe() for @e each event you want to unsubscribe.
832     *  That is the old bitflag approach was abondoned at this point. You can
833     *  however still register all older events with one lscp_client_subscribe()
834     *  call at once. Thus, the old behavior of this functions was not broken.
835     *  Those older events are namely:
836     *  @code
837     *  UNSUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT
838     *      | BUFFER_FILL | CHANNEL_INFO | TOTAL_VOICE_COUNT
839     *      | AUDIO_OUTPUT_DEVICE_COUNT | AUDIO_OUTPUT_DEVICE_INFO
840     *      | MIDI_INPUT_DEVICE_COUNT | MIDI_INPUT_DEVICE_INFO
841     *      | MIDI_INSTRUMENT_MAP_COUNT | MIDI_INSTRUMENT_MAP_INFO
842     *      | MIDI_INSTRUMENT_COUNT | MIDI_INSTRUMENT_INFO
843     *      | MISCELLANEOUS
844     *  @endcode
845     *  The old events occupy the lower 16 bits (as bit flags), and all younger
846     *  events enumerate the whole upper 16 bits range. The new, enumerated
847     *  events are namely:
848     *  @code
849     *  UNSUBSCRIBE CHANNEL_MIDI
850     *  @endcode
851   *   *
852   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
853   *  @param events   Bit-wise OR'ed event flags to unsubscribe.   *  @param events   LSCP event to unsubscribe.
854   *   *
855   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
856   */   */
857  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
858  {  {
859      lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
860            lscp_event_t currentEvent;
861    
862      if (pClient == NULL)          if (pClient == NULL)
863          return LSCP_FAILED;                  return LSCP_FAILED;
864    
865      // Lock this section up.          // Lock this section up.
866      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
867    
868      // Send the unsubscription commands.          // Send the unsubscription commands.
869      if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
870          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT);
871      if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))          if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
872          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT);
873      if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))          if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT))
874          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_STREAM_COUNT);
875      if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))          if (ret == LSCP_OK && (events & LSCP_EVENT_BUFFER_FILL))
876          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_BUFFER_FILL);
877      if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_INFO))
878          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_INFO);
879      if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))          if (ret == LSCP_OK && (events & LSCP_EVENT_TOTAL_VOICE_COUNT))
880          ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_TOTAL_VOICE_COUNT);
881            if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT))
882      // If necessary, close the alternate connection...                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
883      if (pClient->events == LSCP_EVENT_NONE)          if (ret == LSCP_OK && (events & LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO))
884          lscp_socket_agent_free(&(pClient->evt));                  ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
885            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT))
886                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
887            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INPUT_DEVICE_INFO))
888                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
889            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT))
890                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_COUNT);
891            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO))
892                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_MAP_INFO);
893            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_COUNT))
894                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_COUNT);
895            if (ret == LSCP_OK && (events & LSCP_EVENT_MIDI_INSTRUMENT_INFO))
896                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MIDI_INSTRUMENT_INFO);
897            if (ret == LSCP_OK && (events & LSCP_EVENT_MISCELLANEOUS))
898                    ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_MISCELLANEOUS);
899            // Caution: for the upper 16 bits, we don't use bit flags anymore ...
900            currentEvent = events & 0xffff0000;
901            if (ret == LSCP_OK && currentEvent) {
902                    switch (currentEvent) {
903                            case LSCP_EVENT_CHANNEL_MIDI:
904                            case LSCP_EVENT_DEVICE_MIDI:
905                                    ret = _lscp_client_evt_request(pClient, 0, currentEvent);
906                                    break;
907                            default: // unknown "upper" event type
908                                    ret = LSCP_FAILED;
909                                    break;
910                    }
911            }
912    
913            // If necessary, close the alternate connection...
914            if (pClient->events == LSCP_EVENT_NONE)
915                    lscp_socket_agent_free(&(pClient->evt));
916    
917      // Unlock this section down.          // Unlock this section down.
918      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
919    
920      return ret;          return ret;
921  }  }
922    
923    
# Line 661  lscp_status_t lscp_client_unsubscribe ( Line 930  lscp_status_t lscp_client_unsubscribe (
930   */   */
931  lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )  lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )
932  {  {
933      if (pClient == NULL)          if (pClient == NULL)
934          return LSCP_EVENT_NONE;                  return LSCP_EVENT_NONE;
935    
936      return pClient->events;          return pClient->events;
937  }  }
938    
939    
# Line 682  lscp_event_t lscp_client_get_events ( ls Line 951  lscp_event_t lscp_client_get_events ( ls
951   *   *
952   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
953   */   */
954  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument ( lscp_client_t *pClient,
955            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
956  {  {
957      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
958    
959      if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
960          return LSCP_FAILED;                  return LSCP_FAILED;
961    
962      sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
963      return lscp_client_query(pClient, szQuery);                  pszFileName, iInstrIndex, iSamplerChannel);
964            return lscp_client_query(pClient, szQuery);
965  }  }
966    
967    
# Line 705  lscp_status_t lscp_load_instrument ( lsc Line 976  lscp_status_t lscp_load_instrument ( lsc
976   *   *
977   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
978   */   */
979  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient, const char *pszFileName, int iInstrIndex, int iSamplerChannel )  lscp_status_t lscp_load_instrument_non_modal ( lscp_client_t *pClient,
980            const char *pszFileName, int iInstrIndex, int iSamplerChannel )
981  {  {
982      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
983    
984      if (pszFileName == NULL || iSamplerChannel < 0)          if (pszFileName == NULL || iSamplerChannel < 0)
985          return LSCP_FAILED;                  return LSCP_FAILED;
986    
987      sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n", pszFileName, iInstrIndex, iSamplerChannel);          sprintf(szQuery, "LOAD INSTRUMENT NON_MODAL '%s' %d %d\r\n",
988      return lscp_client_query(pClient, szQuery);                  pszFileName, iInstrIndex, iSamplerChannel);
989            return lscp_client_query(pClient, szQuery);
990  }  }
991    
992    
# Line 729  lscp_status_t lscp_load_instrument_non_m Line 1002  lscp_status_t lscp_load_instrument_non_m
1002   */   */
1003  lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )  lscp_status_t lscp_load_engine ( lscp_client_t *pClient, const char *pszEngineName, int iSamplerChannel )
1004  {  {
1005      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1006    
1007      if (pszEngineName == NULL || iSamplerChannel < 0)          if (pszEngineName == NULL || iSamplerChannel < 0)
1008          return LSCP_FAILED;                  return LSCP_FAILED;
1009    
1010      sprintf(szQuery, "LOAD ENGINE %s %d\r\n", pszEngineName, iSamplerChannel);          sprintf(szQuery, "LOAD ENGINE %s %d\r\n",
1011      return lscp_client_query(pClient, szQuery);                  pszEngineName, iSamplerChannel);
1012            return lscp_client_query(pClient, szQuery);
1013  }  }
1014    
1015    
# Line 750  lscp_status_t lscp_load_engine ( lscp_cl Line 1024  lscp_status_t lscp_load_engine ( lscp_cl
1024   */   */
1025  int lscp_get_channels ( lscp_client_t *pClient )  int lscp_get_channels ( lscp_client_t *pClient )
1026  {  {
1027      int iChannels = -1;          int iChannels = -1;
1028    
1029      // Lock this section up.          if (pClient == NULL)
1030      lscp_mutex_lock(pClient->mutex);                  return -1;
1031    
1032      if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)          // Lock this section up.
1033          iChannels = atoi(lscp_client_get_result(pClient));          lscp_mutex_lock(pClient->mutex);
1034    
1035      // Unlock this section doen.          if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)
1036      lscp_mutex_unlock(pClient->mutex);                  iChannels = atoi(lscp_client_get_result(pClient));
1037    
1038      return iChannels;          // Unlock this section doen.
1039            lscp_mutex_unlock(pClient->mutex);
1040    
1041            return iChannels;
1042  }  }
1043    
1044    
# Line 776  int lscp_get_channels ( lscp_client_t *p Line 1053  int lscp_get_channels ( lscp_client_t *p
1053   */   */
1054  int *lscp_list_channels ( lscp_client_t *pClient )  int *lscp_list_channels ( lscp_client_t *pClient )
1055  {  {
1056      const char *pszSeps = ",";          const char *pszSeps = ",";
1057    
1058      if (pClient == NULL)          if (pClient == NULL)
1059          return NULL;                  return NULL;
1060    
1061      // Lock this section up.          // Lock this section up.
1062      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1063    
1064      if (pClient->channels) {          if (pClient->channels) {
1065          lscp_isplit_destroy(pClient->channels);                  lscp_isplit_destroy(pClient->channels);
1066          pClient->channels = NULL;                  pClient->channels = NULL;
1067      }          }
1068    
1069      if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)
1070          pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);                  pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
1071    
1072      // Unlock this section down.          // Unlock this section down.
1073      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1074    
1075      return pClient->channels;          return pClient->channels;
1076  }  }
1077    
1078    
# Line 810  int *lscp_list_channels ( lscp_client_t Line 1087  int *lscp_list_channels ( lscp_client_t
1087   */   */
1088  int lscp_add_channel ( lscp_client_t *pClient )  int lscp_add_channel ( lscp_client_t *pClient )
1089  {  {
1090      int iSamplerChannel = -1;          int iSamplerChannel = -1;
1091    
1092            if (pClient == NULL)
1093                    return -1;
1094    
1095      // Lock this section up.          // Lock this section up.
1096      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1097    
1098      if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)
1099          iSamplerChannel = atoi(lscp_client_get_result(pClient));                  iSamplerChannel = atoi(lscp_client_get_result(pClient));
1100    
1101      // Unlock this section down.          // Unlock this section down.
1102      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1103    
1104      return iSamplerChannel;          return iSamplerChannel;
1105  }  }
1106    
1107    
# Line 836  int lscp_add_channel ( lscp_client_t *pC Line 1116  int lscp_add_channel ( lscp_client_t *pC
1116   */   */
1117  lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )  lscp_status_t lscp_remove_channel ( lscp_client_t *pClient, int iSamplerChannel )
1118  {  {
1119      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1120    
1121      if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1122          return LSCP_FAILED;                  return LSCP_FAILED;
1123    
1124      sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);          sprintf(szQuery, "REMOVE CHANNEL %d\r\n", iSamplerChannel);
1125      return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1126  }  }
1127    
1128    
# Line 857  lscp_status_t lscp_remove_channel ( lscp Line 1137  lscp_status_t lscp_remove_channel ( lscp
1137   */   */
1138  int lscp_get_available_engines ( lscp_client_t *pClient )  int lscp_get_available_engines ( lscp_client_t *pClient )
1139  {  {
1140      int iAvailableEngines = -1;          int iAvailableEngines = -1;
1141    
1142            if (pClient == NULL)
1143                    return -1;
1144    
1145      // Lock this section up.          // Lock this section up.
1146      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1147    
1148      if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
1149          iAvailableEngines = atoi(lscp_client_get_result(pClient));                  iAvailableEngines = atoi(lscp_client_get_result(pClient));
1150    
1151      // Unlock this section down.          // Unlock this section down.
1152      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1153    
1154      return iAvailableEngines;          return iAvailableEngines;
1155  }  }
1156    
1157    
# Line 883  int lscp_get_available_engines ( lscp_cl Line 1166  int lscp_get_available_engines ( lscp_cl
1166   */   */
1167  const char **lscp_list_available_engines ( lscp_client_t *pClient )  const char **lscp_list_available_engines ( lscp_client_t *pClient )
1168  {  {
1169      const char *pszSeps = ",";          const char *pszSeps = ",";
1170    
1171      // Lock this section up.          if (pClient == NULL)
1172      lscp_mutex_lock(pClient->mutex);                  return NULL;
1173    
1174      if (pClient->engines) {          // Lock this section up.
1175          lscp_szsplit_destroy(pClient->engines);          lscp_mutex_lock(pClient->mutex);
         pClient->engines = NULL;  
     }  
1176    
1177      if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)          if (pClient->engines) {
1178          pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);                  lscp_szsplit_destroy(pClient->engines);
1179                    pClient->engines = NULL;
1180            }
1181    
1182      // Unlock this section down.          if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
1183      lscp_mutex_unlock(pClient->mutex);                  pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);
1184    
1185      return (const char **) pClient->engines;          // Unlock this section down.
1186            lscp_mutex_unlock(pClient->mutex);
1187    
1188            return (const char **) pClient->engines;
1189  }  }
1190    
1191    
# Line 913  const char **lscp_list_available_engines Line 1199  const char **lscp_list_available_engines
1199   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the   *  @returns A pointer to a @ref lscp_engine_info_t structure, with all the
1200   *  information of the given sampler engine, or NULL in case of failure.   *  information of the given sampler engine, or NULL in case of failure.
1201   */   */
1202  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient, const char *pszEngineName )  lscp_engine_info_t *lscp_get_engine_info ( lscp_client_t *pClient,
1203            const char *pszEngineName )
1204  {  {
1205      lscp_engine_info_t *pEngineInfo;          lscp_engine_info_t *pEngineInfo;
1206      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1207      const char *pszResult;          const char *pszResult;
1208      const char *pszSeps = ":";          const char *pszSeps = ":";
1209      const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1210      char *pszToken;          char *pszToken;
1211      char *pch;          char *pch;
1212    
1213      if (pszEngineName == NULL)          if (pClient == NULL)
1214          return NULL;                  return NULL;
1215            if (pszEngineName == NULL)
1216      // Lock this section up.                  return NULL;
1217      lscp_mutex_lock(pClient->mutex);  
1218            // Lock this section up.
1219      pEngineInfo = &(pClient->engine_info);          lscp_mutex_lock(pClient->mutex);
1220      lscp_engine_info_reset(pEngineInfo);  
1221            pEngineInfo = &(pClient->engine_info);
1222      sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);          lscp_engine_info_reset(pEngineInfo);
1223      if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {  
1224          pszResult = lscp_client_get_result(pClient);          sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
1225          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1226          while (pszToken) {                  pszResult = lscp_client_get_result(pClient);
1227              if (strcasecmp(pszToken, "DESCRIPTION") == 0) {                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1228                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                  while (pszToken) {
1229                  if (pszToken)                          if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1230                      lscp_unquote_dup(&(pEngineInfo->description), &pszToken);                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1231              }                                  if (pszToken)
1232              else if (strcasecmp(pszToken, "VERSION") == 0) {                                          lscp_unquote_dup(&(pEngineInfo->description), &pszToken);
1233                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                          }
1234                  if (pszToken)                          else if (strcasecmp(pszToken, "VERSION") == 0) {
1235                      lscp_unquote_dup(&(pEngineInfo->version), &pszToken);                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1236              }                                  if (pszToken)
1237              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          lscp_unquote_dup(&(pEngineInfo->version), &pszToken);
1238          }                          }
1239      }                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1240      else pEngineInfo = NULL;                  }
1241            }
1242            else pEngineInfo = NULL;
1243    
1244      // Unlock this section down.          // Unlock this section down.
1245      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1246    
1247      return pEngineInfo;          return pEngineInfo;
1248  }  }
1249    
1250    
# Line 971  lscp_engine_info_t *lscp_get_engine_info Line 1260  lscp_engine_info_t *lscp_get_engine_info
1260   */   */
1261  lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )  lscp_channel_info_t *lscp_get_channel_info ( lscp_client_t *pClient, int iSamplerChannel )
1262  {  {
1263      lscp_channel_info_t *pChannelInfo;          lscp_channel_info_t *pChannelInfo;
1264      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1265      const char *pszResult;          const char *pszResult;
1266      const char *pszSeps = ":";          const char *pszSeps = ":";
1267      const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1268      char *pszToken;          char *pszToken;
1269      char *pch;          char *pch;
1270            struct _locale_t locale;
1271      if (iSamplerChannel < 0)  
1272          return NULL;          if (pClient == NULL)
1273                    return NULL;
1274      // Lock this section up.          if (iSamplerChannel < 0)
1275      lscp_mutex_lock(pClient->mutex);                  return NULL;
1276    
1277      pChannelInfo = &(pClient->channel_info);          // Lock this section up.
1278      lscp_channel_info_reset(pChannelInfo);          lscp_mutex_lock(pClient->mutex);
1279    
1280      sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          pChannelInfo = &(pClient->channel_info);
1281      if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          lscp_channel_info_reset(pChannelInfo);
1282          pszResult = lscp_client_get_result(pClient);  
1283          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));          _save_and_set_c_locale(&locale);
1284          while (pszToken) {  
1285              if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1286                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1287                  if (pszToken)                  pszResult = lscp_client_get_result(pClient);
1288                      lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1289              }                  while (pszToken) {
1290              else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {                          if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
1291                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1292                  if (pszToken)                                  if (pszToken)
1293                      pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));                                          lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);
1294              }                          }
1295              else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
1296                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1297                  if (pszToken)                                  if (pszToken)
1298                      pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));                                          pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
1299              }                          }
1300              else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
1301                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1302                  if (pszToken) {                                  if (pszToken)
1303                      if (pChannelInfo->audio_routing)                                          pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
1304                          lscp_szsplit_destroy(pChannelInfo->audio_routing);                          }
1305                      pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
1306                  }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1307              }                                  if (pszToken) {
1308              else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                                          if (pChannelInfo->audio_routing)
1309                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1310                  if (pszToken)                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1311                      lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);                                  }
1312              }                          }
1313              else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
1314                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1315                  if (pszToken)                                  if (pszToken)
1316                      pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));                                          lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);
1317              }                          }
1318              else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
1319                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1320                  if (pszToken)                                  if (pszToken)
1321                      lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);                                          pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
1322              }                          }
1323              else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
1324                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1325                  if (pszToken)                                  if (pszToken)
1326                      pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));                                          lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);
1327              }                          }
1328              else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
1329                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1330                  if (pszToken)                                  if (pszToken)
1331                      pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));                                          pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
1332              }                          }
1333              else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {                          else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
1334                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1335                  if (pszToken)                                  if (pszToken)
1336                      pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));                                          pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
1337              }                          }
1338              else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {                          else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
1339                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1340                  if (pszToken) {                                  if (pszToken)
1341                      pszToken = lscp_ltrim(pszToken);                                          pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
1342                      if (strcasecmp(pszToken, "ALL") == 0)                          }
1343                          pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;                          else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
1344                      else                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1345                          pChannelInfo->midi_channel = atoi(pszToken);                                  if (pszToken) {
1346                  }                                          pszToken = lscp_ltrim(pszToken);
1347              }                                          if (strcasecmp(pszToken, "ALL") == 0)
1348              else if (strcasecmp(pszToken, "VOLUME") == 0) {                                                  pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;
1349                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          else
1350                  if (pszToken)                                                  pChannelInfo->midi_channel = atoi(pszToken);
1351                      pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                  }
1352              }                          }
1353              else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MIDI_INSTRUMENT_MAP") == 0) {
1354                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1355                  if (pszToken)                                  if (pszToken) {
1356                      pChannelInfo->mute = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);                                          pszToken = lscp_ltrim(pszToken);
1357              }                                          if (strcasecmp(pszToken, "NONE") == 0)
1358              else if (strcasecmp(pszToken, "SOLO") == 0) {                                                  pChannelInfo->midi_map = LSCP_MIDI_MAP_NONE;
1359                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          else
1360                  if (pszToken)                                          if (strcasecmp(pszToken, "DEFAULT") == 0)
1361                      pChannelInfo->solo = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);                                                  pChannelInfo->midi_map = LSCP_MIDI_MAP_DEFAULT;
1362              }                                          else
1363              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                                  pChannelInfo->midi_map = atoi(pszToken);
1364          }                                  }
1365      }                          }
1366      else pChannelInfo = NULL;                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1367                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1368                                    if (pszToken)
1369                                            pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1370                            }
1371                            else if (strcasecmp(pszToken, "MUTE") == 0) {
1372                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1373                                    if (pszToken)
1374                                            pChannelInfo->mute = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1375                            }
1376                            else if (strcasecmp(pszToken, "SOLO") == 0) {
1377                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1378                                    if (pszToken)
1379                                            pChannelInfo->solo = (strcasecmp(lscp_unquote(&pszToken, 0), "TRUE") == 0);
1380                            }
1381                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1382                    }
1383            }
1384            else pChannelInfo = NULL;
1385    
1386            _restore_locale(&locale);
1387    
1388      // Unlock this section up.          // Unlock this section up.
1389      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1390    
1391      return pChannelInfo;          return pChannelInfo;
1392  }  }
1393    
1394    
# Line 1094  lscp_channel_info_t *lscp_get_channel_in Line 1403  lscp_channel_info_t *lscp_get_channel_in
1403   */   */
1404  int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )  int lscp_get_channel_voice_count ( lscp_client_t *pClient, int iSamplerChannel )
1405  {  {
1406      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1407      int iVoiceCount = -1;          int iVoiceCount = -1;
1408    
1409      if (iSamplerChannel < 0)          if (pClient == NULL)
1410          return iVoiceCount;                  return -1;
1411            if (iSamplerChannel < 0)
1412                    return -1;
1413    
1414      // Lock this section up.          // Lock this section up.
1415      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1416    
1417      sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL VOICE_COUNT %d\r\n", iSamplerChannel);
1418      if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1419          iVoiceCount = atoi(lscp_client_get_result(pClient));                  iVoiceCount = atoi(lscp_client_get_result(pClient));
1420    
1421      // Unlock this section down.          // Unlock this section down.
1422      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1423    
1424      return iVoiceCount;          return iVoiceCount;
1425  }  }
1426    
1427    
# Line 1125  int lscp_get_channel_voice_count ( lscp_ Line 1436  int lscp_get_channel_voice_count ( lscp_
1436   */   */
1437  int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )  int lscp_get_channel_stream_count ( lscp_client_t *pClient, int iSamplerChannel )
1438  {  {
1439      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1440      int iStreamCount = -1;          int iStreamCount = -1;
1441    
1442      if (iSamplerChannel < 0)          if (pClient == NULL)
1443          return iStreamCount;                  return -1;
1444            if (iSamplerChannel < 0)
1445                    return -1;
1446    
1447      // Lock this section up.          // Lock this section up.
1448      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1449    
1450      sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL STREAM_COUNT %d\r\n", iSamplerChannel);
1451      if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
1452          iStreamCount = atoi(lscp_client_get_result(pClient));                  iStreamCount = atoi(lscp_client_get_result(pClient));
1453    
1454      // Unlock this section down.          // Unlock this section down.
1455      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1456    
1457      return iStreamCount;          return iStreamCount;
1458  }  }
1459    
1460    
# Line 1156  int lscp_get_channel_stream_count ( lscp Line 1469  int lscp_get_channel_stream_count ( lscp
1469   */   */
1470  int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )  int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )
1471  {  {
1472      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1473      int  iStreamUsage = -1;          int  iStreamUsage = -1;
1474      const char *pszResult;          const char *pszResult;
1475      const char *pszSeps = "[]%,";          const char *pszSeps = "[]%,";
1476      char *pszToken;          char *pszToken;
1477      char *pch;          char *pch;
1478      int   iStream;          int   iStream;
1479      int   iPercent;          int   iPercent;
1480    
1481      if (iSamplerChannel < 0)          if (pClient == NULL)
1482          return iStreamUsage;                  return -1;
1483            if (iSamplerChannel < 0)
1484      // Lock this section up.                  return -1;
1485      lscp_mutex_lock(pClient->mutex);  
1486            // Lock this section up.
1487      iStream = 0;          lscp_mutex_lock(pClient->mutex);
1488      sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);  
1489      if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {          iStream = 0;
1490          pszResult = lscp_client_get_result(pClient);          sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);
1491          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1492          while (pszToken) {                  pszResult = lscp_client_get_result(pClient);
1493              if (*pszToken) {                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1494                  // Skip stream id.                  while (pszToken) {
1495                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          if (*pszToken) {
1496                  if (pszToken == NULL)                                  // Skip stream id.
1497                      break;                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1498                  // Get least buffer fill percentage.                                  if (pszToken == NULL)
1499                  iPercent = atol(pszToken);                                          break;
1500                  if (iStreamUsage > iPercent || iStream == 0)                                  // Get least buffer fill percentage.
1501                      iStreamUsage = iPercent;                                  iPercent = atol(pszToken);
1502                  iStream++;                                  if (iStreamUsage > iPercent || iStream == 0)
1503              }                                          iStreamUsage = iPercent;
1504              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                  iStream++;
1505          }                          }
1506      }                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1507                    }
1508            }
1509    
1510      // Unlock this section down.          // Unlock this section down.
1511      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1512    
1513      return iStreamUsage;          return iStreamUsage;
1514  }  }
1515    
1516    
# Line 1213  int lscp_get_channel_stream_usage ( lscp Line 1528  int lscp_get_channel_stream_usage ( lscp
1528   *  information of the current disk stream buffer fill usage, for the given   *  information of the current disk stream buffer fill usage, for the given
1529   *  sampler channel, or NULL in case of failure.   *  sampler channel, or NULL in case of failure.
1530   */   */
1531  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient, lscp_usage_t usage_type, int iSamplerChannel )  lscp_buffer_fill_t *lscp_get_channel_buffer_fill ( lscp_client_t *pClient,
1532            lscp_usage_t usage_type, int iSamplerChannel )
1533  {  {
1534      lscp_buffer_fill_t *pBufferFill;          lscp_buffer_fill_t *pBufferFill;
1535      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1536      int iStreamCount;          int iStreamCount;
1537      const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");          const char *pszUsageType = (usage_type == LSCP_USAGE_BYTES ? "BYTES" : "PERCENTAGE");
1538      const char *pszResult;          const char *pszResult;
1539      const char *pszSeps = "[]%,";          const char *pszSeps = "[]%,";
1540      char *pszToken;          char *pszToken;
1541      char *pch;          char *pch;
1542      int   iStream;          int   iStream;
1543    
1544      // Retrieve a channel stream estimation.          // Retrieve a channel stream estimation.
1545      iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1546      if (pClient->iStreamCount < 0)          if (iStreamCount < 0)
1547          return NULL;                  return NULL;
1548    
1549      // Lock this section up.          // Lock this section up.
1550      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1551    
1552      // Check if we need to reallocate the stream usage array.          // Check if we need to reallocate the stream usage array.
1553      if (pClient->iStreamCount != iStreamCount) {          if (pClient->iStreamCount != iStreamCount) {
1554          if (pClient->buffer_fill)                  if (pClient->buffer_fill)
1555              free(pClient->buffer_fill);                          free(pClient->buffer_fill);
1556          if (iStreamCount > 0)                  if (iStreamCount > 0)
1557              pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));                          pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1558          else                  else
1559              pClient->buffer_fill = NULL;                          pClient->buffer_fill = NULL;
1560          pClient->iStreamCount = iStreamCount;                  pClient->iStreamCount = iStreamCount;
1561      }          }
1562    
1563      // Get buffer fill usage...          // Get buffer fill usage...
1564      pBufferFill = pClient->buffer_fill;          pBufferFill = pClient->buffer_fill;
1565      if (pBufferFill && iStreamCount > 0) {          if (pBufferFill && iStreamCount > 0) {
1566          iStream = 0;                  iStream = 0;
1567          pBufferFill = pClient->buffer_fill;                  pBufferFill = pClient->buffer_fill;
1568          sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);                  sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1569          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {                  if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1570              pszResult = lscp_client_get_result(pClient);                          pszResult = lscp_client_get_result(pClient);
1571              pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));                          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1572              while (pszToken && iStream < pClient->iStreamCount) {                          while (pszToken && iStream < pClient->iStreamCount) {
1573                  if (*pszToken) {                                  if (*pszToken) {
1574                      pBufferFill[iStream].stream_id = atol(pszToken);                                          pBufferFill[iStream].stream_id = atol(pszToken);
1575                      pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1576                      if (pszToken == NULL)                                          if (pszToken == NULL)
1577                          break;                                                  break;
1578                      pBufferFill[iStream].stream_usage = atol(pszToken);                                          pBufferFill[iStream].stream_usage = atol(pszToken);
1579                      iStream++;                                          iStream++;
1580                  }                                  }
1581                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1582              }                          }
1583          }   // Reset the usage, whatever it was before.                  }   // Reset the usage, whatever it was before.
1584          else while (iStream < pClient->iStreamCount)                  else while (iStream < pClient->iStreamCount)
1585              pBufferFill[iStream++].stream_usage = 0;                          pBufferFill[iStream++].stream_usage = 0;
1586      }          }
1587    
1588      // Unlock this section down.          // Unlock this section down.
1589      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1590    
1591      return pBufferFill;          return pBufferFill;
1592  }  }
1593    
1594    
# Line 1286  lscp_buffer_fill_t *lscp_get_channel_buf Line 1602  lscp_buffer_fill_t *lscp_get_channel_buf
1602   *   *
1603   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1604   */   */
1605  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszAudioDriver )  lscp_status_t lscp_set_channel_audio_type ( lscp_client_t *pClient,
1606            int iSamplerChannel, const char *pszAudioDriver )
1607  {  {
1608      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1609    
1610      if (iSamplerChannel < 0 || pszAudioDriver == NULL)          if (iSamplerChannel < 0 || pszAudioDriver == NULL)
1611          return LSCP_FAILED;                  return LSCP_FAILED;
1612    
1613      sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n", iSamplerChannel, pszAudioDriver);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_TYPE %d %s\r\n",
1614      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, pszAudioDriver);
1615            return lscp_client_query(pClient, szQuery);
1616  }  }
1617    
1618    
# Line 1308  lscp_status_t lscp_set_channel_audio_typ Line 1626  lscp_status_t lscp_set_channel_audio_typ
1626   *   *
1627   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1628   */   */
1629  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient, int iSamplerChannel, int iAudioDevice )  lscp_status_t lscp_set_channel_audio_device ( lscp_client_t *pClient,
1630            int iSamplerChannel, int iAudioDevice )
1631  {  {
1632      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1633    
1634      if (iSamplerChannel < 0 || iAudioDevice < 0)          if (iSamplerChannel < 0 || iAudioDevice < 0)
1635          return LSCP_FAILED;                  return LSCP_FAILED;
1636    
1637      sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n", iSamplerChannel, iAudioDevice);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1638      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iAudioDevice);
1639            return lscp_client_query(pClient, szQuery);
1640  }  }
1641    
1642    
# Line 1331  lscp_status_t lscp_set_channel_audio_dev Line 1651  lscp_status_t lscp_set_channel_audio_dev
1651   *   *
1652   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1653   */   */
1654  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient, int iSamplerChannel, int iAudioOut, int iAudioIn )  lscp_status_t lscp_set_channel_audio_channel ( lscp_client_t *pClient,
1655            int iSamplerChannel, int iAudioOut, int iAudioIn )
1656  {  {
1657      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1658    
1659      if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)          if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0)
1660          return LSCP_FAILED;                  return LSCP_FAILED;
1661    
1662      sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn);          sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n",
1663      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iAudioOut, iAudioIn);
1664            return lscp_client_query(pClient, szQuery);
1665  }  }
1666    
1667    
# Line 1353  lscp_status_t lscp_set_channel_audio_cha Line 1675  lscp_status_t lscp_set_channel_audio_cha
1675   *   *
1676   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1677   */   */
1678  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient, int iSamplerChannel, const char *pszMidiDriver )  lscp_status_t lscp_set_channel_midi_type ( lscp_client_t *pClient,
1679            int iSamplerChannel, const char *pszMidiDriver )
1680  {  {
1681      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1682    
1683      if (iSamplerChannel < 0 || pszMidiDriver == NULL)          if (iSamplerChannel < 0 || pszMidiDriver == NULL)
1684          return LSCP_FAILED;                  return LSCP_FAILED;
1685    
1686      sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n", iSamplerChannel, pszMidiDriver);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_TYPE %d %s\r\n",
1687      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, pszMidiDriver);
1688            return lscp_client_query(pClient, szQuery);
1689  }  }
1690    
1691    
# Line 1375  lscp_status_t lscp_set_channel_midi_type Line 1699  lscp_status_t lscp_set_channel_midi_type
1699   *   *
1700   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1701   */   */
1702  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient, int iSamplerChannel, int iMidiDevice )  lscp_status_t lscp_set_channel_midi_device ( lscp_client_t *pClient,
1703            int iSamplerChannel, int iMidiDevice )
1704  {  {
1705      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1706    
1707      if (iSamplerChannel < 0 || iMidiDevice < 0)          if (iSamplerChannel < 0 || iMidiDevice < 0)
1708          return LSCP_FAILED;                  return LSCP_FAILED;
1709    
1710      sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n", iSamplerChannel, iMidiDevice);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1711      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iMidiDevice);
1712            return lscp_client_query(pClient, szQuery);
1713  }  }
1714    
1715    
# Line 1397  lscp_status_t lscp_set_channel_midi_devi Line 1723  lscp_status_t lscp_set_channel_midi_devi
1723   *   *
1724   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1725   */   */
1726  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient, int iSamplerChannel, int iMidiPort )  lscp_status_t lscp_set_channel_midi_port ( lscp_client_t *pClient,
1727            int iSamplerChannel, int iMidiPort )
1728  {  {
1729      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1730    
1731      if (iSamplerChannel < 0 || iMidiPort < 0)          if (iSamplerChannel < 0 || iMidiPort < 0)
1732          return LSCP_FAILED;                  return LSCP_FAILED;
1733    
1734      sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n", iSamplerChannel, iMidiPort);          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_PORT %d %d\r\n",
1735      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iMidiPort);
1736            return lscp_client_query(pClient, szQuery);
1737  }  }
1738    
1739    
# Line 1416  lscp_status_t lscp_set_channel_midi_port Line 1744  lscp_status_t lscp_set_channel_midi_port
1744   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
1745   *  @param iSamplerChannel  Sampler channel number.   *  @param iSamplerChannel  Sampler channel number.
1746   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or   *  @param iMidiChannel     MIDI channel address number to listen (0-15) or
1747   *                          LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.   *                          @ref LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels.
1748   *   *
1749   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1750   */   */
1751  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient, int iSamplerChannel, int iMidiChannel )  lscp_status_t lscp_set_channel_midi_channel ( lscp_client_t *pClient,
1752            int iSamplerChannel, int iMidiChannel )
1753  {  {
1754      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1755    
1756      if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)          if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)
1757          return LSCP_FAILED;                  return LSCP_FAILED;
1758    
1759      if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)          if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL)
1760          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n",
1761      else                          iSamplerChannel);
1762          sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);          else
1763      return lscp_client_query(pClient, szQuery);                  sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n",
1764                            iSamplerChannel, iMidiChannel);
1765            return lscp_client_query(pClient, szQuery);
1766    }
1767    
1768    
1769    /**
1770     *  Setting MIDI instrument map:
1771     *  SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <midi-map>
1772     *
1773     *  @param pClient          Pointer to client instance structure.
1774     *  @param iSamplerChannel  Sampler channel number.
1775     *  @param iMidiMap         MIDI instrument map number, or either
1776     *                          @ref LSCP_MIDI_MAP_NONE or
1777     *                          @ref LSCP_MIDI_MAP_DEFAULT .
1778     *
1779     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1780     */
1781    lscp_status_t lscp_set_channel_midi_map ( lscp_client_t *pClient,
1782            int iSamplerChannel, int iMidiMap )
1783    {
1784            char szQuery[LSCP_BUFSIZ];
1785    
1786            if (iSamplerChannel < 0)
1787                    return LSCP_FAILED;
1788    
1789            sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1790            if (iMidiMap == LSCP_MIDI_MAP_NONE)
1791                    strcat(szQuery , "NONE");
1792            else
1793            if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1794                    strcat(szQuery , "DEFAULT");
1795            else
1796                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1797    
1798            strcat(szQuery, "\r\n");
1799    
1800            return lscp_client_query(pClient, szQuery);
1801  }  }
1802    
1803    
# Line 1447  lscp_status_t lscp_set_channel_midi_chan Line 1813  lscp_status_t lscp_set_channel_midi_chan
1813   *   *
1814   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1815   */   */
1816  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient,
1817            int iSamplerChannel, float fVolume )
1818  {  {
1819      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1820            struct _locale_t locale;
1821    
1822            if (iSamplerChannel < 0 || fVolume < 0.0f)
1823                    return LSCP_FAILED;
1824    
1825      if (iSamplerChannel < 0 || fVolume < 0.0)          _save_and_set_c_locale(&locale);
1826          return LSCP_FAILED;          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1827                    iSamplerChannel, fVolume);
1828            _restore_locale(&locale);
1829    
1830      sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          return lscp_client_query(pClient, szQuery);
     return lscp_client_query(pClient, szQuery);  
1831  }  }
1832    
1833    
# Line 1471  lscp_status_t lscp_set_channel_volume ( Line 1843  lscp_status_t lscp_set_channel_volume (
1843   *   *
1844   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1845   */   */
1846  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient, int iSamplerChannel, int iMute )  lscp_status_t lscp_set_channel_mute ( lscp_client_t *pClient,
1847            int iSamplerChannel, int iMute )
1848  {  {
1849      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1850    
1851      if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)          if (iSamplerChannel < 0 || iMute < 0 || iMute > 1)
1852          return LSCP_FAILED;                  return LSCP_FAILED;
1853    
1854      sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n", iSamplerChannel, iMute);          sprintf(szQuery, "SET CHANNEL MUTE %d %d\r\n",
1855      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iMute);
1856            return lscp_client_query(pClient, szQuery);
1857  }  }
1858    
1859    
# Line 1495  lscp_status_t lscp_set_channel_mute ( ls Line 1869  lscp_status_t lscp_set_channel_mute ( ls
1869   *   *
1870   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
1871   */   */
1872  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient, int iSamplerChannel, int iSolo )  lscp_status_t lscp_set_channel_solo ( lscp_client_t *pClient,
1873            int iSamplerChannel, int iSolo )
1874  {  {
1875      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1876    
1877      if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)          if (iSamplerChannel < 0 || iSolo < 0 || iSolo > 1)
1878          return LSCP_FAILED;                  return LSCP_FAILED;
1879    
1880      sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n", iSamplerChannel, iSolo);          sprintf(szQuery, "SET CHANNEL SOLO %d %d\r\n",
1881      return lscp_client_query(pClient, szQuery);                  iSamplerChannel, iSolo);
1882            return lscp_client_query(pClient, szQuery);
1883  }  }
1884    
1885    
# Line 1518  lscp_status_t lscp_set_channel_solo ( ls Line 1894  lscp_status_t lscp_set_channel_solo ( ls
1894   */   */
1895  lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )  lscp_status_t lscp_reset_channel ( lscp_client_t *pClient, int iSamplerChannel )
1896  {  {
1897      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1898    
1899      if (iSamplerChannel < 0)          if (iSamplerChannel < 0)
1900          return LSCP_FAILED;                  return LSCP_FAILED;
1901    
1902      sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);          sprintf(szQuery, "RESET CHANNEL %d\r\n", iSamplerChannel);
1903      return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1904  }  }
1905    
1906    
# Line 1538  lscp_status_t lscp_reset_channel ( lscp_ Line 1914  lscp_status_t lscp_reset_channel ( lscp_
1914   */   */
1915  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1916  {  {
1917      return lscp_client_query(pClient, "RESET\r\n");          // Do actual whole sampler reset...
1918            return lscp_client_query(pClient, "RESET\r\n");
1919  }  }
1920    
1921    
# Line 1553  lscp_status_t lscp_reset_sampler ( lscp_ Line 1930  lscp_status_t lscp_reset_sampler ( lscp_
1930   */   */
1931  lscp_server_info_t *lscp_get_server_info ( lscp_client_t *pClient )  lscp_server_info_t *lscp_get_server_info ( lscp_client_t *pClient )
1932  {  {
1933      lscp_server_info_t *pServerInfo;          lscp_server_info_t *pServerInfo;
1934      const char *pszResult;          const char *pszResult;
1935      const char *pszSeps = ":";          const char *pszSeps = ":";
1936      const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1937      char *pszToken;          char *pszToken;
1938      char *pch;          char *pch;
1939    
1940      // Lock this section up.          if (pClient == NULL)
1941      lscp_mutex_lock(pClient->mutex);                  return NULL;
1942    
1943      pServerInfo = &(pClient->server_info);          // Lock this section up.
1944      lscp_server_info_reset(pServerInfo);          lscp_mutex_lock(pClient->mutex);
1945    
1946      if (lscp_client_call(pClient, "GET SERVER INFO\r\n", 1) == LSCP_OK) {          pServerInfo = &(pClient->server_info);
1947          pszResult = lscp_client_get_result(pClient);          lscp_server_info_reset(pServerInfo);
1948          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));  
1949          while (pszToken) {          if (lscp_client_call(pClient, "GET SERVER INFO\r\n", 1) == LSCP_OK) {
1950              if (strcasecmp(pszToken, "DESCRIPTION") == 0) {                  pszResult = lscp_client_get_result(pClient);
1951                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1952                  if (pszToken)                  while (pszToken) {
1953                      lscp_unquote_dup(&(pServerInfo->description), &pszToken);                          if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1954              }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1955              else if (strcasecmp(pszToken, "VERSION") == 0) {                                  if (pszToken)
1956                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          lscp_unquote_dup(&(pServerInfo->description), &pszToken);
1957                  if (pszToken)                          }
1958                      lscp_unquote_dup(&(pServerInfo->version), &pszToken);                          else if (strcasecmp(pszToken, "VERSION") == 0) {
1959              }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1960              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                  if (pszToken)
1961          }                                          lscp_unquote_dup(&(pServerInfo->version), &pszToken);
1962      }                          }
1963      else pServerInfo = NULL;                          else if (strcasecmp(pszToken, "PROTOCOL_VERSION") == 0) {
1964                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1965                                    if (pszToken)
1966                                            lscp_unquote_dup(&(pServerInfo->protocol_version), &pszToken);
1967                            }
1968                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1969                    }
1970            }
1971            else pServerInfo = NULL;
1972    
1973      // Unlock this section down.          // Unlock this section down.
1974      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1975    
1976      return pServerInfo;          return pServerInfo;
1977  }  }
1978    
1979    
# Line 1603  lscp_server_info_t *lscp_get_server_info Line 1988  lscp_server_info_t *lscp_get_server_info
1988   */   */
1989  int lscp_get_total_voice_count ( lscp_client_t *pClient )  int lscp_get_total_voice_count ( lscp_client_t *pClient )
1990  {  {
1991      int iVoiceCount = -1;          int iVoiceCount = -1;
1992    
1993      // Lock this section up.          if (pClient == NULL)
1994      lscp_mutex_lock(pClient->mutex);                  return -1;
1995    
1996      if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT\r\n", 0) == LSCP_OK)          // Lock this section up.
1997          iVoiceCount = atoi(lscp_client_get_result(pClient));          lscp_mutex_lock(pClient->mutex);
1998    
1999      // Unlock this section down.          if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT\r\n", 0) == LSCP_OK)
2000      lscp_mutex_unlock(pClient->mutex);                  iVoiceCount = atoi(lscp_client_get_result(pClient));
2001    
2002      return iVoiceCount;          // Unlock this section down.
2003            lscp_mutex_unlock(pClient->mutex);
2004    
2005            return iVoiceCount;
2006  }  }
2007    
2008    
# Line 1629  int lscp_get_total_voice_count ( lscp_cl Line 2017  int lscp_get_total_voice_count ( lscp_cl
2017   */   */
2018  int lscp_get_total_voice_count_max ( lscp_client_t *pClient )  int lscp_get_total_voice_count_max ( lscp_client_t *pClient )
2019  {  {
2020      int iVoiceCount = -1;          int iVoiceCount = -1;
2021    
2022            if (pClient == NULL)
2023                    return -1;
2024    
2025            // Lock this section up.
2026            lscp_mutex_lock(pClient->mutex);
2027    
2028            if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT_MAX\r\n", 0) == LSCP_OK)
2029                    iVoiceCount = atoi(lscp_client_get_result(pClient));
2030    
2031            // Unlock this section down.
2032            lscp_mutex_unlock(pClient->mutex);
2033    
2034            return iVoiceCount;
2035    }
2036    
2037    
2038    /**
2039     *  Get global volume attenuation:
2040     *  GET VOLUME
2041     *
2042     *  @param pClient  Pointer to client instance structure.
2043     *
2044     *  @returns The global volume as positive floating point value usually in
2045     *  the range between 0.0 and 1.0; in case of failure 0.0 is returned.
2046     */
2047    float lscp_get_volume ( lscp_client_t *pClient )
2048    {
2049            float fVolume = 0.0f;
2050            struct _locale_t locale;
2051    
2052            if (pClient == NULL)
2053                    return 0.0f;
2054    
2055            // Lock this section up.
2056            lscp_mutex_lock(pClient->mutex);
2057    
2058            _save_and_set_c_locale(&locale);
2059    
2060      // Lock this section up.          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
2061      lscp_mutex_lock(pClient->mutex);                  fVolume = _atof(lscp_client_get_result(pClient));
2062    
2063      if (lscp_client_call(pClient, "GET TOTAL_VOICE_COUNT_MAX\r\n", 0) == LSCP_OK)          _restore_locale(&locale);
         iVoiceCount = atoi(lscp_client_get_result(pClient));  
2064    
2065      // Unlock this section down.          // Unlock this section down.
2066      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2067    
2068      return iVoiceCount;          return fVolume;
2069    }
2070    
2071    
2072    /**
2073     *  Setting global volume attenuation:
2074     *  SET VOLUME <volume>
2075     *
2076     *  @param pClient  Pointer to client instance structure.
2077     *  @param fVolume  Global volume parameter as positive floating point
2078     *                  value usually be in the range between 0.0 and 1.0,
2079     *                  that is for attenuating the overall volume.
2080     *
2081     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2082     */
2083    lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
2084    {
2085            char szQuery[LSCP_BUFSIZ];
2086            struct _locale_t locale;
2087    
2088            if (fVolume < 0.0f)
2089                    return LSCP_FAILED;
2090    
2091            _save_and_set_c_locale(&locale);
2092            sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
2093            _restore_locale(&locale);
2094    
2095            return lscp_client_query(pClient, szQuery);
2096    }
2097    
2098    
2099    /**
2100     *  Get global voice limit setting:
2101     *  @code
2102     *  GET VOICES
2103     *  @endcode
2104     *  This value reflects the maximum amount of voices a sampler engine
2105     *  processes simultaniously before voice stealing kicks in.
2106     *
2107     *  @param pClient  Pointer to client instance structure.
2108     *
2109     *  @returns The current global maximum amount of voices limit or a
2110     *           negative value on error (e.g. if sampler doesn't support
2111     *           this command).
2112     */
2113    int lscp_get_voices ( lscp_client_t *pClient )
2114    {
2115            int iVoices = -1;
2116    
2117            if (pClient == NULL)
2118                    return -1;
2119    
2120            // Lock this section up.
2121            lscp_mutex_lock(pClient->mutex);
2122    
2123            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
2124                    iVoices = atoi(lscp_client_get_result(pClient));
2125    
2126            // Unlock this section down.
2127            lscp_mutex_unlock(pClient->mutex);
2128    
2129            return iVoices;
2130    }
2131    
2132    
2133    /**
2134     *  Setting global voice limit setting:
2135     *  @code
2136     *  SET VOICES <max-voices>
2137     *  @endcode
2138     *  This value reflects the maximum amount of voices a sampler engine
2139     *  processes simultaniously before voice stealing kicks in. Note that
2140     *  this value will be passed to all sampler engine instances, that is
2141     *  the total amount of maximum voices on the running system is thus
2142     *  @param iMaxVoices multiplied with the current amount of sampler
2143     *  engine instances.
2144     *
2145     *  @param pClient     Pointer to client instance structure.
2146     *  @param iMaxVoices  Global voice limit setting as integer value larger
2147     *                     or equal to 1.
2148     *
2149     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2150     */
2151    lscp_status_t lscp_set_voices ( lscp_client_t *pClient, int iMaxVoices )
2152    {
2153            char szQuery[LSCP_BUFSIZ];
2154    
2155            if (iMaxVoices < 1)
2156                    return LSCP_FAILED;
2157    
2158            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2159            return lscp_client_query(pClient, szQuery);
2160    }
2161    
2162    
2163    /**
2164     *  Get global disk streams limit setting:
2165     *  @code
2166     *  GET STREAMS
2167     *  @endcode
2168     *  This value reflects the maximum amount of disk streams a sampler
2169     *  engine processes simultaniously.
2170     *
2171     *  @param pClient  Pointer to client instance structure.
2172     *
2173     *  @returns The current global maximum amount of disk streams limit
2174     *           or a negative value on error (e.g. if sampler doesn't
2175     *           support this command).
2176     */
2177    int lscp_get_streams ( lscp_client_t *pClient )
2178    {
2179            int iStreams = -1;
2180    
2181            if (pClient == NULL)
2182                    return -1;
2183    
2184            // Lock this section up.
2185            lscp_mutex_lock(pClient->mutex);
2186    
2187            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2188                    iStreams = atoi(lscp_client_get_result(pClient));
2189    
2190            // Unlock this section down.
2191            lscp_mutex_unlock(pClient->mutex);
2192    
2193            return iStreams;
2194    }
2195    
2196    
2197    /**
2198     *  Setting global disk streams limit setting:
2199     *  @code
2200     *  SET STREAMS <max-streams>
2201     *  @endcode
2202     *  This value reflects the maximum amount of dist streams a sampler
2203     *  engine instance processes simultaniously. Note that this value will
2204     *  be passed to all sampler engine instances, that is the total amount
2205     *  of maximum disk streams on the running system is thus
2206     *  @param iMaxStreams multiplied with the current amount of sampler
2207     *  engine instances.
2208     *
2209     *  @param pClient      Pointer to client instance structure.
2210     *  @param iMaxStreams  Global streams limit setting as positive integer
2211     *                      value (larger or equal to 0).
2212     *
2213     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2214     */
2215    lscp_status_t lscp_set_streams ( lscp_client_t *pClient, int iMaxStreams )
2216    {
2217            char szQuery[LSCP_BUFSIZ];
2218    
2219            if (iMaxStreams < 0)
2220                    return LSCP_FAILED;
2221    
2222            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2223            return lscp_client_query(pClient, szQuery);
2224    }
2225    
2226    
2227    /**
2228     *  Add an effect send to a sampler channel:
2229     *  CREATE FX_SEND <sampler-channel> <midi-ctrl> [<fx-name>]
2230     *
2231     *  @param pClient          Pointer to client instance structure.
2232     *  @param iSamplerChannel  Sampler channel number.
2233     *  @param iMidiController  MIDI controller used to alter the effect,
2234     *                          usually a number between 0 and 127.
2235     *  @param pszFxName        Optional name for the effect send entity,
2236     *                          does not have to be unique.
2237     *
2238     *  @returns The new effect send number identifier, or -1 in case of failure.
2239     */
2240    int lscp_create_fxsend ( lscp_client_t *pClient,
2241            int iSamplerChannel, int iMidiController, const char *pszFxName )
2242    {
2243            int iFxSend = -1;
2244            char szQuery[LSCP_BUFSIZ];
2245    
2246            if (pClient == NULL)
2247                    return -1;
2248            if (iSamplerChannel < 0 || iMidiController < 0 || iMidiController > 127)
2249                    return -1;
2250    
2251            // Lock this section up.
2252            lscp_mutex_lock(pClient->mutex);
2253    
2254            sprintf(szQuery, "CREATE FX_SEND %d %d",
2255                    iSamplerChannel, iMidiController);
2256    
2257            if (pszFxName)
2258                    sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2259    
2260            strcat(szQuery, "\r\n");
2261    
2262            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2263                    iFxSend = atoi(lscp_client_get_result(pClient));
2264    
2265            // Unlock this section down.
2266            lscp_mutex_unlock(pClient->mutex);
2267    
2268            return iFxSend;
2269    }
2270    
2271    
2272    /**
2273     *  Remove an effect send from a sampler channel:
2274     *  DESTROY FX_SEND <sampler-channel> <fx-send-id>
2275     *
2276     *  @param pClient          Pointer to client instance structure.
2277     *  @param iSamplerChannel  Sampler channel number.
2278     *  @param iFxSend          Effect send number.
2279     *
2280     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2281     */
2282    lscp_status_t lscp_destroy_fxsend ( lscp_client_t *pClient,
2283            int iSamplerChannel, int iFxSend )
2284    {
2285            char szQuery[LSCP_BUFSIZ];
2286    
2287            if (iSamplerChannel < 0 || iFxSend < 0)
2288                    return LSCP_FAILED;
2289    
2290            sprintf(szQuery, "DESTROY FX_SEND %d %d\r\n",
2291                    iSamplerChannel, iFxSend);
2292    
2293            return lscp_client_query(pClient, szQuery);
2294    }
2295    
2296    
2297    /**
2298     *  Get amount of effect sends on a sampler channel:
2299     *  GET FX_SENDS <sampler-channel>
2300     *
2301     *  @param pClient          Pointer to client instance structure.
2302     *  @param iSamplerChannel  Sampler channel number.
2303     *
2304     *  @returns The current total number of effect sends of the sampler channel
2305     *  on success, -1 otherwise.
2306     */
2307    int lscp_get_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2308    {
2309            int iFxSends = -1;
2310            char szQuery[LSCP_BUFSIZ];
2311    
2312            if (pClient == NULL)
2313                    return -1;
2314            if (iSamplerChannel < 0)
2315                    return -1;
2316    
2317            // Lock this section up.
2318            lscp_mutex_lock(pClient->mutex);
2319    
2320            sprintf(szQuery, "GET FX_SENDS %d\r\n", iSamplerChannel);
2321    
2322            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2323                    iFxSends = atoi(lscp_client_get_result(pClient));
2324    
2325            // Unlock this section doen.
2326            lscp_mutex_unlock(pClient->mutex);
2327    
2328            return iFxSends;
2329    }
2330    
2331    
2332    /**
2333     *  List all effect sends on a sampler channel:
2334     *  LIST FX_SENDS <sampler-channel>
2335     *
2336     *  @param pClient          Pointer to client instance structure.
2337     *  @param iSamplerChannel  Sampler channel number.
2338     *
2339     *  @returns An array of the effect sends identifiers as positive integers,
2340     *  terminated with -1 on success, NULL otherwise.
2341     */
2342    int *lscp_list_fxsends ( lscp_client_t *pClient, int iSamplerChannel )
2343    {
2344            const char *pszSeps = ",";
2345            char szQuery[LSCP_BUFSIZ];
2346    
2347            if (pClient == NULL)
2348                    return NULL;
2349    
2350            // Lock this section up.
2351            lscp_mutex_lock(pClient->mutex);
2352    
2353            if (pClient->fxsends) {
2354                    lscp_isplit_destroy(pClient->fxsends);
2355                    pClient->fxsends = NULL;
2356            }
2357    
2358            sprintf(szQuery, "LIST FX_SENDS %d\r\n", iSamplerChannel);
2359    
2360            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2361                    pClient->fxsends = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2362    
2363            // Unlock this section down.
2364            lscp_mutex_unlock(pClient->mutex);
2365    
2366            return pClient->fxsends;
2367    }
2368    
2369    
2370    /**
2371     *  Getting effect send information
2372     *  GET FX_SEND INFO <sampler-channel> <fx-send-id>
2373     *
2374     *  @param pClient          Pointer to client instance structure.
2375     *  @param iSamplerChannel  Sampler channel number.
2376     *  @param iFxSend          Effect send number.
2377     *
2378     *  @returns A pointer to a @ref lscp_fxsend_info_t structure, with the
2379     *  information of the given FX send, or NULL in case of failure.
2380     */
2381    lscp_fxsend_info_t *lscp_get_fxsend_info ( lscp_client_t *pClient,
2382            int iSamplerChannel, int iFxSend )
2383    {
2384            lscp_fxsend_info_t *pFxSendInfo;
2385            char szQuery[LSCP_BUFSIZ];
2386            const char *pszResult;
2387            const char *pszSeps = ":";
2388            const char *pszCrlf = "\r\n";
2389            char *pszToken;
2390            char *pch;
2391            struct _locale_t locale;
2392    
2393            if (pClient == NULL)
2394                    return NULL;
2395            if (iSamplerChannel < 0 || iFxSend < 0)
2396                    return NULL;
2397    
2398            // Lock this section up.
2399            lscp_mutex_lock(pClient->mutex);
2400    
2401            _save_and_set_c_locale(&locale);
2402    
2403            pFxSendInfo = &(pClient->fxsend_info);
2404            lscp_fxsend_info_reset(pFxSendInfo);
2405    
2406            sprintf(szQuery, "GET FX_SEND INFO %d %d\r\n", iSamplerChannel, iFxSend);
2407            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2408                    pszResult = lscp_client_get_result(pClient);
2409                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2410                    while (pszToken) {
2411                            if (strcasecmp(pszToken, "NAME") == 0) {
2412                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2413                                    if (pszToken)
2414                                            lscp_unquote_dup(&(pFxSendInfo->name), &pszToken);
2415                            }
2416                            else if (strcasecmp(pszToken, "MIDI_CONTROLLER") == 0) {
2417                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2418                                    if (pszToken)
2419                                            pFxSendInfo->midi_controller = atoi(lscp_ltrim(pszToken));
2420                            }
2421                            else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
2422                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2423                                    if (pszToken) {
2424                                            if (pFxSendInfo->audio_routing)
2425                                                    lscp_isplit_destroy(pFxSendInfo->audio_routing);
2426                                            pFxSendInfo->audio_routing = lscp_isplit_create(pszToken, ",");
2427                                    }
2428                            }
2429                            else if (strcasecmp(pszToken, "LEVEL") == 0) {
2430                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2431                                    if (pszToken)
2432                                            pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2433                            }
2434                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2435                    }
2436            }
2437            else pFxSendInfo = NULL;
2438    
2439            _restore_locale(&locale);
2440    
2441            // Unlock this section up.
2442            lscp_mutex_unlock(pClient->mutex);
2443    
2444            return pFxSendInfo;
2445    }
2446    
2447    
2448    /**
2449     *  Alter effect send's name:
2450     *  @code
2451     *  SET FX_SEND NAME <sampler-chan> <fx-send-id> <name>
2452     *  @endcode
2453     *
2454     *  @param pClient          Pointer to client instance structure.
2455     *  @param iSamplerChannel  Sampler channel number.
2456     *  @param iFxSend          Effect send number.
2457     *  @param pszFxName        Effect send's new name.
2458     *
2459     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2460     */
2461    lscp_status_t lscp_set_fxsend_name ( lscp_client_t *pClient,
2462            int iSamplerChannel, int iFxSend, const char *pszFxName )
2463    {
2464            char szQuery[LSCP_BUFSIZ];
2465    
2466            if (!pClient || iSamplerChannel < 0 || iFxSend < 0 || !pszFxName)
2467                    return LSCP_FAILED;
2468    
2469            snprintf(szQuery, LSCP_BUFSIZ, "SET FX_SEND NAME %d %d '%s'\r\n",
2470                    iSamplerChannel, iFxSend, pszFxName);
2471            return lscp_client_query(pClient, szQuery);
2472    }
2473    
2474    
2475    /**
2476     *  Alter effect send's audio routing:
2477     *  SET FX_SEND AUDIO_OUTPUT_CHANNEL <sampler-chan> <fx-send-id>
2478     *    <audio-src> <audio-dst>
2479     *
2480     *  @param pClient          Pointer to client instance structure.
2481     *  @param iSamplerChannel  Sampler channel number.
2482     *  @param iFxSend          Effect send number.
2483     *  @param iAudioSrc        Audio output device channel to be routed from.
2484     *  @param iAudioDst        Audio output device channel to be routed into.
2485     *
2486     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2487     */
2488    lscp_status_t lscp_set_fxsend_audio_channel ( lscp_client_t *pClient,
2489            int iSamplerChannel, int iFxSend, int iAudioSrc, int iAudioDst )
2490    {
2491            char szQuery[LSCP_BUFSIZ];
2492    
2493            if (iSamplerChannel < 0 || iFxSend < 0 || iAudioSrc < 0 || iAudioDst < 0)
2494                    return LSCP_FAILED;
2495    
2496            sprintf(szQuery, "SET FX_SEND AUDIO_OUTPUT_CHANNEL %d %d %d %d\r\n",
2497                    iSamplerChannel, iFxSend, iAudioSrc, iAudioDst);
2498            return lscp_client_query(pClient, szQuery);
2499    }
2500    
2501    
2502    /**
2503     *  Alter effect send's MIDI controller:
2504     *  SET FX_SEND MIDI_CONTROLLER <sampler-chan> <fx-send-id> <midi-ctrl>
2505     *
2506     *  @param pClient          Pointer to client instance structure.
2507     *  @param iSamplerChannel  Sampler channel number.
2508     *  @param iFxSend          Effect send number.
2509     *  @param iMidiController  MIDI controller used to alter the effect,
2510     *                          usually a number between 0 and 127.
2511     *
2512     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2513     */
2514    lscp_status_t lscp_set_fxsend_midi_controller ( lscp_client_t *pClient,
2515            int iSamplerChannel, int iFxSend, int iMidiController )
2516    {
2517            char szQuery[LSCP_BUFSIZ];
2518    
2519            if (iSamplerChannel < 0 || iFxSend < 0 ||
2520                    iMidiController < 0 || iMidiController > 127)
2521                    return LSCP_FAILED;
2522    
2523            sprintf(szQuery, "SET FX_SEND MIDI_CONTROLLER %d %d %d\r\n",
2524                    iSamplerChannel, iFxSend, iMidiController);
2525            return lscp_client_query(pClient, szQuery);
2526    }
2527    
2528    
2529    /**
2530     *  Alter effect send's audio level:
2531     *  SET FX_SEND LEVEL <sampler-chan> <fx-send-id> <level>
2532     *
2533     *  @param pClient          Pointer to client instance structure.
2534     *  @param iSamplerChannel  Sampler channel number.
2535     *  @param iFxSend          Effect send number.
2536     *  @param fLevel           Effect send volume level.
2537     *
2538     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2539     */
2540    lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient,
2541            int iSamplerChannel, int iFxSend, float fLevel )
2542    {
2543            char szQuery[LSCP_BUFSIZ];
2544            struct _locale_t locale;
2545    
2546            if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2547                    return LSCP_FAILED;
2548    
2549            _save_and_set_c_locale(&locale);
2550            sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n",
2551                    iSamplerChannel, iFxSend, fLevel);
2552            _restore_locale(&locale);
2553    
2554            return lscp_client_query(pClient, szQuery);
2555    }
2556    
2557    
2558    /**
2559     *  Create a new MIDI instrument map:
2560     *  ADD MIDI_INSTRUMENT_MAP [<name>]
2561     *
2562     *  @param pClient      Pointer to client instance structure.
2563     *  @param pszMapName   MIDI instrument map name (optional)
2564     *
2565     *  @returns The new MIDI instrument map number identifier,
2566     *  or -1 in case of failure.
2567     */
2568    int lscp_add_midi_instrument_map ( lscp_client_t *pClient, const char *pszMapName )
2569    {
2570            int iMidiMap = -1;
2571            char szQuery[LSCP_BUFSIZ];
2572    
2573            if (pClient == NULL)
2574                    return -1;
2575    
2576            // Lock this section up.
2577            lscp_mutex_lock(pClient->mutex);
2578    
2579            strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2580    
2581            if (pszMapName)
2582                    sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2583    
2584            strcat(szQuery, "\r\n");
2585    
2586            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2587                    iMidiMap = atoi(lscp_client_get_result(pClient));
2588    
2589            // Unlock this section down.
2590            lscp_mutex_unlock(pClient->mutex);
2591    
2592            return iMidiMap;
2593    }
2594    
2595    
2596    /**
2597     *  Delete one particular or all MIDI instrument maps:
2598     *  REMOVE MIDI_INSTRUMENT_MAP <midi-map>
2599     *
2600     *  @param pClient  Pointer to client instance structure.
2601     *  @param iMidiMap MIDI instrument map number.
2602     *
2603     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2604     */
2605    lscp_status_t lscp_remove_midi_instrument_map ( lscp_client_t *pClient, int iMidiMap )
2606    {
2607            char szQuery[LSCP_BUFSIZ];
2608    
2609            if (iMidiMap < 0)
2610                    return LSCP_FAILED;
2611    
2612            sprintf(szQuery, "REMOVE MIDI_INSTRUMENT_MAP %d\r\n", iMidiMap);
2613    
2614            return lscp_client_query(pClient, szQuery);
2615    }
2616    
2617    
2618    /**
2619     *  Get amount of existing MIDI instrument maps:
2620     *  GET MIDI_INSTRUMENT_MAPS
2621     *
2622     *  @param pClient  Pointer to client instance structure.
2623     *
2624     *  @returns The current total number of MIDI instrument maps
2625     *  on success, -1 otherwise.
2626     */
2627    int lscp_get_midi_instrument_maps ( lscp_client_t *pClient )
2628    {
2629            int iMidiMaps = -1;
2630    
2631            if (pClient == NULL)
2632                    return -1;
2633    
2634            // Lock this section up.
2635            lscp_mutex_lock(pClient->mutex);
2636    
2637            if (lscp_client_call(pClient, "GET MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2638                    iMidiMaps = atoi(lscp_client_get_result(pClient));
2639    
2640            // Unlock this section doen.
2641            lscp_mutex_unlock(pClient->mutex);
2642    
2643            return iMidiMaps;
2644    }
2645    
2646    
2647    /**
2648     *  Getting all created MIDI instrument maps:
2649     *  LIST MIDI_INSTRUMENT_MAPS
2650     *
2651     *  @param pClient  Pointer to client instance structure.
2652     *
2653     *  @returns An array of the MIDI instrument map identifiers as positive
2654     *  integers, terminated with -1 on success, NULL otherwise.
2655     */
2656    int *lscp_list_midi_instrument_maps ( lscp_client_t *pClient )
2657    {
2658            const char *pszSeps = ",";
2659    
2660            if (pClient == NULL)
2661                    return NULL;
2662    
2663            // Lock this section up.
2664            lscp_mutex_lock(pClient->mutex);
2665    
2666            if (pClient->midi_maps) {
2667                    lscp_isplit_destroy(pClient->midi_maps);
2668                    pClient->midi_maps = NULL;
2669            }
2670    
2671            if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENT_MAPS\r\n", 0) == LSCP_OK)
2672                    pClient->midi_maps = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
2673    
2674            // Unlock this section down.
2675            lscp_mutex_unlock(pClient->mutex);
2676    
2677            return pClient->midi_maps;
2678    }
2679    
2680    
2681    /**
2682     *  Getting a MIDI instrument map name:
2683     *  GET MIDI_INSTRUMENT_MAP INFO <midi-map>
2684     *
2685     *  @param pClient  Pointer to client instance structure.
2686     *  @param iMidiMap MIDI instrument map number.
2687     *
2688     *  @returns The MIDI instrument map name on success, NULL on failure.
2689     */
2690    const char *lscp_get_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap )
2691    {
2692            char szQuery[LSCP_BUFSIZ];
2693            const char *pszResult;
2694            const char *pszSeps = ":";
2695            const char *pszCrlf = "\r\n";
2696            char *pszToken;
2697            char *pch;
2698    
2699            if (pClient == NULL)
2700                    return NULL;
2701            if (iMidiMap < 0)
2702                    return NULL;
2703    
2704            // Lock this section up.
2705            lscp_mutex_lock(pClient->mutex);
2706    
2707            if (pClient->midi_map_name) {
2708                    free(pClient->midi_map_name);
2709                    pClient->midi_map_name = NULL;
2710            }
2711    
2712            sprintf(szQuery, "GET MIDI_INSTRUMENT_MAP INFO %d\r\n", iMidiMap);
2713            if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2714                    pszResult = lscp_client_get_result(pClient);
2715                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2716                    while (pszToken) {
2717                            if (strcasecmp(pszToken, "NAME") == 0) {
2718                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2719                                    if (pszToken)
2720                                            lscp_unquote_dup(&(pClient->midi_map_name), &pszToken);
2721                            }
2722                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2723                    }
2724            }
2725    
2726            // Unlock this section down.
2727            lscp_mutex_unlock(pClient->mutex);
2728    
2729            return pClient->midi_map_name;
2730    }
2731    
2732    
2733    /**
2734     *  Renaming a MIDI instrument map:
2735     *  SET MIDI_INSTRUMENT_MAP NAME <midi-map> <map-name>
2736     *
2737     *  @param pClient      Pointer to client instance structure.
2738     *  @param iMidiMap     MIDI instrument map number.
2739     *  @param pszMapName   MIDI instrument map name.
2740     *
2741     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2742     */
2743    lscp_status_t lscp_set_midi_instrument_map_name ( lscp_client_t *pClient, int iMidiMap, const char *pszMapName )
2744    {
2745            char szQuery[LSCP_BUFSIZ];
2746    
2747            if (iMidiMap < 0)
2748                    return LSCP_FAILED;
2749            if (pszMapName == NULL)
2750                    return LSCP_FAILED;
2751    
2752            sprintf(szQuery, "SET MIDI_INSTRUMENT_MAP NAME %d '%s'\r\n",
2753                    iMidiMap, pszMapName);
2754    
2755            return lscp_client_query(pClient, szQuery);
2756  }  }
2757    
2758    
2759  /**  /**
2760   *  Create or replace a MIDI instrumnet map entry:   *  Create or replace a MIDI instrumnet map entry:
2761   *  MAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  MAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2762   *      <engine-name> <filename> <instr-index> <volume> <load-mode> [<name>]   *      <engine-name> <filename> <instr-index> <volume> [<load-mode> [<name>]}
2763   *   *
2764   *  @param pClient          Pointer to client instance structure.   *  @param pClient          Pointer to client instance structure.
2765   *  @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 2767  int lscp_get_total_voice_count_max ( lsc
2767   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2768   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2769   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2770   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2771   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2772   *                          1.0 for amplification.   *                          1.0 for amplification.
2773   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 1663  int lscp_get_total_voice_count_max ( lsc Line 2775  int lscp_get_total_voice_count_max ( lsc
2775   *                          @ref LSCP_LOAD_ON_DEMAND, or   *                          @ref LSCP_LOAD_ON_DEMAND, or
2776   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or   *                          @ref LSCP_LOAD_ON_DEMAND_HOLD, or
2777   *                          @ref LSCP_LOAD_PERSISTENT.   *                          @ref LSCP_LOAD_PERSISTENT.
2778   *  @param pszName          Instrument custom name for the map entry.   *  @param pszName         Instrument custom name for the map entry (optional).
2779   *   *
2780   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2781   */   */
2782  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient,
2783  {          lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName,
2784      char szQuery[LSCP_BUFSIZ];          const char *pszFileName, int iInstrIndex, float fVolume,
2785                lscp_load_mode_t load_mode, const char *pszName )
2786      if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)  {
2787          return LSCP_FAILED;          char szQuery[LSCP_BUFSIZ];
2788      if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          struct _locale_t locale;
2789          return LSCP_FAILED;  
2790      if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->map < 0)
2791          return LSCP_FAILED;                  return LSCP_FAILED;
2792      if (pszEngineName == NULL || pszFileName == NULL)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2793          return LSCP_FAILED;                  return LSCP_FAILED;
2794                if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2795      if (fVolume < 0.0f)                  return LSCP_FAILED;
2796          fVolume = 1.0f;          if (pszEngineName == NULL || pszFileName == NULL)
2797                        return LSCP_FAILED;
2798      sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",  
2799          pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program,          if (fVolume < 0.0f)
2800          pszEngineName, pszFileName, iInstrIndex, fVolume);                  fVolume = 1.0f;
2801        
2802      switch (load_mode) {          _save_and_set_c_locale(&locale);
2803      case LSCP_LOAD_PERSISTENT:          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2804          strcat(szQuery, " PERSISTENT");                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2805          break;                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2806      case LSCP_LOAD_ON_DEMAND_HOLD:          _restore_locale(&locale);
2807          strcat(szQuery, " ON_DEMAND_HOLD");  
2808          break;          switch (load_mode) {
2809      case LSCP_LOAD_ON_DEMAND:          case LSCP_LOAD_PERSISTENT:
2810          strcat(szQuery, " ON_DEMAND_HOLD");                  strcat(szQuery, " PERSISTENT");
2811          break;                  break;
2812      case LSCP_LOAD_DEFAULT:          case LSCP_LOAD_ON_DEMAND_HOLD:
2813      default:                  strcat(szQuery, " ON_DEMAND_HOLD");
2814          break;                  break;
2815      }          case LSCP_LOAD_ON_DEMAND:
2816                        strcat(szQuery, " ON_DEMAND");
2817      if (pszName)                  break;
2818          sprintf(szQuery + strlen(szQuery), " '%s'", pszName);          case LSCP_LOAD_DEFAULT:
2819                default:
2820      strcat(szQuery, "\r\n");                  break;
2821                }
2822      return lscp_client_query(pClient, szQuery);  
2823            if (pszName)
2824                    sprintf(szQuery + strlen(szQuery), " '%s'", pszName);
2825    
2826            strcat(szQuery, "\r\n");
2827    
2828            return lscp_client_query(pClient, szQuery);
2829  }  }
2830    
2831    
2832  /**  /**
2833   *  Remove an entry from the MIDI instrument map:   *  Remove an entry from the MIDI instrument map:
2834   *  UNMAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  UNMAP MIDI_INSTRUMENT <midi-map> <midi-bank> <midi-prog>
2835   *   *
2836   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2837   *  @param pMidiInstr   MIDI instrument bank and program parameter key.   *  @param pMidiInstr   MIDI instrument bank and program parameter key.
2838   *   *
2839   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2840   */   */
2841  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_status_t lscp_unmap_midi_instrument ( lscp_client_t *pClient,
2842            lscp_midi_instrument_t *pMidiInstr )
2843  {  {
2844      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2845    
2846      if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)          if (pMidiInstr->map < 0)
2847          return LSCP_FAILED;                  return LSCP_FAILED;
2848      if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2849          return LSCP_FAILED;                  return LSCP_FAILED;
2850      if (pMidiInstr->program < 0 || pMidiInstr->program > 127)          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2851          return LSCP_FAILED;                  return LSCP_FAILED;
2852    
2853      sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",          sprintf(szQuery, "UNMAP MIDI_INSTRUMENT %d %d %d\r\n",
2854                  pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2855    
2856      return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2857  }  }
2858    
2859    
2860  /**  /**
2861   *  Get the total count of MIDI instrument map entries:   *  Get the total count of MIDI instrument map entries:
2862   *  GET MIDI_INSTRUMENTS   *  GET MIDI_INSTRUMENTS ALL|<midi-map>
2863   *   *
2864   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2865     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2866   *   *
2867   *  @returns The current total number of MIDI instrument map entries   *  @returns The current total number of MIDI instrument map entries
2868   *  on success, -1 otherwise.   *  on success, -1 otherwise.
2869   */   */
2870  int lscp_get_midi_instruments ( lscp_client_t *pClient )  int lscp_get_midi_instruments ( lscp_client_t *pClient, int iMidiMap )
2871  {  {
2872      int iInstruments = -1;          int iInstruments = -1;
2873            char szQuery[LSCP_BUFSIZ];
2874    
2875            if (pClient == NULL)
2876                    return -1;
2877    
2878            // Lock this section up.
2879            lscp_mutex_lock(pClient->mutex);
2880    
2881      // Lock this section up.          strcpy(szQuery, "GET MIDI_INSTRUMENTS ");
     lscp_mutex_lock(pClient->mutex);  
2882    
2883      if (lscp_client_call(pClient, "GET MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          if (iMidiMap < 0)
2884          iInstruments = atoi(lscp_client_get_result(pClient));                  strcat(szQuery, "ALL");
2885            else
2886                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2887    
2888      // Unlock this section down.          strcat(szQuery, "\r\n");
     lscp_mutex_unlock(pClient->mutex);  
2889    
2890      return iInstruments;          if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2891                    iInstruments = atoi(lscp_client_get_result(pClient));
2892    
2893            // Unlock this section down.
2894            lscp_mutex_unlock(pClient->mutex);
2895    
2896            return iInstruments;
2897  }  }
2898    
2899    
2900  /**  /**
2901   *  Getting indeces of all MIDI instrument map entries:   *  Getting indeces of all MIDI instrument map entries:
2902   *  LIST MIDI_INSTRUMENTS   *  LIST MIDI_INSTRUMENTS ALL|<midi-map>
2903   *   *
2904   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
2905     *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
2906   *   *
2907   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the   *  @returns An array of @ref lscp_midi_instrument_t, terminated with the
2908   *  {-1,-1,-1} triplet, NULL otherwise.   *  {-1,-1,-1} triplet, NULL otherwise.
2909   */   */
2910  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 )
2911  {  {
2912      if (pClient == NULL)          char szQuery[LSCP_BUFSIZ];
2913          return NULL;  
2914            if (pClient == NULL)
2915                    return NULL;
2916    
2917      // Lock this section up.          // Lock this section up.
2918      lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2919    
2920      if (pClient->midi_instruments) {          if (pClient->midi_instruments) {
2921          lscp_midi_instruments_destroy(pClient->midi_instruments);                  lscp_midi_instruments_destroy(pClient->midi_instruments);
2922          pClient->midi_instruments = NULL;                  pClient->midi_instruments = NULL;
2923      }          }
2924    
2925      if (lscp_client_call(pClient, "LIST MIDI_INSTRUMENTS\r\n", 0) == LSCP_OK)          strcpy(szQuery, "LIST MIDI_INSTRUMENTS ");
         pClient->midi_instruments = lscp_midi_instruments_create(lscp_client_get_result(pClient));  
2926    
2927      // Unlock this section down.          if (iMidiMap < 0)
2928      lscp_mutex_unlock(pClient->mutex);                  strcat(szQuery, "ALL");
2929            else
2930                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
2931    
2932      return pClient->midi_instruments;          strcat(szQuery, "\r\n");
2933    
2934            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK)
2935                    pClient->midi_instruments = lscp_midi_instruments_create(
2936                            lscp_client_get_result(pClient));
2937    
2938            // Unlock this section down.
2939            lscp_mutex_unlock(pClient->mutex);
2940    
2941            return pClient->midi_instruments;
2942  }  }
2943    
2944    
2945  /**  /**
2946   *  Getting information about a MIDI instrument map entry:   *  Getting information about a MIDI instrument map entry:
2947   *  GET MIDI_INSTRUMENT INFO <midi-bank-msb> <midi-bank-lsb> <midi-prog>   *  GET MIDI_INSTRUMENT INFO <midi-map> <midi-bank> <midi-prog>
2948   *   *
2949   *  @param pClient      Pointer to client instance structure.   *  @param pClient      Pointer to client instance structure.
2950   *  @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 2953  lscp_midi_instrument_t *lscp_list_midi_i
2953   *  with all the information of the given MIDI instrument map entry,   *  with all the information of the given MIDI instrument map entry,
2954   *  or NULL in case of failure.   *  or NULL in case of failure.
2955   */   */
2956  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr )  lscp_midi_instrument_info_t *lscp_get_midi_instrument_info ( lscp_client_t *pClient,
2957            lscp_midi_instrument_t *pMidiInstr )
2958  {  {
2959      lscp_midi_instrument_info_t *pInstrInfo;          lscp_midi_instrument_info_t *pInstrInfo;
2960      char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2961      const char *pszResult;          const char *pszResult;
2962      const char *pszSeps = ":";          const char *pszSeps = ":";
2963      const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2964      char *pszToken;          char *pszToken;
2965      char *pch;          char *pch;
2966                struct _locale_t locale;
2967      if (pMidiInstr->bank_msb < 0 || pMidiInstr->bank_msb > 127)  
2968          return NULL;          if (pClient == NULL)
2969      if (pMidiInstr->bank_lsb < 0 || pMidiInstr->bank_lsb > 127)                  return NULL;
2970          return NULL;          if (pMidiInstr->map < 0)
2971      if (pMidiInstr->program < 0 || pMidiInstr->program > 127)                  return NULL;
2972          return NULL;          if (pMidiInstr->bank < 0 || pMidiInstr->bank > 16383)
2973                        return NULL;
2974      // Lock this section up.          if (pMidiInstr->prog < 0 || pMidiInstr->prog > 127)
2975      lscp_mutex_lock(pClient->mutex);                  return NULL;
2976        
2977      pInstrInfo = &(pClient->midi_instrument_info);          // Lock this section up.
2978      lscp_midi_instrument_info_reset(pInstrInfo);          lscp_mutex_lock(pClient->mutex);
2979        
2980      sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",          _save_and_set_c_locale(&locale);
2981          pMidiInstr->bank_msb, pMidiInstr->bank_lsb, pMidiInstr->program);  
2982      if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          pInstrInfo = &(pClient->midi_instrument_info);
2983          pszResult = lscp_client_get_result(pClient);          lscp_midi_instrument_info_reset(pInstrInfo);
2984          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));  
2985          while (pszToken) {          sprintf(szQuery, "GET MIDI_INSTRUMENT INFO %d %d %d\r\n",
2986              if (strcasecmp(pszToken, "NAME") == 0) {                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog);
2987                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
2988                  if (pszToken)                  pszResult = lscp_client_get_result(pClient);
2989                      lscp_unquote_dup(&(pInstrInfo->name), &pszToken);                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
2990              }                  while (pszToken) {
2991              else if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {                          if (strcasecmp(pszToken, "NAME") == 0) {
2992                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2993                  if (pszToken)                                  if (pszToken)
2994                      lscp_unquote_dup(&(pInstrInfo->engine_name), &pszToken);                                          lscp_unquote_dup(&(pInstrInfo->name), &pszToken);
2995              }                          }
2996              else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          else if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
2997                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2998                  if (pszToken)                                  if (pszToken)
2999                      lscp_unquote_dup(&(pInstrInfo->instrument_file), &pszToken);                                          lscp_unquote_dup(&(pInstrInfo->engine_name), &pszToken);
3000              }                          }
3001              else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
3002                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3003                  if (pszToken)                                  if (pszToken)
3004                      pInstrInfo->instrument_nr = atoi(lscp_ltrim(pszToken));                                          lscp_unquote_dup(&(pInstrInfo->instrument_file), &pszToken);
3005              }                          }
3006              else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
3007                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3008                  if (pszToken)                                  if (pszToken)
3009                      lscp_unquote_dup(&(pInstrInfo->instrument_name), &pszToken);                                          pInstrInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
3010              }                          }
3011              else if (strcasecmp(pszToken, "LOAD_MODE") == 0) {                          else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
3012                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3013                  if (pszToken) {                                  if (pszToken)
3014                      pszToken = lscp_ltrim(pszToken);                                          lscp_unquote_dup(&(pInstrInfo->instrument_name), &pszToken);
3015                      if (strcasecmp(pszToken, "ON_DEMAND") == 0)                          }
3016                          pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND;                          else if (strcasecmp(pszToken, "LOAD_MODE") == 0) {
3017                      else                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3018                      if (strcasecmp(pszToken, "ON_DEMAND_HOLD") == 0)                                  if (pszToken) {
3019                          pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND_HOLD;                                          pszToken = lscp_ltrim(pszToken);
3020                      else                                          if (strcasecmp(pszToken, "ON_DEMAND") == 0)
3021                      if (strcasecmp(pszToken, "PERSISTENT") == 0)                                                  pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND;
3022                          pInstrInfo->load_mode = LSCP_LOAD_PERSISTENT;                                          else
3023                      else                                          if (strcasecmp(pszToken, "ON_DEMAND_HOLD") == 0)
3024                          pInstrInfo->load_mode = LSCP_LOAD_DEFAULT;                                                  pInstrInfo->load_mode = LSCP_LOAD_ON_DEMAND_HOLD;
3025                  }                                          else
3026              }                                          if (strcasecmp(pszToken, "PERSISTENT") == 0)
3027              else if (strcasecmp(pszToken, "VOLUME") == 0) {                                                  pInstrInfo->load_mode = LSCP_LOAD_PERSISTENT;
3028                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          else
3029                  if (pszToken)                                                  pInstrInfo->load_mode = LSCP_LOAD_DEFAULT;
3030                      pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                  }
3031              }                          }
3032              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
3033          }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
3034      }                                  if (pszToken)
3035      else pInstrInfo = NULL;                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
3036                                }
3037      // Unlock this section down.                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
3038      lscp_mutex_unlock(pClient->mutex);                  }
3039                }
3040      return pInstrInfo;          else pInstrInfo = NULL;
3041    
3042            _restore_locale(&locale);
3043    
3044            // Unlock this section down.
3045            lscp_mutex_unlock(pClient->mutex);
3046    
3047            return pInstrInfo;
3048  }  }
3049    
3050    
3051  /**  /**
3052   *  Clear the MIDI instrumnet map:   *  Clear the MIDI instrumnet map:
3053   *  CLEAR MIDI_INSTRUMENTS   *  CLEAR MIDI_INSTRUMENTS ALL|<midi-map>
3054   *   *
3055   *  @param pClient          Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
3056   *  @param iSamplerChannel  Sampler channel number.   *  @param iMidiMap MIDI instrument map number, or @ref LSCP_MIDI_MAP_ALL .
3057   *   *
3058   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
3059   */   */
3060  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient )  lscp_status_t lscp_clear_midi_instruments  ( lscp_client_t *pClient, int iMidiMap )
3061    {
3062            char szQuery[LSCP_BUFSIZ];
3063    
3064            strcpy(szQuery, "CLEAR MIDI_INSTRUMENTS ");
3065    
3066            if (iMidiMap < 0)
3067                    strcat(szQuery, "ALL");
3068            else
3069                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
3070    
3071            strcat(szQuery, "\r\n");
3072    
3073            return lscp_client_query(pClient, szQuery);
3074    }
3075    
3076    
3077    /**
3078     * Open an instrument editor application for the instrument
3079     * on the given sampler channel:
3080     * EDIT CHANNEL INSTRUMENT <sampler-channel>
3081     *
3082     * @param pClient         Pointer to client instance structure.
3083     * @param iSamplerChannel Sampler Channel.
3084     *
3085     * @returns LSCP_OK on success, LSCP_FAILED otherwise.
3086     */
3087    lscp_status_t lscp_edit_channel_instrument ( lscp_client_t *pClient, int iSamplerChannel )
3088  {  {
3089      return lscp_client_query(pClient, "CLEAR MIDI_INSTRUMENTS\r\n");          char szQuery[LSCP_BUFSIZ];
3090    
3091            if (iSamplerChannel < 0)
3092                    return LSCP_FAILED;
3093    
3094            sprintf(szQuery, "EDIT CHANNEL INSTRUMENT %d\r\n", iSamplerChannel);
3095    
3096            return lscp_client_query(pClient, szQuery);
3097  }  }
3098    
3099    

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

  ViewVC Help
Powered by ViewVC