/[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 107 by capela, Fri Jun 4 21:06:59 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_set_result (lscp_client_t *pClient, char *pszResult, int iErrno);  static void _lscp_client_evt_proc (void *pvClient);
47  static void _lscp_client_udp_proc   (void *pvClient);  
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  // Helper functions.  // General helper functions.
55    
56  // Result buffer internal settler.  struct _locale_t {
57  static void _lscp_client_set_result ( lscp_client_t *pClient, char *pszResult, int iErrno )          char numeric[32];
58            char ctype[32];
59    };
60    
61    // we need to ensure a constant locale setting e.g. for parsing
62    // floating point numbers with atof(), as the floating point separator
63    // character varies by the invidual locale settings
64    static void _save_and_set_c_locale(struct _locale_t* locale)
65  {  {
66      if (pClient->pszResult)          strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
67          free(pClient->pszResult);          strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
68      pClient->pszResult = NULL;          setlocale(LC_NUMERIC, "C");
69            setlocale(LC_CTYPE, "C");
70    }
71    
72      pClient->iErrno = iErrno;  // 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      if (pszResult)  // seems the standard atof() function doesnt care much about locale
80          pClient->pszResult = strdup(lscp_ltrim(pszResult));  // 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  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
89  // UDP service (datagram oriented).  // Event service (datagram oriented).
90    
91  static void _lscp_client_udp_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      struct sockaddr_in addr;  
95      int   cAddr;          fd_set fds;                         // File descriptor list for select().
96      char  achBuffer[LSCP_BUFSIZ];          int    fd, fdmax;                   // Maximum file descriptor number.
97      int   cchBuffer;          struct timeval tv;                  // For specifying a timeout value.
98      const char *pszSeps = " \r\n";          int    iSelect;                     // Holds select return status.
99      char *pszToken;          int    iTimeout;
100      char *pch;  
101            char   achBuffer[LSCP_BUFSIZ];
102            int    cchBuffer;
103            const char *pszSeps = ":\r\n";
104            char  *pszToken;
105            char  *pch;
106            int    cchToken;
107    
108            lscp_event_t event;
109    
110  #ifdef DEBUG  #ifdef DEBUG
111      fprintf(stderr, "_lscp_client_udp_proc: Client waiting for events.\n");          fprintf(stderr, "_lscp_client_evt_proc: Client waiting for events.\n");
112  #endif  #endif
113    
114      while (pClient->udp.iState) {          while (pClient->evt.iState) {
115          cAddr = sizeof(struct sockaddr_in);  
116          cchBuffer = recvfrom(pClient->udp.sock, achBuffer, sizeof(achBuffer), 0, (struct sockaddr *) &addr, &cAddr);                  // Prepare for waiting on select...
117          if (cchBuffer > 0) {                  fd = (int) pClient->evt.sock;
118                    FD_ZERO(&fds);
119                    FD_SET((unsigned int) fd, &fds);
120                    fdmax = fd;
121    
122                    // Use the timeout (x10) select feature ...
123                    iTimeout = 10 * pClient->iTimeout;
124                    if (iTimeout >= 1000) {
125                            tv.tv_sec = iTimeout / 1000;
126                            iTimeout -= tv.tv_sec * 1000;
127                    }
128                    else tv.tv_sec = 0;
129                    tv.tv_usec = iTimeout * 1000;
130    
131                    // Wait for event...
132                    iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
133                    if (iSelect > 0 && FD_ISSET(fd, &fds)) {
134                            // May recv now...
135                            cchBuffer = recv(pClient->evt.sock, achBuffer, sizeof(achBuffer), 0);
136                            if (cchBuffer > 0) {
137                                    // Make sure received buffer it's null terminated.
138                                    achBuffer[cchBuffer] = (char) 0;
139                                    pch = achBuffer;
140                                    do {
141                                            // Parse for the notification event message...
142                                            pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have "NOTIFY"
143                                            if (strcasecmp(pszToken, "NOTIFY") == 0) {
144                                                    pszToken = lscp_strtok(NULL, pszSeps, &(pch));
145                                                    event    = lscp_event_from_text(pszToken);
146                                                    // And pick the rest of data...
147                                                    pszToken = lscp_strtok(NULL, pszSeps, &(pch));
148                                                    cchToken = (pszToken == NULL ? 0 : strlen(pszToken));
149                                                    // Double-check if we're really up to it...
150                                                    if (pClient->events & event) {
151                                                            // Invoke the client event callback...
152                                                            if ((*pClient->pfnCallback)(
153                                                                            pClient,
154                                                                            event,
155                                                                            pszToken,
156                                                                            cchToken,
157                                                                            pClient->pvData) != LSCP_OK) {
158                                                                    pClient->evt.iState = 0;
159                                                            }
160                                                    }
161                                            }
162                                    } while (*pch);
163                            } else {
164                                    lscp_socket_perror("_lscp_client_evt_proc: recv");
165                                    pClient->evt.iState = 0;
166                                    pClient->iErrno = -errno;
167                            }
168                    }   // Check if select has in error.
169                    else if (iSelect < 0) {
170                            lscp_socket_perror("_lscp_client_evt_proc: select");
171                            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              lscp_socket_trace("_lscp_client_udp_proc: recvfrom", &addr, achBuffer, cchBuffer);          fprintf(stderr, "_lscp_client_evt_proc: Client closing.\n");
181  #endif  #endif
182              if (strncasecmp(achBuffer, "PING ", 5) == 0) {  }
183                  // Make sure received buffer it's null terminated.  
184                  achBuffer[cchBuffer] = (char) 0;  
185                  lscp_strtok(achBuffer, pszSeps, &(pch));       // Skip "PING"  //-------------------------------------------------------------------------
186                  lscp_strtok(NULL, pszSeps, &(pch));            // Skip port (must be the same as in addr)  // Event subscription helpers.
187                  pszToken = lscp_strtok(NULL, pszSeps, &(pch)); // Have session-id.  
188                  if (pszToken) {  // Open the event service socket connection.
189                      // Set now client's session-id, if not already  static lscp_status_t _lscp_client_evt_connect ( lscp_client_t *pClient )
190                      if (pClient->sessid == NULL)  {
191                          pClient->sessid = strdup(pszToken);          lscp_socket_t sock;
192                      if (pClient->sessid && strcmp(pszToken, pClient->sessid) == 0) {          struct sockaddr_in addr;
193                          sprintf(achBuffer, "PONG %s\r\n", pClient->sessid);          int cAddr;
194                          cchBuffer = strlen(achBuffer);  #if defined(WIN32)
195                          if (sendto(pClient->udp.sock, achBuffer, cchBuffer, 0, (struct sockaddr *) &addr, cAddr) < cchBuffer)          int iSockOpt = (-1);
196                              lscp_socket_perror("_lscp_client_udp_proc: sendto");  #endif
197  #ifdef DEBUG  
198                          fprintf(stderr, "> %s", achBuffer);          // Prepare the event connection socket...
199            sock = socket(AF_INET, SOCK_STREAM, 0);
200            if (sock == INVALID_SOCKET) {
201                    lscp_socket_perror("_lscp_client_evt_connect: socket");
202                    return LSCP_FAILED;
203            }
204    
205    #if defined(WIN32)
206            if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
207                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
208                    lscp_socket_perror("lscp_client_evt_connect: setsockopt(SO_DONTLINGER)");
209  #endif  #endif
                     }  
                 }  
                 // Done with life proof.  
             } else {  
                 //  
                 if ((*pClient->pfnCallback)(  
                         pClient,  
                         achBuffer,  
                         cchBuffer,  
                         pClient->pvData) != LSCP_OK) {  
                     pClient->udp.iState = 0;  
                 }  
             }  
         } else {  
             lscp_socket_perror("_lscp_client_udp_proc: recvfrom");  
             pClient->udp.iState = 0;  
         }  
     }  
210    
211  #ifdef DEBUG  #ifdef DEBUG
212      fprintf(stderr, "_lscp_client_udp_proc: Client closing.\n");          lscp_socket_getopts("_lscp_client_evt_connect:", sock);
213  #endif  #endif
214    
215            // Use same address of the command connection.
216            cAddr = sizeof(struct sockaddr_in);
217            memmove((char *) &addr, &(pClient->cmd.addr), cAddr);
218    
219            // Start the connection...
220            if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
221                    lscp_socket_perror("_lscp_client_evt_connect: connect");
222                    closesocket(sock);
223                    return LSCP_FAILED;
224            }
225    
226            // Set our socket agent struct...
227            lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr);
228    
229            // And finally the service thread...
230            return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0);
231    }
232    
233    
234    // Subscribe to a single event.
235    static lscp_status_t _lscp_client_evt_request ( lscp_client_t *pClient,
236            int iSubscribe, lscp_event_t event )
237    {
238            const char *pszEvent;
239            char  szQuery[LSCP_BUFSIZ];
240            int   cchQuery;
241    
242            if (pClient == NULL)
243                    return LSCP_FAILED;
244    
245            // Which (single) event?
246            pszEvent = lscp_event_to_text(event);
247            if (pszEvent == NULL)
248                    return LSCP_FAILED;
249    
250            // Build the query string...
251            cchQuery = sprintf(szQuery, "%sSUBSCRIBE %s\n\n",
252                    (iSubscribe == 0 ? "UN" : ""), pszEvent);
253            // Just send data, forget result...
254            if (send(pClient->evt.sock, szQuery, cchQuery, 0) < cchQuery) {
255                    lscp_socket_perror("_lscp_client_evt_request: send");
256                    return LSCP_FAILED;
257            }
258    
259            // Wait on response.
260            lscp_cond_wait(pClient->cond, pClient->mutex);
261    
262            // Update as naively as we can...
263            if (iSubscribe)
264                    pClient->events |=  event;
265            else
266                    pClient->events &= ~event;
267    
268            return LSCP_OK;
269  }  }
270    
271    
# Line 127  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 148  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      int iSockOpt = (-1);  #else
312            struct hostent *pHost;
313      if (pfnCallback == NULL) {          struct sockaddr_in addr;
314          fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");          int cAddr;
315          return NULL;  #endif  /* !USE_GETADDRINFO */
316      }          lscp_socket_t sock;
   
     pHost = gethostbyname(pszHost);  
     if (pHost == NULL) {  
         lscp_socket_perror("lscp_client_create: gethostbyname");  
         return NULL;  
     }  
   
     // Allocate client descriptor...  
   
     pClient = (lscp_client_t *) malloc(sizeof(lscp_client_t));  
     if (pClient == NULL) {  
         fprintf(stderr, "lscp_client_create: Out of memory.\n");  
         return NULL;  
     }  
     memset(pClient, 0, sizeof(lscp_client_t));  
   
     pClient->pfnCallback = pfnCallback;  
     pClient->pvData = pvData;  
   
 #ifdef DEBUG  
     fprintf(stderr, "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n", pClient, pszHost, iPort);  
 #endif  
   
     // Prepare the TCP connection socket...  
   
     sock = socket(AF_INET, SOCK_STREAM, 0);  
     if (sock == INVALID_SOCKET) {  
         lscp_socket_perror("lscp_client_create: tcp: socket");  
         free(pClient);  
         return NULL;  
     }  
   
