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

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

  ViewVC Help
Powered by ViewVC