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

Legend:
Removed from v.132  
changed lines
  Added in v.3664

  ViewVC Help
Powered by ViewVC