317  #if defined(WIN32)  #if defined(WIN32)
318      if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          int iSockOpt = (-1);
         lscp_socket_perror("lscp_client_create: tcp: setsockopt(SO_DONTLINGER)");  
319  #endif  #endif
320    
321  #ifdef DEBUG          if (pfnCallback == NULL) {
322      lscp_socket_getopts("lscp_client_create: tcp", sock);                  fprintf(stderr, "lscp_client_create: Invalid client callback function.\n");
323  #endif                  return NULL;
324            }
325    
326    #if defined(USE_GETADDRINFO)
327    
328            // Convert port number to string/name...
329            snprintf(szPort, sizeof(szPort), "%d", iPort);
330    
331            // Obtain address(es) matching host/port...
332            memset(&hints, 0, sizeof(struct addrinfo));
333            hints.ai_family = AF_INET;
334            hints.ai_socktype = SOCK_STREAM;
335    
336            result = NULL;
337    
338            if (getaddrinfo(pszHost, szPort, &hints, &result)) {
339                    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      cAddr = sizeof(struct sockaddr_in);          pClient->pfnCallback = pfnCallback;
364      memset((char *) &addr, 0, cAddr);          pClient->pvData = pvData;
     addr.sin_family = pHost->h_addrtype;  
     memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);  
     addr.sin_port = htons((short) iPort);  
   
     if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {  
         lscp_socket_perror("lscp_client_create: tcp: connect");  
         closesocket(sock);  
         free(pClient);  
         return NULL;  
     }  
   
     lscp_socket_agent_init(&(pClient->tcp), sock, &addr, cAddr);  
