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

Legend:
Removed from v.562  
changed lines
  Added in v.3666

  ViewVC Help
Powered by ViewVC