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

Legend:
Removed from v.188  
changed lines
  Added in v.3665

  ViewVC Help
Powered by ViewVC