365    
366  #ifdef DEBUG  #ifdef DEBUG
367      fprintf(stderr, "lscp_client_create: tcp: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->tcp.sock, inet_ntoa(pClient->tcp.addr.sin_addr), ntohs(pClient->tcp.addr.sin_port));          fprintf(stderr,
368                    "lscp_client_create: pClient=%p: pszHost=%s iPort=%d.\n",
369                     pClient, pszHost, iPort);
370  #endif  #endif
371    
372      // Prepare the UDP datagram service socket...          // Prepare the command connection socket...
373    
374      sock = socket(AF_INET, SOCK_DGRAM, 0);  #if defined(USE_GETADDRINFO)
     if (sock == INVALID_SOCKET) {  
         lscp_socket_perror("lscp_client_create: udp: socket");  
         lscp_socket_agent_free(&(pClient->tcp));  
         free(pClient);  
         return NULL;  
     }  
375    
376      if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)          // getaddrinfo() returns a list of address structures;
377          lscp_socket_perror("lscp_client_create: udp: setsockopt(SO_REUSEADDR)");          // try each address until we successfully connect(2);
378            // 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)
428            if (setsockopt(sock, SOL_SOCKET, SO_DONTLINGER,
429                            (char *) &iSockOpt, sizeof(int)) == SOCKET_ERROR)
430                    lscp_socket_perror("lscp_client_create: cmd: setsockopt(SO_DONTLINGER)");
431    #endif
432    
433  #ifdef DEBUG  #ifdef DEBUG
434      lscp_socket_getopts("lscp_client_create: udp", 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 = AF_INET;          addr.sin_family = pHost->h_addrtype;
440      addr.sin_addr.s_addr = htonl(INADDR_ANY);          memmove((char *) &(addr.sin_addr), pHost->h_addr, pHost->h_length);
441      addr.sin_port = htons(0);          addr.sin_port = htons((short) iPort);
442    
443      if (bind(sock, (const struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {          if (connect(sock, (struct sockaddr *) &addr, cAddr) == SOCKET_ERROR) {
444          lscp_socket_perror("lscp_client_create: udp: bind");                  lscp_socket_perror("lscp_client_create: cmd: connect");
445          lscp_socket_agent_free(&(pClient->tcp));                  closesocket(sock);
446          closesocket(sock);                  free(pClient);
447          free(pClient);                  return NULL;
448          return NULL;          }
449      }  
450            // Initialize the command socket agent struct...
451      if (getsockname(sock, (struct sockaddr *) &addr, &cAddr) == SOCKET_ERROR) {          lscp_socket_agent_init(&(pClient->cmd), sock, &addr, cAddr);
         lscp_socket_perror("lscp_client_create: udp: getsockname");  
         lscp_socket_agent_free(&(pClient->tcp));  
         closesocket(sock);  
         free(pClient);  
         return NULL;  
     }  
452    
453      lscp_socket_agent_init(&(pClient->udp), sock, &addr, cAddr);  #endif  /* !USE_GETADDRINFO */
454    
455  #ifdef DEBUG  #ifdef DEBUG
456      fprintf(stderr, "lscp_client_create: udp: pClient=%p: sock=%d addr=%s port=%d.\n", pClient, pClient->udp.sock, inet_ntoa(pClient->udp.addr.sin_addr), ntohs(pClient->udp.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      // No session id, yet.          // Initialize the event service socket struct...
464      pClient->sessid = NULL;          lscp_socket_agent_init(&(pClient->evt), INVALID_SOCKET, NULL, 0);
465      // Initialize cached members.          // No events subscribed, yet.
466      pClient->audio_drivers = NULL;          pClient->events = LSCP_EVENT_NONE;
467      pClient->midi_drivers = NULL;          // Initialize cached members.
468      pClient->engines = NULL;          pClient->audio_drivers = NULL;
469      lscp_driver_info_init(&(pClient->audio_info));          pClient->midi_drivers = NULL;
470      lscp_driver_info_init(&(pClient->midi_info));          pClient->audio_devices = NULL;
471      lscp_engine_info_init(&(pClient->engine_info));          pClient->midi_devices = NULL;
472      lscp_channel_info_init(&(pClient->channel_info));          pClient->engines = NULL;
473      // Initialize error stuff.          pClient->channels = NULL;
474      pClient->pszResult = NULL;          pClient->fxsends = NULL;
475      pClient->iErrno = -1;          pClient->midi_instruments = NULL;
476      // Stream usage stuff.          pClient->midi_maps = NULL;
477      pClient->buffer_fill = NULL;          pClient->midi_map_name = NULL;
478      pClient->iStreamCount = 0;          lscp_driver_info_init(&(pClient->audio_driver_info));
479      // Default timeout value.          lscp_driver_info_init(&(pClient->midi_driver_info));
480      pClient->iTimeout = LSCP_TIMEOUT_MSECS;          lscp_device_info_init(&(pClient->audio_device_info));
481            lscp_device_info_init(&(pClient->midi_device_info));
482      // Initialize the transaction mutex.          lscp_param_info_init(&(pClient->audio_param_info));
483      lscp_mutex_init(pClient->mutex);          lscp_param_info_init(&(pClient->midi_param_info));
484            lscp_device_port_info_init(&(pClient->audio_channel_info));
485      // Now's finally time to startup threads...          lscp_device_port_info_init(&(pClient->midi_port_info));
486      // UDP service thread...          lscp_param_info_init(&(pClient->audio_channel_param_info));
487      if (lscp_socket_agent_start(&(pClient->udp), _lscp_client_udp_proc, pClient, 0) != LSCP_OK) {          lscp_param_info_init(&(pClient->midi_port_param_info));
488          lscp_socket_agent_free(&(pClient->tcp));          lscp_server_info_init(&(pClient->server_info));
489          lscp_socket_agent_free(&(pClient->udp));          lscp_engine_info_init(&(pClient->engine_info));
490          lscp_mutex_destroy(pClient->mutex);          lscp_channel_info_init(&(pClient->channel_info));
491          free(pClient);          lscp_fxsend_info_init(&(pClient->fxsend_info));
492          return NULL;          lscp_midi_instrument_info_init(&(pClient->midi_instrument_info));
493      }          // Initialize error stuff.
494            pClient->pszResult = NULL;
495            pClient->iErrno = -1;
496            // Stream usage stuff.
497            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 310  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->udp));  //  lscp_socket_agent_join(&(pClient->evt));
527      lscp_socket_agent_join(&(pClient->tcp));          lscp_socket_agent_join(&(pClient->cmd));
528    
529      return LSCP_OK;          return LSCP_OK;
530  }  }
531    
532    
# Line 333  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      // Free session-id, if any.          // Lock this section up.
550      if (pClient->sessid)          lscp_mutex_lock(pClient->mutex);
         free(pClient->sessid);  
     pClient->sessid = NULL;  
     // Free up all cached members.  
     lscp_channel_info_reset(&(pClient->channel_info));  
     lscp_engine_info_reset(&(pClient->engine_info));  
     lscp_driver_info_reset(&(pClient->midi_info));  
     lscp_driver_info_reset(&(pClient->audio_info));  
     // Free available engine table.  
     lscp_szsplit_destroy(pClient->audio_drivers);  
     lscp_szsplit_destroy(pClient->midi_drivers);  
     lscp_szsplit_destroy(pClient->engines);  
     // 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);  
     // Frre 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->udp));  
     lscp_socket_agent_free(&(pClient->tcp));  
551    
552      // Last but not least, free good ol'transaction mutex.          // Free up all cached members.
553      lscp_mutex_destroy(pClient->mutex);          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      free(pClient);          free(pClient);
610    
611      return LSCP_OK;          return LSCP_OK;
612  }  }
613    
614    
# Line 389  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 408  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;          return pClient->iTimeout;
648    }
649    
650    /**
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    
665  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
666  // Client common protocol functions.  // Client common protocol functions.
667    
   
668  /**  /**
669   *  Submit a command query line string to the server. The query string   *  Submit a command query line string to the server. The query string
670   *  must be cr/lf and null terminated. Besides the return code, the   *  must be cr/lf and null terminated. Besides the return code, the
# Line 434  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      fd_set fds;                         // File descriptor list for select().          lscp_status_t ret;
     int    fd, fdmax;                   // Maximum file descriptor number.  
     struct timeval tv;                  // For specifying a timeout value.  
     int    iSelect;                     // Holds select return status.  
     int    iTimeout;  
     int    cchQuery;  
     char   achResult[LSCP_BUFSIZ];  
     int    cchResult;  
     const  char *pszSeps = ":[]";  
     char  *pszResult;  
     char  *pszToken;  
     char  *pch;  
     int    iErrno;  
   
     lscp_status_t ret = LSCP_FAILED;  
   
     if (pClient == NULL)  
         return ret;  
   
     // Lock this section up.  
     lscp_mutex_lock(pClient->mutex);  
   
     pszResult = NULL;  
     iErrno = -1;  
   
     // Send data, and then, wait for the result...  
     cchQuery = strlen(pszQuery);  
     if (send(pClient->tcp.sock, pszQuery, cchQuery, 0) < cchQuery) {  
         lscp_socket_perror("lscp_client_query: send");  
         lscp_mutex_unlock(pClient->mutex);  
         return ret;  
     }  
   
     // Prepare for waiting on select...  
     fd = (int) pClient->tcp.sock;  
     FD_ZERO(&fds);  
     FD_SET((unsigned int) fd, &fds);  
     fdmax = fd;  
   
     // Use the timeout select feature...  
     iTimeout = pClient->iTimeout;  
     if (iTimeout > 1000) {  
         tv.tv_sec = iTimeout / 1000;  
         iTimeout -= tv.tv_sec * 1000;  
     }  
     else tv.tv_sec = 0;  
     tv.tv_usec = iTimeout * 1000;  
   
     // Wait for event...  
     iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);  
     if (iSelect > 0 && FD_ISSET(fd, &fds)) {  
         // May recv now...  
         cchResult = recv(pClient->tcp.sock, achResult, sizeof(achResult), 0);  
         if (cchResult > 0) {  
             // Assume early success.  
             ret = LSCP_OK;  
             // Always force the result to be null terminated (and trim trailing CRLFs)!  
             while (cchResult > 0 && (achResult[cchResult - 1] == '\n' || achResult[cchResult- 1] == '\r'))  
                 cchResult--;  
             achResult[cchResult] = (char) 0;  
             // Check if the response it's an error or warning message.  
             if (strncasecmp(achResult, "WRN:", 4) == 0)  
                 ret = LSCP_WARNING;  
             else if (strncasecmp(achResult, "ERR:", 4) == 0)  
                 ret = LSCP_ERROR;  
             // So we got a result...  
             if (ret == LSCP_OK) {  
                 // Reset errno in case of success.  
                 iErrno = 0;  
                 // Is it a special successful response?  
                 if (strncasecmp(achResult, "OK[", 3) == 0) {  
                     // Parse the OK message, get the return string under brackets...  
                     pszToken = lscp_strtok(achResult, pszSeps, &(pch));  
                     if (pszToken)  
                         pszResult = lscp_strtok(NULL, pszSeps, &(pch));  
                 }  
                 else pszResult = achResult;  
                 // The result string is now set to the command response, if any.  
             } else {  
                 // Parse the error/warning message, skip first colon...  
                 pszToken = lscp_strtok(achResult, pszSeps, &(pch));  
                 if (pszToken) {  
                     // Get the error number...  
                     pszToken = lscp_strtok(NULL, pszSeps, &(pch));  
                     if (pszToken) {  
                         iErrno = atoi(pszToken);  
                         // And make the message text our final result.  
                         pszResult = lscp_strtok(NULL, pszSeps, &(pch));  
                     }  
                 }  
                 // The result string is set to the error/warning message text.  
             }  
         }  
         else if (cchResult == 0) {  
             // Fake a result message.  
             pszResult = "Server terminated the connection";  
             ret = LSCP_QUIT;  
         }  
         else lscp_socket_perror("lscp_client_query: recv");  
     }   // Check if select has timed out.  
     else if (iSelect == 0) {  
         // Fake a result message.  
         pszResult = "Timeout during receive operation";  
         ret = LSCP_TIMEOUT;  
     }  
     else lscp_socket_perror("lscp_client_query: select");  
684    
685      // Make the result official...          if (pClient == NULL)
686      _lscp_client_set_result(pClient, pszResult, iErrno);                  return LSCP_FAILED;
687    
688      // Can go on with it...          // Lock this section up.
689      lscp_mutex_unlock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
690    
691      return ret;          // Just make the now guarded call.
692  }          ret = lscp_client_call(pClient, pszQuery, 0);
693    
694            // Unlock this section down.
695            lscp_mutex_unlock(pClient->mutex);
696    
697            return ret;
698    }
699    
700  /**  /**
701   *  Get the last received result string. In case of error or warning,   *  Get the last received result string. In case of error or warning,
# Line 562  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 579  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 590  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 UDP event messages:   *  Register frontend for receiving event messages by the sampler backend.
740   *  SUBSCRIBE NOTIFICATION <udp-port>   *  @e Caution: since liblscp v0.5.5.4 you have to call lscp_client_subscribe()
741     *  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   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_status_t lscp_client_subscribe ( lscp_client_t *pClient, lscp_event_t events )
767  {  {
768      lscp_status_t ret;          lscp_status_t ret = LSCP_OK;
769      char szQuery[LSCP_BUFSIZ];          lscp_event_t currentEvent;
     const char *pszResult;  
     const char *pszSeps = "[]";  
     char *pszToken;  
     char *pch;  
770    
771      if (pClient == NULL || pClient->sessid)          if (pClient == NULL)
772          return LSCP_FAILED;                  return LSCP_FAILED;
773    
774      sprintf(szQuery, "SUBSCRIBE NOTIFICATION %d\r\n", ntohs(pClient->udp.addr.sin_port));          // Lock this section up.
775      ret = lscp_client_query(pClient, szQuery);          lscp_mutex_lock(pClient->mutex);
776      if (ret == LSCP_OK) {  
777          pszResult = lscp_client_get_result(pClient);          // If applicable, start the alternate connection...
778  #ifdef DEBUG          if (pClient->events == LSCP_EVENT_NONE)
779          fprintf(stderr, "lscp_client_subscribe: %s\n", pszResult);                  ret = _lscp_client_evt_connect(pClient);
780  #endif  
781          // Check for the session-id on "OK[sessid]" response.          // Send the subscription commands.
782          pszToken = lscp_strtok(pszResult, pszSeps, &(pch));          if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT))
783          if (pszToken && strcasecmp(pszToken, "OK") == 0) {                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT);
784              pszToken = lscp_strtok(NULL, pszSeps, &(pch));          if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT))
785              if (pszToken)                  ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT);
786                  pClient->sessid = strdup(pszToken);          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.
858     *  @param events   LSCP event to unsubscribe.
859     *
860     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
861     */
862    lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient, lscp_event_t events )
863    {
864            lscp_status_t ret = LSCP_OK;
865            lscp_event_t currentEvent;
866    
867            if (pClient == NULL)
868                    return LSCP_FAILED;
869    
870      return ret;          // Lock this section up.
871            lscp_mutex_lock(pClient->mutex);
872    
873            // Send the unsubscription commands.
874            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            return ret;
926  }  }
927    
928    
929  /**  /**
930   *  Deregister frontend for not receiving UDP event messages anymore:   *  Getting current subscribed events.
  *  UNSUBSCRIBE NOTIFICATION <session-id>  
931   *   *
932   *  @param pClient  Pointer to client instance structure.   *  @param pClient  Pointer to client instance structure.
933   *   *
934   *  @returns LSCP_OK on success, LSCP_FAILED otherwise.   *  @returns The current subscrived bit-wise OR'ed event flags.
935   */   */
936  lscp_status_t lscp_client_unsubscribe ( lscp_client_t *pClient )  lscp_event_t lscp_client_get_events ( lscp_client_t *pClient )
937  {  {
938      lscp_status_t ret;          if (pClient == NULL)
939      char szQuery[LSCP_BUFSIZ];                  return LSCP_EVENT_NONE;
940    
941      if (pClient == NULL)          return pClient->events;
         return LSCP_FAILED;  
     if (pClient->sessid == NULL)  
         return LSCP_FAILED;  
   
     sprintf(szQuery, "UNSUBSCRIBE NOTIFICATION %s\n\n", pClient->sessid);  
     ret = lscp_client_query(pClient, szQuery);  
     if (ret == LSCP_OK) {  
 #ifdef DEBUG  
         fprintf(stderr, "lscp_client_unsubscribe: %s\n", lscp_client_get_result(pClient));  
 #endif  
         // Bail out session-id string.  
         free(pClient->sessid);  
         pClient->sessid = NULL;  
     }  
   
     return ret;  
942  }  }
943    
944    
# Line 676  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];
963    
964            if (pszFileName == NULL || iSamplerChannel < 0)
965                    return LSCP_FAILED;
966    
967            sprintf(szQuery, "LOAD INSTRUMENT '%s' %d %d\r\n",
968                    pszFileName, iInstrIndex, iSamplerChannel);
969            return lscp_client_query(pClient, szQuery);
970    }
971    
972    
973    /**
974     *  Loading an instrument in the background (non modal):
975     *  LOAD INSTRUMENT NON_MODAL <filename> <instr-index> <sampler-channel>
976     *
977     *  @param pClient          Pointer to client instance structure.
978     *  @param pszFileName      Instrument file name.
979     *  @param iInstrIndex      Instrument index number.
980     *  @param iSamplerChannel  Sampler Channel.
981     *
982     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
983     */
984    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 %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 700  lscp_status_t lscp_load_instrument ( lsc Line 1007  lscp_status_t lscp_load_instrument ( lsc
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 721  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      if (lscp_client_query(pClient, "GET CHANNELS\r\n") == LSCP_OK)  
1034          iChannels = atoi(lscp_client_get_result(pClient));          if (pClient == NULL)
1035      return iChannels;                  return -1;
1036    
1037            // Lock this section up.
1038            lscp_mutex_lock(pClient->mutex);
1039    
1040            if (lscp_client_call(pClient, "GET CHANNELS\r\n", 0) == LSCP_OK)
1041                    iChannels = atoi(lscp_client_get_result(pClient));
1042    
1043            // Unlock this section doen.
1044            lscp_mutex_unlock(pClient->mutex);
1045    
1046            return iChannels;
1047    }
1048    
1049    
1050    /**
1051     *  List current sampler channels number identifiers:
1052     *  LIST CHANNELS
1053     *
1054     *  @param pClient  Pointer to client instance structure.
1055     *
1056     *  @returns An array of the sampler channels identifiers as positive integers,
1057     *  terminated with -1 on success, NULL otherwise.
1058     */
1059    int *lscp_list_channels ( lscp_client_t *pClient )
1060    {
1061            const char *pszSeps = ",";
1062    
1063            if (pClient == NULL)
1064                    return NULL;
1065    
1066            // Lock this section up.
1067            lscp_mutex_lock(pClient->mutex);
1068    
1069            if (pClient->channels) {
1070                    lscp_isplit_destroy(pClient->channels);
1071                    pClient->channels = NULL;
1072            }
1073    
1074            if (lscp_client_call(pClient, "LIST CHANNELS\r\n", 0) == LSCP_OK)
1075                    pClient->channels = lscp_isplit_create(lscp_client_get_result(pClient), pszSeps);
1076    
1077            // Unlock this section down.
1078            lscp_mutex_unlock(pClient->mutex);
1079    
1080            return pClient->channels;
1081  }  }
1082    
1083    
# Line 739  int lscp_get_channels ( lscp_client_t *p Line 1092  int lscp_get_channels ( lscp_client_t *p
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      if (lscp_client_query(pClient, "ADD CHANNEL\r\n") == LSCP_OK)  
1097          iSamplerChannel = atoi(lscp_client_get_result(pClient));          if (pClient == NULL)
1098      return iSamplerChannel;                  return -1;
1099    
1100            // Lock this section up.
1101            lscp_mutex_lock(pClient->mutex);
1102    
1103            if (lscp_client_call(pClient, "ADD CHANNEL\r\n", 0) == LSCP_OK)
1104                    iSamplerChannel = atoi(lscp_client_get_result(pClient));
1105    
1106            // Unlock this section down.
1107            lscp_mutex_unlock(pClient->mutex);
1108    
1109            return iSamplerChannel;
1110  }  }
1111    
1112    
# Line 757  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            if (pClient == NULL)
1177                    return NULL;
1178    
1179            // Lock this section up.
1180            lscp_mutex_lock(pClient->mutex);
1181    
1182      if (pClient->engines) {          if (pClient->engines) {
1183          lscp_szsplit_destroy(pClient->engines);                  lscp_szsplit_destroy(pClient->engines);
1184          pClient->engines = NULL;                  pClient->engines = NULL;
1185      }          }
1186    
1187      if (lscp_client_query(pClient, "GET AVAILABLE_ENGINES\r\n") == LSCP_OK)          if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n", 0) == LSCP_OK)
1188          pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps);                  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 802  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      pEngineInfo = &(pClient->engine_info);                  return NULL;
1222      lscp_engine_info_reset(pEngineInfo);  
1223            // Lock this section up.
1224      sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);          lscp_mutex_lock(pClient->mutex);
1225      if (lscp_client_query(pClient, szQuery) != LSCP_OK)  
1226          return NULL;          pEngineInfo = &(pClient->engine_info);
1227            lscp_engine_info_reset(pEngineInfo);
1228      pszResult = lscp_client_get_result(pClient);  
1229      pszToken = lscp_strtok(pszResult, pszSeps, &(pch));          sprintf(szQuery, "GET ENGINE INFO %s\r\n", pszEngineName);
1230      while (pszToken) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1231          if (strcasecmp(pszToken, "DESCRIPTION") == 0) {                  pszResult = lscp_client_get_result(pClient);
1232              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1233              if (pszToken)                  while (pszToken) {
1234                  pEngineInfo->description = lscp_unquote(&pszToken, 1);                          if (strcasecmp(pszToken, "DESCRIPTION") == 0) {
1235          }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1236          else if (strcasecmp(pszToken, "VERSION") == 0) {                                  if (pszToken)
1237              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          lscp_unquote_dup(&(pEngineInfo->description), &pszToken);
1238              if (pszToken)                          }
1239                  pEngineInfo->version = lscp_unquote(&pszToken, 1);                          else if (strcasecmp(pszToken, "VERSION") == 0) {
1240          }                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1241          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                  if (pszToken)
1242      }                                          lscp_unquote_dup(&(pEngineInfo->version), &pszToken);
1243                            }
1244                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1245                    }
1246            }
1247            else pEngineInfo = NULL;
1248    
1249            // Unlock this section down.
1250            lscp_mutex_unlock(pClient->mutex);
1251    
1252      return pEngineInfo;          return pEngineInfo;
1253  }  }
1254    
1255    
# Line 854  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      pChannelInfo = &(pClient->channel_info);          if (iSamplerChannel < 0)
1280      lscp_channel_info_reset(pChannelInfo);                  return NULL;
1281    
1282      sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          // Lock this section up.
1283      if (lscp_client_query(pClient, szQuery) != LSCP_OK)          lscp_mutex_lock(pClient->mutex);
1284          return NULL;  
1285            pChannelInfo = &(pClient->channel_info);
1286      pszResult = lscp_client_get_result(pClient);          lscp_channel_info_reset(pChannelInfo);
1287      pszToken = lscp_strtok(pszResult, pszSeps, &(pch));  
1288      while (pszToken) {          _save_and_set_c_locale(&locale);
1289          if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {  
1290              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1291              if (pszToken)          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1292                  pChannelInfo->engine_name = lscp_unquote(&pszToken, 1);                  pszResult = lscp_client_get_result(pClient);
1293          }                  pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1294          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {                  while (pszToken) {
1295              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                          if (strcasecmp(pszToken, "ENGINE_NAME") == 0) {
1296              if (pszToken)                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1297                  pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));                                  if (pszToken)
1298          }                                          lscp_unquote_dup(&(pChannelInfo->engine_name), &pszToken);
1299          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {                          }
1300              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_DEVICE") == 0) {
1301              if (pszToken)                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1302                  pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));                                  if (pszToken)
1303          }                                          pChannelInfo->audio_device = atoi(lscp_ltrim(pszToken));
1304          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {                          }
1305              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_CHANNELS") == 0) {
1306              if (pszToken)                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1307                  pChannelInfo->audio_routing = lscp_szsplit_create(pszToken, ",");                                  if (pszToken)
1308          }                                          pChannelInfo->audio_channels = atoi(lscp_ltrim(pszToken));
1309          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {                          }
1310              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                          else if (strcasecmp(pszToken, "AUDIO_OUTPUT_ROUTING") == 0) {
1311              if (pszToken)                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1312                  pChannelInfo->instrument_file = lscp_unquote(&pszToken, 1);                                  if (pszToken) {
1313          }                                          if (pChannelInfo->audio_routing)
1314          else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {                                                  lscp_isplit_destroy(pChannelInfo->audio_routing);
1315              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                          pChannelInfo->audio_routing = lscp_isplit_create(pszToken, ",");
1316              if (pszToken)                                  }
1317                  pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));                          }
1318          }                          else if (strcasecmp(pszToken, "INSTRUMENT_FILE") == 0) {
1319          else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1320              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  if (pszToken)
1321              if (pszToken)                                          lscp_unquote_dup(&(pChannelInfo->instrument_file), &pszToken);
1322                  pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));                          }
1323          }                          else if (strcasecmp(pszToken, "INSTRUMENT_NR") == 0) {
1324          else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1325              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  if (pszToken)
1326              if (pszToken)                                          pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken));
1327                  pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));                          }
1328          }                          else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) {
1329          else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1330              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  if (pszToken)
1331              if (pszToken)                                          lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken);
1332                  pChannelInfo->midi_channel = atoi(lscp_ltrim(pszToken));                          }
1333          }                          else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) {
1334          else if (strcasecmp(pszToken, "VOLUME") == 0) {                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1335              pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  if (pszToken)
1336              if (pszToken)                                          pChannelInfo->instrument_status = atoi(lscp_ltrim(pszToken));
1337                  pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                          }
1338          }                          else if (strcasecmp(pszToken, "MIDI_INPUT_DEVICE") == 0) {
1339          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1340      }                                  if (pszToken)
1341                                            pChannelInfo->midi_device = atoi(lscp_ltrim(pszToken));
1342                            }
1343                            else if (strcasecmp(pszToken, "MIDI_INPUT_PORT") == 0) {
1344                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1345                                    if (pszToken)
1346                                            pChannelInfo->midi_port = atoi(lscp_ltrim(pszToken));
1347                            }
1348                            else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) {
1349                                    pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1350                                    if (pszToken) {
1351                                            pszToken = lscp_ltrim(pszToken);
1352                                            if (strcasecmp(pszToken, "ALL") == 0)
1353                                                    pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL;
1354                                            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            _restore_locale(&locale);
1392    
1393      return pChannelInfo;          // Unlock this section up.
1394            lscp_mutex_unlock(pClient->mutex);
1395    
1396            return pChannelInfo;
1397  }  }
1398    
1399    
# Line 943  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 (pClient == NULL)
1415                    return -1;
1416            if (iSamplerChannel < 0)
1417                    return -1;
1418    
1419      if (iSamplerChannel < 0)          // Lock this section up.
1420          return iVoiceCount;          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_query(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      return iVoiceCount;          // Unlock this section down.
1427            lscp_mutex_unlock(pClient->mutex);
1428    
1429            return iVoiceCount;
1430  }  }
1431    
1432    
# Line 961  int lscp_get_channel_voice_count ( lscp_ Line 1434  int lscp_get_channel_voice_count ( lscp_
1434   *  Current number of active disk streams:   *  Current number of active disk streams:
1435   *  GET CHANNEL STREAM_COUNT <sampler-channel>   *  GET CHANNEL STREAM_COUNT <sampler-channel>
1436   *   *
1437     *  @param pClient          Pointer to client instance structure.
1438     *  @param iSamplerChannel  Sampler channel number.
1439     *
1440   *  @returns The number of active disk streams on success, -1 otherwise.   *  @returns The number of active disk streams on success, -1 otherwise.
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 (pClient == NULL)
1448                    return -1;
1449            if (iSamplerChannel < 0)
1450                    return -1;
1451    
1452      if (iSamplerChannel < 0)          // Lock this section up.
1453          return iStreamCount;          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_query(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      return iStreamCount;          // Unlock this section down.
1460            lscp_mutex_unlock(pClient->mutex);
1461    
1462            return iStreamCount;
1463    }
1464    
1465    
1466    /**
1467     *  Current least usage of active disk streams.
1468     *
1469     *  @param pClient          Pointer to client instance structure.
1470     *  @param iSamplerChannel  Sampler channel number.
1471     *
1472     *  @returns The usage percentage of the least filled active disk stream
1473     *  on success, -1 otherwise.
1474     */
1475    int lscp_get_channel_stream_usage ( lscp_client_t *pClient, int iSamplerChannel )
1476    {
1477            char szQuery[LSCP_BUFSIZ];
1478            int  iStreamUsage = -1;
1479            const char *pszResult;
1480            const char *pszSeps = "[]%,";
1481            char *pszToken;
1482            char *pch;
1483            int   iStream;
1484            int   iPercent;
1485    
1486            if (pClient == NULL)
1487                    return -1;
1488            if (iSamplerChannel < 0)
1489                    return -1;
1490    
1491            // Lock this section up.
1492            lscp_mutex_lock(pClient->mutex);
1493    
1494            iStream = 0;
1495            sprintf(szQuery, "GET CHANNEL BUFFER_FILL PERCENTAGE %d\r\n", iSamplerChannel);
1496            if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1497                    pszResult = lscp_client_get_result(pClient);
1498                    pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1499                    while (pszToken) {
1500                            if (*pszToken) {
1501                                    // Skip stream id.
1502                                    pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1503                                    if (pszToken == NULL)
1504                                            break;
1505                                    // Get least buffer fill percentage.
1506                                    iPercent = atol(pszToken);
1507                                    if (iStreamUsage > iPercent || iStream == 0)
1508                                            iStreamUsage = iPercent;
1509                                    iStream++;
1510                            }
1511                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1512                    }
1513            }
1514    
1515            // Unlock this section down.
1516            lscp_mutex_unlock(pClient->mutex);
1517    
1518            return iStreamUsage;
1519  }  }
1520    
1521    
# Line 993  int lscp_get_channel_stream_count ( lscp Line 1533  int lscp_get_channel_stream_count ( 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      iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);          // Retrieve a channel stream estimation.
1550      if (pClient->iStreamCount != iStreamCount) {          iStreamCount = lscp_get_channel_stream_count(pClient, iSamplerChannel);
1551          if (pClient->buffer_fill)          if (iStreamCount < 0)
1552              free(pClient->buffer_fill);                  return NULL;
1553          if (iStreamCount > 0)  
1554              pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));          // Lock this section up.
1555          else          lscp_mutex_lock(pClient->mutex);
1556              pClient->buffer_fill = NULL;  
1557          pClient->iStreamCount = iStreamCount;          // Check if we need to reallocate the stream usage array.
1558      }          if (pClient->iStreamCount != iStreamCount) {
1559                    if (pClient->buffer_fill)
1560      if (pClient->iStreamCount < 1)                          free(pClient->buffer_fill);
1561          return NULL;                  if (iStreamCount > 0)
1562                            pClient->buffer_fill = (lscp_buffer_fill_t *) malloc(iStreamCount * sizeof(lscp_buffer_fill_t));
1563      iStream = 0;                  else
1564      pBufferFill = pClient->buffer_fill;                          pClient->buffer_fill = NULL;
1565                    pClient->iStreamCount = iStreamCount;
1566      // Get buffer fill usage...          }
1567      sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);  
1568      if (lscp_client_query(pClient, szQuery) == LSCP_OK) {          // Get buffer fill usage...
1569          pszResult = lscp_client_get_result(pClient);          pBufferFill = pClient->buffer_fill;
1570          pszToken = lscp_strtok(pszResult, pszSeps, &(pch));          if (pBufferFill && iStreamCount > 0) {
1571          while (pszToken && iStream < pClient->iStreamCount) {                  iStream = 0;
1572              if (*pszToken) {                  pBufferFill = pClient->buffer_fill;
1573                  pBufferFill[iStream].stream_id = atol(pszToken);                  sprintf(szQuery, "GET CHANNEL BUFFER_FILL %s %d\r\n", pszUsageType, iSamplerChannel);
1574                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));                  if (lscp_client_call(pClient, szQuery, 0) == LSCP_OK) {
1575                  if (pszToken == NULL)                          pszResult = lscp_client_get_result(pClient);
1576                      break;                          pszToken = lscp_strtok((char *) pszResult, pszSeps, &(pch));
1577                  pBufferFill[iStream].stream_usage = atol(pszToken);                          while (pszToken && iStream < pClient->iStreamCount) {
1578                  iStream++;                                  if (*pszToken) {
1579              }                                          pBufferFill[iStream].stream_id = atol(pszToken);
1580              pszToken = lscp_strtok(NULL, pszSeps, &(pch));                                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1581          }                                          if (pszToken == NULL)
1582      }   // Reset the usage, whatever it was before.                                                  break;
1583      else while (iStream < pClient->iStreamCount)                                          pBufferFill[iStream].stream_usage = atol(pszToken);
1584          pBufferFill[iStream++].stream_usage = 0;                                          iStream++;
1585                                    }
1586                                    pszToken = lscp_strtok(NULL, pszSeps, &(pch));
1587                            }
1588                    }   // Reset the usage, whatever it was before.
1589                    else while (iStream < pClient->iStreamCount)
1590                            pBufferFill[iStream++].stream_usage = 0;
1591            }
1592    
1593      return pBufferFill;          // Unlock this section down.
1594            lscp_mutex_unlock(pClient->mutex);
1595    
1596            return pBufferFill;
1597  }  }
1598    
1599    
# Line 1053  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    
1624    /**
1625     *  Setting audio output device:
1626     *  SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
1627     *
1628     *  @param pClient          Pointer to client instance structure.
1629     *  @param iSamplerChannel  Sampler channel number.
1630     *  @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,
1635            int iSamplerChannel, int iAudioDevice )
1636    {
1637            char szQuery[LSCP_BUFSIZ];
1638    
1639            if (iSamplerChannel < 0 || iAudioDevice < 0)
1640                    return LSCP_FAILED;
1641    
1642            sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_DEVICE %d %d\r\n",
1643                    iSamplerChannel, iAudioDevice);
1644            return lscp_client_query(pClient, szQuery);
1645  }  }
1646    
1647    
# Line 1077  lscp_status_t lscp_set_channel_audio_typ Line 1656  lscp_status_t lscp_set_channel_audio_typ
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_CHANNELS %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 1099  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    
1697    /**
1698     *  Setting MIDI input device:
1699     *  SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
1700     *
1701     *  @param pClient          Pointer to client instance structure.
1702     *  @param iSamplerChannel  Sampler channel number.
1703     *  @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,
1708            int iSamplerChannel, int iMidiDevice )
1709    {
1710            char szQuery[LSCP_BUFSIZ];
1711    
1712            if (iSamplerChannel < 0 || iMidiDevice < 0)
1713                    return LSCP_FAILED;
1714    
1715            sprintf(szQuery, "SET CHANNEL MIDI_INPUT_DEVICE %d %d\r\n",
1716                    iSamplerChannel, iMidiDevice);
1717            return lscp_client_query(pClient, szQuery);
1718  }  }
1719    
1720    
# Line 1121  lscp_status_t lscp_set_channel_midi_type Line 1728  lscp_status_t lscp_set_channel_midi_type
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 1139  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)
1792                    return LSCP_FAILED;
1793    
1794            sprintf(szQuery, "SET CHANNEL MIDI_INSTRUMENT_MAP %d ", iSamplerChannel);
1795            if (iMidiMap == LSCP_MIDI_MAP_NONE)
1796                    strcat(szQuery , "NONE");
1797            else
1798            if (iMidiMap == LSCP_MIDI_MAP_DEFAULT)
1799                    strcat(szQuery , "DEFAULT");
1800            else
1801                    sprintf(szQuery + strlen(szQuery), "%d", iMidiMap);
1802    
1803      if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16)          strcat(szQuery, "\r\n");
         return LSCP_FAILED;  
1804    
1805      if (iMidiChannel > 0)          return lscp_client_query(pClient, szQuery);
         sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel);  
     else  
         sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel);  
     return lscp_client_query(pClient, szQuery);  
1806  }  }
1807    
1808    
# Line 1171  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.0)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1828          return LSCP_FAILED;                  return LSCP_FAILED;
1829    
1830      sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          _save_and_set_c_locale(&locale);
1831      return lscp_client_query(pClient, szQuery);          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n",
1832                    iSamplerChannel, fVolume);
1833            _restore_locale(&locale);
1834    
1835            return lscp_client_query(pClient, szQuery);
1836    }
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 1194  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.107  
changed lines
  Added in v.3665

  ViewVC Help
Powered by ViewVC