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

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

  ViewVC Help
Powered by ViewVC