/[svn]/liblscp/trunk/src/common.c
ViewVC logotype

Diff of /liblscp/trunk/src/common.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 144 by capela, Thu Jun 24 18:25:11 2004 UTC revision 977 by capela, Sun Dec 17 15:08:35 2006 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-2006, 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    
# Line 25  Line 25 
25  #include <ctype.h>  #include <ctype.h>
26    
27    
28  // Chunk size magic:  // Split chunk size magic:
29  // LSCP_SPLIT_CHUNK1 = 2 ^ LSCP_SPLIT_CHUNK2  // LSCP_SPLIT_CHUNK1 := 2 ^ LSCP_SPLIT_CHUNK2
30  #define LSCP_SPLIT_CHUNK1   4  #define LSCP_SPLIT_CHUNK1   4
31  #define LSCP_SPLIT_CHUNK2   2  #define LSCP_SPLIT_CHUNK2   2
32  // Chunk size legal calculator.  // Chunk size legal calculator.
# Line 39  Line 39 
39  // Result buffer internal settler.  // Result buffer internal settler.
40  void lscp_client_set_result ( lscp_client_t *pClient, char *pszResult, int iErrno )  void lscp_client_set_result ( lscp_client_t *pClient, char *pszResult, int iErrno )
41  {  {
42      if (pClient->pszResult)          if (pClient->pszResult)
43          free(pClient->pszResult);                  free(pClient->pszResult);
44      pClient->pszResult = NULL;          pClient->pszResult = NULL;
45    
46      pClient->iErrno = iErrno;          pClient->iErrno = iErrno;
47    
48      if (pszResult)          if (pszResult)
49          pClient->pszResult = strdup(lscp_ltrim(pszResult));                  pClient->pszResult = strdup(lscp_ltrim(pszResult));
50  }  }
51    
52  // The main client requester call executive.  
53  lscp_status_t lscp_client_call ( lscp_client_t *pClient, const char *pszQuery )  // The common client receiver executive.
54    lscp_status_t lscp_client_recv ( lscp_client_t *pClient, char *pchBuffer, int *pcchBuffer, int iTimeout )
55  {  {
56      fd_set fds;                         // File descriptor list for select().          fd_set fds;         // File descriptor list for select().
57      int    fd, fdmax;                   // Maximum file descriptor number.          int    fd, fdmax;   // Maximum file descriptor number.
58      struct timeval tv;                  // For specifying a timeout value.          struct timeval tv;  // For specifying a timeout value.
59      int    iSelect;                     // Holds select return status.          int    iSelect;     // Holds select return status.
60      int    iTimeout;  
61      int    cchQuery;          lscp_status_t ret = LSCP_FAILED;
62      char   achResult[LSCP_BUFSIZ];  
63      int    cchResult;          if (pClient == NULL)
64      const  char *pszSeps = ":[]";                  return ret;
65      char  *pszResult;  
66      char  *pszToken;          // Prepare for waiting on select...
67      char  *pch;          fd = (int) pClient->cmd.sock;
68      int    iErrno;          FD_ZERO(&fds);
69            FD_SET((unsigned int) fd, &fds);
70      lscp_status_t ret = LSCP_FAILED;          fdmax = fd;
71    
72      if (pClient == NULL)          // Use the timeout select feature...
73          return ret;          if (iTimeout < 1)
74                    iTimeout = pClient->iTimeout;
75      pszResult = NULL;          if (iTimeout >= 1000) {
76      iErrno = -1;                  tv.tv_sec = iTimeout / 1000;
77                    iTimeout -= tv.tv_sec * 1000;
78      // Check if command socket socket is still valid.          }
79      if (pClient->cmd.sock == INVALID_SOCKET) {          else tv.tv_sec = 0;
80          pszResult = "Connection closed or no longer valid";          tv.tv_usec = iTimeout * 1000;
81          lscp_client_set_result(pClient, pszResult, iErrno);  
82          return ret;          // Wait for event...
83      }          iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
84            if (iSelect > 0 && FD_ISSET(fd, &fds)) {
85      // Send data, and then, wait for the result...                  // May recv now...
86      cchQuery = strlen(pszQuery);                  *pcchBuffer = recv(pClient->cmd.sock, pchBuffer, *pcchBuffer, 0);
87      if (send(pClient->cmd.sock, pszQuery, cchQuery, 0) < cchQuery) {                  if (*pcchBuffer > 0)
88          lscp_socket_perror("_lscp_client_call: send");                          ret = LSCP_OK;
89          pszResult = "Failure during send operation";                  else if (*pcchBuffer < 0)
90          lscp_client_set_result(pClient, pszResult, iErrno);                          lscp_socket_perror("lscp_client_recv: recv");
91          return ret;                  else if (*pcchBuffer == 0) {
92      }                          // Damn, server probably disconnected,
93                            // we better free everything down here.
94      // Prepare for waiting on select...                          lscp_socket_agent_free(&(pClient->evt));
95      fd = (int) pClient->cmd.sock;                          lscp_socket_agent_free(&(pClient->cmd));
96      FD_ZERO(&fds);                          // Fake a result message.
97      FD_SET((unsigned int) fd, &fds);                          ret = LSCP_QUIT;
98      fdmax = fd;                  }
99            }   // Check if select has timed out.
100      // Use the timeout select feature...          else if (iSelect == 0)
101      iTimeout = pClient->iTimeout;                  ret = LSCP_TIMEOUT;
102      if (iTimeout > 1000) {          else
103          tv.tv_sec = iTimeout / 1000;                  lscp_socket_perror("lscp_client_recv: select");
         iTimeout -= tv.tv_sec * 1000;  
     }  
     else tv.tv_sec = 0;  
     tv.tv_usec = iTimeout * 1000;  
   
     // Wait for event...  
     iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);  
     if (iSelect > 0 && FD_ISSET(fd, &fds)) {  
         // May recv now...  
         cchResult = recv(pClient->cmd.sock, achResult, sizeof(achResult), 0);  
         if (cchResult > 0) {  
             // Assume early success.  
             ret = LSCP_OK;  
             // Always force the result to be null terminated (and trim trailing CRLFs)!  
             while (cchResult > 0 && (achResult[cchResult - 1] == '\n' || achResult[cchResult- 1] == '\r'))  
                 cchResult--;  
             achResult[cchResult] = (char) 0;  
             // Check if the response it's an error or warning message.  
             if (strncasecmp(achResult, "WRN:", 4) == 0)  
                 ret = LSCP_WARNING;  
             else if (strncasecmp(achResult, "ERR:", 4) == 0)  
                 ret = LSCP_ERROR;  
             // So we got a result...  
             if (ret == LSCP_OK) {  
                 // Reset errno in case of success.  
                 iErrno = 0;  
                 // Is it a special successful response?  
                 if (strncasecmp(achResult, "OK[", 3) == 0) {  
                     // Parse the OK message, get the return string under brackets...  
                     pszToken = lscp_strtok(achResult, pszSeps, &(pch));  
                     if (pszToken)  
                         pszResult = lscp_strtok(NULL, pszSeps, &(pch));  
                 }  
                 else pszResult = achResult;  
                 // The result string is now set to the command response, if any.  
             } else {  
                 // Parse the error/warning message, skip first colon...  
                 pszToken = lscp_strtok(achResult, pszSeps, &(pch));  
                 if (pszToken) {  
                     // Get the error number...  
                     pszToken = lscp_strtok(NULL, pszSeps, &(pch));  
                     if (pszToken) {  
                         iErrno = atoi(pszToken);  
                         // And make the message text our final result.  
                         pszResult = lscp_strtok(NULL, pszSeps, &(pch));  
                     }  
                 }  
                 // The result string is set to the error/warning message text.  
             }  
         }  
         else if (cchResult == 0) {  
             // Damn, server disconnected, we better free everything down here.  
             lscp_socket_agent_free(&(pClient->evt));  
             lscp_socket_agent_free(&(pClient->cmd));  
             // Fake a result message.  
             ret = LSCP_QUIT;  
             pszResult = "Server terminated the connection";  
             iErrno = (int) ret;  
         } else {  
             // What's down?  
             lscp_socket_perror("_lscp_client_call: recv");  
             pszResult = "Failure during receive operation";  
         }  
     }   // Check if select has timed out.  
     else if (iSelect == 0) {  
         // Fake a result message.  
         ret = LSCP_TIMEOUT;  
         pszResult = "Timeout during receive operation";  
         iErrno = (int) ret;  
    }  
     else lscp_socket_perror("_lscp_client_call: select");  
104    
105      // Make the result official...          return ret;
106      lscp_client_set_result(pClient, pszResult, iErrno);  }
107    
108      return ret;  
109    // The main client requester call executive.
110    lscp_status_t lscp_client_call ( lscp_client_t *pClient, const char *pszQuery, int iResult )
111    {
112            int    cchQuery;
113            char   achBuffer[LSCP_BUFSIZ];
114            int    cchBuffer;
115            const  char *pszSeps = ":[]";
116            char  *pszBuffer;
117            char  *pszToken;
118            char  *pch;
119            int    iErrno;
120            char  *pszResult;
121            int    cchResult;
122            
123            lscp_status_t ret = LSCP_FAILED;
124            
125            if (pClient == NULL)
126                    return ret;
127            
128            iErrno = -1;
129            cchResult = 0;
130            pszResult = NULL;
131            pszBuffer = NULL;
132    
133            // Check if command socket socket is still valid.
134            if (pClient->cmd.sock == INVALID_SOCKET) {
135                    pszResult = "Connection closed or no longer valid";
136                    lscp_client_set_result(pClient, pszResult, iErrno);
137                    return ret;
138            }
139    
140            // Check if last transaction has timed out, in which case
141            // we'll retry wait and flush for some pending garbage...
142            if (pClient->iTimeoutCount > 0) {
143                    // We'll hope to get rid of timeout trouble...
144                    pClient->iTimeoutCount = 0;
145                    cchBuffer = sizeof(achBuffer);
146                    ret = lscp_client_recv(pClient, achBuffer, &cchBuffer, pClient->iTimeout);
147                    if (ret != LSCP_OK) {
148                            // Things seems to be unresolved. Fake a result message.
149                            iErrno = (int) ret;
150                            pszResult = "Failure during flush timeout operation";
151                            lscp_client_set_result(pClient, pszResult, iErrno);
152                            return ret;
153                    }
154            }
155    
156            // Send data, and then, wait for the result...
157            cchQuery = strlen(pszQuery);
158            if (send(pClient->cmd.sock, pszQuery, cchQuery, 0) < cchQuery) {
159                    lscp_socket_perror("lscp_client_call: send");
160                    pszResult = "Failure during send operation";
161                    lscp_client_set_result(pClient, pszResult, iErrno);
162                    return ret;
163            }
164    
165            // Keep receiving while result is not the expected one:
166            // single-line result (iResult = 0) : one single CRLF ends the receipt;
167            // multi-line result  (iResult > 0) : one "." followed by a last CRLF;
168    
169            while (pszResult == NULL) {
170    
171                    // Wait for receive event...
172                    cchBuffer = sizeof(achBuffer) - 1;
173                    ret = lscp_client_recv(pClient, achBuffer, &cchBuffer, pClient->iTimeout);
174    
175                    switch (ret) {
176    
177                    case LSCP_OK:
178                            // Always force the result to be null terminated.
179                            achBuffer[cchBuffer] = (char) 0;
180                            // Check if the response it's an error or warning message.
181                            if (strncasecmp(achBuffer, "WRN:", 4) == 0)
182                                    ret = LSCP_WARNING;
183                            else if (strncasecmp(achBuffer, "ERR:", 4) == 0)
184                                    ret = LSCP_ERROR;
185                            // So we got a result...
186                            if (ret == LSCP_OK) {
187                                    // Reset errno in case of success.
188                                    iErrno = 0;
189                                    // Is it a special successful response?
190                                    if (iResult < 1 && strncasecmp(achBuffer, "OK[", 3) == 0) {
191                                            // Parse the OK message, get the return string under brackets...
192                                            pszToken = lscp_strtok(achBuffer, pszSeps, &(pch));
193                                            if (pszToken)
194                                                    pszResult = lscp_strtok(NULL, pszSeps, &(pch));
195                                    } else {
196                                            // It can be specially long response...
197                                            cchResult += sizeof(achBuffer);
198                                            pszResult  = malloc(cchResult + 1);
199                                            pszResult[0] = (char) 0;
200                                            if (pszBuffer) {
201                                                    strcat(pszResult, pszBuffer);
202                                                    free(pszBuffer);
203                                            }
204                                            strcat(pszResult, achBuffer);
205                                            pszBuffer = pszResult;
206                                            pszResult = NULL;
207                                            // Check for correct end-of-transmission...
208                                            // Depending whether its single or multi-line we'll
209                                            // flag end-of-transmission...
210                                            cchBuffer = strlen(pszBuffer);
211                                            if (cchBuffer >= 2
212                                                    && pszBuffer[cchBuffer - 1] == '\n'
213                                                    && pszBuffer[cchBuffer - 2] == '\r'
214                                                    && (iResult < 1 || (cchBuffer >= 3
215                                                                    && pszBuffer[cchBuffer - 3] == '.'))) {
216                                                    // Get rid of the trailling dot and CRLF anyway...
217                                                    while (cchBuffer > 0 && (
218                                                            pszBuffer[cchBuffer - 1] == '\r' ||
219                                                            pszBuffer[cchBuffer - 1] == '\n' ||
220                                                            pszBuffer[cchBuffer - 1] == '.'))
221                                                            cchBuffer--;
222                                                    pszBuffer[cchBuffer] = (char) 0;
223                                                    pszResult = pszBuffer;
224                                            }
225                                    }
226                                    // The result string is now set to the command response, if any.
227                            } else {
228                                    // Get rid of the CRLF anyway...
229                                    while (cchBuffer > 0 && (
230                                            achBuffer[cchBuffer - 1] == '\r' ||
231                                            achBuffer[cchBuffer - 1] == '\n'))
232                                            achBuffer[--cchBuffer] = (char) 0;
233                                    // Parse the error/warning message, skip first colon...
234                                    pszToken = lscp_strtok(achBuffer, pszSeps, &(pch));
235                                    if (pszToken) {
236                                            // Get the error number...
237                                            pszToken = lscp_strtok(NULL, pszSeps, &(pch));
238                                            if (pszToken) {
239                                                    iErrno = atoi(pszToken) + 100;
240                                                    // And make the message text our final result.
241                                                    pszResult = lscp_strtok(NULL, pszSeps, &(pch));
242                                            }
243                                    }
244                                    // The result string is set to the error/warning message text.
245                            }
246                            break;
247    
248                    case LSCP_TIMEOUT:
249                            // We have trouble...
250                            pClient->iTimeoutCount++;
251                            // Fake a result message.
252                            pszResult = "Timeout during receive operation";
253                            iErrno = (int) ret;
254                            break;
255    
256                    case LSCP_QUIT:
257                            // Fake a result message.
258                            pszResult = "Server terminated the connection";
259                            iErrno = (int) ret;
260                            break;
261    
262                    case LSCP_FAILED:
263                    default:
264                            // What's down?
265                            pszResult = "Failure during receive operation";
266                            break;
267                    }
268            }
269    
270            // Make the result official...
271            lscp_client_set_result(pClient, pszResult, iErrno);
272    
273            // Free long-buffer, if any...
274            if (pszBuffer)
275                    free(pszBuffer);
276    
277            return ret;
278  }  }
279    
280    
# Line 185  lscp_status_t lscp_client_call ( lscp_cl Line 284  lscp_status_t lscp_client_call ( lscp_cl
284  // Trimming left spaces...  // Trimming left spaces...
285  char *lscp_ltrim ( char *psz )  char *lscp_ltrim ( char *psz )
286  {  {
287      while (isspace(*psz))          while (isspace(*psz))
288          psz++;                  psz++;
289      return psz;          return psz;
290  }  }
291    
292  // Unquote an in-split string.  // Unquote an in-split string.
293  char *lscp_unquote ( char **ppsz, int dup )  char *lscp_unquote ( char **ppsz, int dup )
294  {  {
295      char  chQuote;          char  chQuote;
296      char *psz = *ppsz;          char *psz = *ppsz;
297    
298      while (isspace(*psz))          while (isspace(*psz))
299          ++psz;                  ++psz;
300      if (*psz == '\"' || *psz == '\'') {          if (*psz == '\"' || *psz == '\'') {
301          chQuote = *psz++;                  chQuote = *psz++;
302          while (isspace(*psz))                  while (isspace(*psz))
303              ++psz;                          ++psz;
304          if (dup)                  if (dup)
305              psz = strdup(psz);                          psz = strdup(psz);
306          *ppsz = psz;                  *ppsz = psz;
307          if (*ppsz) {                  if (*ppsz) {
308              while (**ppsz && **ppsz != chQuote)                          while (**ppsz && **ppsz != chQuote)
309                  ++(*ppsz);                                  ++(*ppsz);
310              if (**ppsz) {                          if (**ppsz) {
311                  while (isspace(*(*ppsz - 1)) && *ppsz > psz)                                  while (isspace(*(*ppsz - 1)) && *ppsz > psz)
312                      --(*ppsz);                                          --(*ppsz);
313                  *(*ppsz)++ = (char) 0;                                  *(*ppsz)++ = (char) 0;
314              }                          }
315          }                  }
316      }          }
317      else if (dup) {          else if (dup) {
318          psz = strdup(psz);                  psz = strdup(psz);
319          *ppsz = psz;                  *ppsz = psz;
320      }          }
321    
322            return psz;
323    }
324    
325      return psz;  // Unquote and make a duplicate of an in-split string.
326    void lscp_unquote_dup ( char **ppszDst, char **ppszSrc )
327    {
328            // Free desteny string, if already there.
329            if (*ppszDst)
330                    free(*ppszDst);
331            *ppszDst = NULL;
332            // Unquote and duplicate.
333            if (*ppszSrc)
334                    *ppszDst = lscp_unquote(ppszSrc, 1);
335  }  }
336    
337    
338  // Custom tokenizer.  // Custom tokenizer.
339  char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )  char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )
340  {  {
341      char *pszToken;          char *pszToken;
342    
343      if (pchBuffer == NULL)          if (pchBuffer == NULL)
344          pchBuffer = *ppch;                  pchBuffer = *ppch;
345    
346      pchBuffer += strspn(pchBuffer, pszSeps);          pchBuffer += strspn(pchBuffer, pszSeps);
347      if (*pchBuffer == '\0')          if (*pchBuffer == '\0')
348          return NULL;                  return NULL;
349    
350      pszToken  = pchBuffer;          pszToken  = pchBuffer;
351      pchBuffer = strpbrk(pszToken, pszSeps);          pchBuffer = strpbrk(pszToken, pszSeps);
352      if (pchBuffer == NULL) {          if (pchBuffer == NULL) {
353          *ppch = strchr(pszToken, '\0');                  *ppch = strchr(pszToken, '\0');
354      } else {          } else {
355          *pchBuffer = '\0';                  *pchBuffer = '\0';
356          *ppch = pchBuffer + 1;                  *ppch = pchBuffer + 1;
357          while (**ppch && strchr(pszSeps, **ppch))                  while (**ppch && strchr(pszSeps, **ppch))
358              (*ppch)++;                          (*ppch)++;
359      }          }
360    
361      return pszToken;          return pszToken;
362  }  }
363    
364    
365  // Split a comma separated string into a null terminated array of strings.  // Split a comma separated string into a null terminated array of strings.
366  char **lscp_szsplit_create ( const char *pszCsv, const char *pszSeps )  char **lscp_szsplit_create ( const char *pszCsv, const char *pszSeps )
367  {  {
368      char *pszHead, *pch;          char *pszHead, *pch;
369      int iSize, i, j, cchSeps;          int iSize, i, j, cchSeps;
370      char **ppszSplit, **ppszNewSplit;          char **ppszSplit, **ppszNewSplit;
371    
372      // Initial size is one chunk away.          // Initial size is one chunk away.
373      iSize = LSCP_SPLIT_CHUNK1;          iSize = LSCP_SPLIT_CHUNK1;
374      // Allocate and split...          // Allocate and split...
375      ppszSplit = (char **) malloc(iSize * sizeof(char *));          ppszSplit = (char **) malloc(iSize * sizeof(char *));
376      if (ppszSplit == NULL)          if (ppszSplit == NULL)
377          return NULL;                  return NULL;
378    
379      // Make a copy of the original string.          // Make a copy of the original string.
380      i = 0;          i = 0;
381      pszHead = (char *) pszCsv;          pszHead = (char *) pszCsv;
382      if ((ppszSplit[i++] = lscp_unquote(&pszHead, 1)) == NULL) {          if ((ppszSplit[i++] = lscp_unquote(&pszHead, 1)) == NULL) {
383          free(ppszSplit);                  free(ppszSplit);
384          return NULL;                  return NULL;
385      }          }
386    
387      // Go on for it...          // Go on for it...
388      cchSeps = strlen(pszSeps);          cchSeps = strlen(pszSeps);
389      while ((pch = strpbrk(pszHead, pszSeps)) != NULL) {          while ((pch = strpbrk(pszHead, pszSeps)) != NULL) {
390          // Pre-advance to next item.                  // Pre-advance to next item.
391          pszHead = pch + cchSeps;                  pszHead = pch + cchSeps;
392          // Trim and null terminate current item.                  // Trim and null terminate current item.
393          while (isspace(*(pch - 1)) && pch > ppszSplit[0])                  while (isspace(*(pch - 1)) && pch > ppszSplit[0])
394              --pch;                          --pch;
395          *pch = (char) 0;                  *pch = (char) 0;
396          // Make it official.                  // Make it official.
397          ppszSplit[i++] = lscp_unquote(&pszHead, 0);                  ppszSplit[i] = lscp_unquote(&pszHead, 0);
398          // Do we need to grow?                  // Do we need to grow?
399          if (i >= iSize) {                  if (++i >= iSize) {
400              // Yes, but only grow in chunks.                          // Yes, but only grow in chunks.
401              iSize += LSCP_SPLIT_CHUNK1;                          iSize += LSCP_SPLIT_CHUNK1;
402              // Allocate and copy to new split array.                          // Allocate and copy to new split array.
403              ppszNewSplit = (char **) malloc(iSize * sizeof(char *));                          ppszNewSplit = (char **) malloc(iSize * sizeof(char *));
404              if (ppszNewSplit) {                          if (ppszNewSplit) {
405                  for (j = 0; j < i; j++)                                  for (j = 0; j < i; j++)
406                      ppszNewSplit[j] = ppszSplit[j];                                          ppszNewSplit[j] = ppszSplit[j];
407                  free(ppszSplit);                                  free(ppszSplit);
408                  ppszSplit = ppszNewSplit;                                  ppszSplit = ppszNewSplit;
409              }                          }
410          }                  }
411      }          }
412    
413      // NULL terminate split array.          // NULL terminate split array.
414      for ( ; i < iSize; i++)          for ( ; i < iSize; i++)
415          ppszSplit[i] = NULL;                  ppszSplit[i] = NULL;
416    
417      return ppszSplit;          return ppszSplit;
418  }  }
419    
420    
421  // Free allocated memory of a legal null terminated array of strings.  // Free allocated memory of a legal null terminated array of strings.
422  void lscp_szsplit_destroy ( char **ppszSplit )  void lscp_szsplit_destroy ( char **ppszSplit )
423  {  {
424      // Our split string is always the first item, if any.          // Our split string is always the first item, if any.
425      if (ppszSplit && ppszSplit[0])          if (ppszSplit && ppszSplit[0])
426          free(ppszSplit[0]);                  free(ppszSplit[0]);
427      // Now free the array itself.          // Now free the array itself.
428      if (ppszSplit)          if (ppszSplit)
429          free(ppszSplit);                  free(ppszSplit);
430  }  }
431    
432    
# Line 324  void lscp_szsplit_destroy ( char **ppszS Line 435  void lscp_szsplit_destroy ( char **ppszS
435  // Return the number of items of a null terminated array of strings.  // Return the number of items of a null terminated array of strings.
436  int lscp_szsplit_count ( char **ppszSplit )  int lscp_szsplit_count ( char **ppszSplit )
437  {  {
438      int i = 0;          int i = 0;
439      while (ppszSplit && ppszSplit[i])          while (ppszSplit && ppszSplit[i])
440          i++;                  i++;
441      return i;          return i;
442  }  }
443    
444  // Return the allocated number of items of a splitted string array.  // Return the allocated number of items of a splitted string array.
445  int lscp_szsplit_size ( char **ppszSplit )  int lscp_szsplit_size ( char **ppszSplit )
446  {  {
447      return LSCP_SPLIT_SIZE(lscp_szsplit_count(ppszSplit));          return LSCP_SPLIT_SIZE(lscp_szsplit_count(ppszSplit));
448  }  }
449    
450  #endif // LSCP_SZSPLIT_COUNT  #endif // LSCP_SZSPLIT_COUNT
# Line 342  int lscp_szsplit_size ( char **ppszSplit Line 453  int lscp_szsplit_size ( char **ppszSplit
453  // Split a comma separated string into a -1 terminated array of positive integers.  // Split a comma separated string into a -1 terminated array of positive integers.
454  int *lscp_isplit_create ( const char *pszCsv, const char *pszSeps )  int *lscp_isplit_create ( const char *pszCsv, const char *pszSeps )
455  {  {
456      char *pchHead, *pch;          char *pchHead, *pch;
457      int iSize, i, j, cchSeps;          int iSize, i, j, cchSeps;
458      int *piSplit, *piNewSplit;          int *piSplit, *piNewSplit;
459    
460      // Initial size is one chunk away.          // Get it clean first.
461      iSize = LSCP_SPLIT_CHUNK1;          pchHead = lscp_ltrim((char *) pszCsv);
462      // Allocate and split...          if (*pchHead == (char) 0)
463      piSplit = (int *) malloc(iSize * sizeof(int));                  return NULL;
464      if (piSplit == NULL)  
465          return NULL;          // Initial size is one chunk away.
466            iSize = LSCP_SPLIT_CHUNK1;
467      // Make a copy of the original string.          // Allocate and split...
468      i = 0;          piSplit = (int *) malloc(iSize * sizeof(int));
469      pchHead = (char *) pszCsv;          if (piSplit == NULL)
470      if ((piSplit[i++] = atoi(pchHead)) < 0) {                  return NULL;
471          free(piSplit);  
472          return NULL;          // Make a copy of the original string.
473      }          i = 0;
474            if ((piSplit[i++] = atoi(pchHead)) < 0) {
475      // Go on for it...                  free(piSplit);
476      cchSeps = strlen(pszSeps);                  return NULL;
477      while ((pch = strpbrk(pchHead, pszSeps)) != NULL) {          }
478          // Pre-advance to next item.  
479          pchHead = pch + cchSeps;          // Go on for it...
480          // Make it official.          cchSeps = strlen(pszSeps);
481          piSplit[i++] = atoi(pchHead);          while ((pch = strpbrk(pchHead, pszSeps)) != NULL) {
482          // Do we need to grow?                  // Pre-advance to next item.
483          if (i >= iSize) {                  pchHead = pch + cchSeps;
484              // Yes, but only grow in chunks.                  // Make it official.
485              iSize += LSCP_SPLIT_CHUNK1;                  piSplit[i] = atoi(pchHead);
486              // Allocate and copy to new split array.                  // Do we need to grow?
487              piNewSplit = (int *) malloc(iSize * sizeof(int));                  if (++i >= iSize) {
488              if (piNewSplit) {                          // Yes, but only grow in chunks.
489                  for (j = 0; j < i; j++)                          iSize += LSCP_SPLIT_CHUNK1;
490                      piNewSplit[j] = piSplit[j];                          // Allocate and copy to new split array.
491                  free(piSplit);                          piNewSplit = (int *) malloc(iSize * sizeof(int));
492                  piSplit = piNewSplit;                          if (piNewSplit) {
493              }                                  for (j = 0; j < i; j++)
494          }                                          piNewSplit[j] = piSplit[j];
495      }                                  free(piSplit);
496                                    piSplit = piNewSplit;
497      // NULL terminate split array.                          }
498      for ( ; i < iSize; i++)                  }
499          piSplit[i] = -1;          }
500    
501            // NULL terminate split array.
502            for ( ; i < iSize; i++)
503                    piSplit[i] = -1;
504    
505      return piSplit;          return piSplit;
506  }  }
507    
508    
509  // Destroy a integer splitted array.  // Destroy a integer splitted array.
510  void lscp_isplit_destroy ( int *piSplit )  void lscp_isplit_destroy ( int *piSplit )
511  {  {
512      if (piSplit)          if (piSplit)
513          free(piSplit);                  free(piSplit);
514  }  }
515    
516    
# Line 404  void lscp_isplit_destroy ( int *piSplit Line 519  void lscp_isplit_destroy ( int *piSplit
519  // Compute a string list valid item count.  // Compute a string list valid item count.
520  int lscp_isplit_count ( int *piSplit )  int lscp_isplit_count ( int *piSplit )
521  {  {
522      int i = 0;          int i = 0;
523      while (piSplit && piSplit[i] >= 0)          while (piSplit && piSplit[i] >= 0)
524          i++;                  i++;
525      return i;          return i;
526  }  }
527    
528  // Compute a string list size.  // Compute a string list size.
529  int lscp_isplit_size ( int *piSplit )  int lscp_isplit_size ( int *piSplit )
530  {  {
531      return LSCP_SPLIT_SIZE(lscp_isplit_count(piSplit));          return LSCP_SPLIT_SIZE(lscp_isplit_count(piSplit));
532  }  }
533    
534  #endif // LSCP_ISPLIT_COUNT  #endif // LSCP_ISPLIT_COUNT
535    
536    
537    // Split a string into a null terminated array of parameter items.
538    lscp_param_t *lscp_psplit_create ( const char *pszCsv, const char *pszSeps1, const char *pszSeps2 )
539    {
540            char *pszHead, *pch;
541            int iSize, i, j, cchSeps1, cchSeps2;
542            lscp_param_t *ppSplit, *ppNewSplit;
543    
544            pszHead = strdup(pszCsv);
545            if (pszHead == NULL)
546                    return NULL;
547    
548            iSize = LSCP_SPLIT_CHUNK1;
549            ppSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t));
550            if (ppSplit == NULL) {
551                    free(pszHead);
552                    return NULL;
553            }
554    
555            cchSeps1 = strlen(pszSeps1);
556            cchSeps2 = strlen(pszSeps2);
557    
558            i = 0;
559            while ((pch = strpbrk(pszHead, pszSeps1)) != NULL) {
560                    ppSplit[i].key = pszHead;
561                    pszHead = pch + cchSeps1;
562                    *pch = (char) 0;
563                    ppSplit[i].value = lscp_unquote(&pszHead, 0);
564                    if ((pch = strpbrk(pszHead, pszSeps2)) != NULL) {
565                            pszHead = pch + cchSeps2;
566                            *pch = (char) 0;
567                    }
568                    if (++i >= iSize) {
569                            iSize += LSCP_SPLIT_CHUNK1;
570                            ppNewSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t));
571                            if (ppNewSplit) {
572                                    for (j = 0; j < i; j++) {
573                                            ppNewSplit[j].key   = ppSplit[j].key;
574                                            ppNewSplit[j].value = ppSplit[j].value;
575                                    }
576                                    free(ppSplit);
577                                    ppSplit = ppNewSplit;
578                            }
579                    }
580            }
581    
582            if (i < 1)
583                    free(pszHead);
584    
585            for ( ; i < iSize; i++) {
586                    ppSplit[i].key   = NULL;
587                    ppSplit[i].value = NULL;
588            }
589    
590            return ppSplit;
591    }
592    
593    
594    // Destroy a parameter list array.
595    void lscp_psplit_destroy ( lscp_param_t *ppSplit )
596    {
597            if (ppSplit && ppSplit[0].key)
598                    free(ppSplit[0].key);
599            if (ppSplit)
600                    free(ppSplit);
601    }
602    
603    
604    #ifdef LSCP_PSPLIT_COUNT
605    
606    // Compute a parameter list valid item count.
607    int lscp_psplit_count ( lscp_param_t *ppSplit )
608    {
609            int i = 0;
610            while (ppSplit && ppSplit[i].key)
611                    i++;
612            return i;
613    }
614    
615    // Compute a parameter list size.
616    int lscp_psplit_size ( lscp_param_t *ppSplit )
617    {
618            return LSCP_SPLIT_SIZE(lscp_psplit_count(ppSplit));
619    }
620    
621    #endif // LSCP_PSPLIT_COUNT
622    
623    
624    // Allocate a parameter list, optionally copying an existing one.
625    void lscp_plist_alloc (lscp_param_t **ppList)
626    {
627            lscp_param_t *pParams;
628            int iSize, i;
629    
630            if (ppList) {
631                    iSize = LSCP_SPLIT_CHUNK1;
632                    pParams = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t));
633                    if (pParams) {
634                            for (i = 0 ; i < iSize; i++) {
635                                    pParams[i].key   = NULL;
636                                    pParams[i].value = NULL;
637                            }
638                    }
639                    *ppList = pParams;
640            }
641    }
642    
643    
644    // Destroy a parameter list, including all it's contents.
645    void lscp_plist_free ( lscp_param_t **ppList )
646    {
647            lscp_param_t *pParams;
648            int i;
649    
650            if (ppList) {
651                    if (*ppList) {
652                            pParams = *ppList;
653                            for (i = 0; pParams && pParams[i].key; i++) {
654                                    free(pParams[i].key);
655                                    free(pParams[i].value);
656                            }
657                            free(pParams);
658                    }
659                    *ppList = NULL;
660            }
661    }
662    
663    
664    // Add an item to a parameter list, growing it as fit.
665    void lscp_plist_append ( lscp_param_t **ppList, const char *pszKey, const char *pszValue )
666    {
667            lscp_param_t *pParams;
668            lscp_param_t *pNewParams;
669            int iSize, iNewSize;
670            int i = 0;
671    
672            if (ppList && *ppList) {
673                    pParams = *ppList;
674                    while (pParams[i].key) {
675                            if (strcasecmp(pParams[i].key, pszKey) == 0) {
676                                    if (pParams[i].value)
677                                            free(pParams[i].value);
678                                    pParams[i].value = strdup(pszValue);
679                                    return;
680                            }
681                            i++;
682                    }
683                    iSize = LSCP_SPLIT_SIZE(i);
684                    pParams[i].key   = strdup(pszKey);
685                    pParams[i].value = strdup(pszValue);
686                    if (++i >= iSize) {
687                            iNewSize   = iSize + LSCP_SPLIT_CHUNK1;
688                            pNewParams = (lscp_param_t *) malloc(iNewSize * sizeof(lscp_param_t));
689                            for (i = 0; i < iSize; i++) {
690                                    pNewParams[i].key   = pParams[i].key;
691                                    pNewParams[i].value = pParams[i].value;
692                            }
693                            for ( ; i < iNewSize; i++) {
694                                    pNewParams[i].key   = NULL;
695                                    pNewParams[i].value = NULL;
696                            }
697                            free(pParams);
698                            *ppList = pNewParams;
699                    }
700            }
701    }
702    
703    #ifdef LSCP_PLIST_COUNT
704    
705    // Compute a parameter list valid item count.
706    int lscp_plist_count ( lscp_param_t **ppList )
707    {
708            lscp_param_t *pParams;
709            int i = 0;
710            if (ppList && *ppList) {
711                    pParams = *ppList;
712                    while (pParams[i].key)
713                            i++;
714            }
715            return i;
716    }
717    
718    // Compute the legal parameter list size.
719    int lscp_plist_size ( lscp_param_t **ppList )
720    {
721            return LSCP_SPLIT_SIZE(lscp_plist_count(ppList));
722    }
723    
724    #endif // LSCP_PLIST_COUNT
725    
726    
727    // Split a string into an array of MIDI instrument triplets.
728    lscp_midi_instrument_t *lscp_midi_instruments_create ( const char *pszCsv )
729    {
730            char *pchHead, *pch;
731            int iSize, i, j, k;
732            lscp_midi_instrument_t *pInstrs;
733            lscp_midi_instrument_t *pNewInstrs;
734            
735            // Get it clean first.
736            pchHead = lscp_ltrim((char *) pszCsv);
737            if (*pchHead == (char) 0)
738                    return NULL;
739            
740            // Initial size is one chunk away.
741            iSize = LSCP_SPLIT_CHUNK1;
742            // Allocate and split...
743            pInstrs = (lscp_midi_instrument_t *) malloc(iSize * sizeof(lscp_midi_instrument_t));
744            if (pInstrs == NULL)
745                    return NULL;
746            
747            // Go on for it...
748            i = 0;
749            k = 0;
750            
751            while ((pch = strpbrk(pchHead, "{,}")) != NULL) {
752                    // Pre-advance to next item.
753                    switch (*pch) {
754                    case '{':
755                            pchHead = pch + 1;
756                            if (k == 0) {
757                                    pInstrs[i].map = atoi(pchHead);
758                                    k++;
759                            }
760                            break;
761                    case ',':
762                            pchHead = pch + 1;
763                            if (k == 1) {
764                                    pInstrs[i].bank = atoi(pchHead);
765                                    k++;
766                            }
767                            else
768                            if (k == 2) {
769                                    pInstrs[i].prog = atoi(pchHead);
770                                    k++;
771                            }
772                            break;
773                    case '}':
774                            pchHead = pch + 1;
775                            k = 0;
776                            break;
777                    }
778                    // Do we need to grow?
779                    if (k == 3 && ++i >= iSize) {
780                            // Yes, but only grow in chunks.
781                            iSize += LSCP_SPLIT_CHUNK1;
782                            // Allocate and copy to new split array.
783                            pNewInstrs = (lscp_midi_instrument_t *) malloc(iSize * sizeof(lscp_midi_instrument_t));
784                            if (pNewInstrs) {
785                                    for (j = 0; j < i; j++) {
786                                            pNewInstrs[j].map  = pInstrs[j].map;
787                                            pNewInstrs[j].bank = pInstrs[j].bank;
788                                            pNewInstrs[j].prog = pInstrs[j].prog;
789                                    }
790                                    free(pInstrs);
791                                    pInstrs = pNewInstrs;
792                            }
793                    }
794            }
795            
796            // Special terminate split array.
797            for ( ; i < iSize; i++) {
798                    pInstrs[i].map  = -1;
799                    pInstrs[i].bank = -1;
800                    pInstrs[i].prog = -1;
801            }
802            
803            return pInstrs;
804    }
805    
806    // Destroy a MIDI instrument triplet array.
807    void lscp_midi_instruments_destroy ( lscp_midi_instrument_t *pInstrs )
808    {
809            if (pInstrs)
810                    free(pInstrs);
811    }
812    
813    #ifdef LSCP_MIDI_INSTRUMENTS_COUNT
814    
815    // Compute a MIDI instrument array item count.
816    int lscp_midi_instruments_count ( lscp_midi_instrument_t *pInstrs )
817    {
818            int i = 0;
819            while (pInstrs && pInstrs[i].program >= 0)
820                    i++;
821            return i;
822    }
823    
824    // Compute a MIDI instrument array size.
825    int lscp_midi_instruments_size ( lscp_midi_instrument_t *pInstrs )
826    {
827            return LSCP_SPLIT_SIZE(lscp_midi_instruments_count(pInstrs));
828    }
829    
830    #endif // LSCP_MIDI_INSTRUMENTS_COUNT
831    
832    
833    //-------------------------------------------------------------------------
834    // Server info struct helper functions.
835    
836    void lscp_server_info_init ( lscp_server_info_t *pServerInfo )
837    {
838            pServerInfo->description      = NULL;
839            pServerInfo->version          = NULL;
840            pServerInfo->protocol_version = NULL;
841    }
842    
843    void lscp_server_info_free ( lscp_server_info_t *pServerInfo )
844    {
845            if (pServerInfo->description)
846                    free(pServerInfo->description);
847            if (pServerInfo->version)
848                    free(pServerInfo->version);
849            if (pServerInfo->protocol_version)
850                    free(pServerInfo->protocol_version);
851    }
852    
853    void lscp_server_info_reset ( lscp_server_info_t *pServerInfo )
854    {
855            lscp_server_info_free(pServerInfo);
856            lscp_server_info_init(pServerInfo);
857    }
858    
859    
860  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
861  // Engine info struct helper functions.  // Engine info struct helper functions.
862    
863  void lscp_engine_info_init ( lscp_engine_info_t *pEngineInfo )  void lscp_engine_info_init ( lscp_engine_info_t *pEngineInfo )
864  {  {
865      pEngineInfo->description = NULL;          pEngineInfo->description = NULL;
866      pEngineInfo->version     = NULL;          pEngineInfo->version     = NULL;
867  }  }
868    
869  void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo )  void lscp_engine_info_free ( lscp_engine_info_t *pEngineInfo )
870  {  {
871      if (pEngineInfo->description)          if (pEngineInfo->description)
872          free(pEngineInfo->description);                  free(pEngineInfo->description);
873      if (pEngineInfo->version)          if (pEngineInfo->version)
874          free(pEngineInfo->version);                  free(pEngineInfo->version);
875    }
876    
877      lscp_engine_info_init(pEngineInfo);  void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo )
878    {
879            lscp_engine_info_free(pEngineInfo);
880            lscp_engine_info_init(pEngineInfo);
881  }  }
882    
883    
# Line 444  void lscp_engine_info_reset ( lscp_engin Line 886  void lscp_engine_info_reset ( lscp_engin
886    
887  void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )  void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )
888  {  {
889      pChannelInfo->engine_name       = NULL;          pChannelInfo->engine_name       = NULL;
890      pChannelInfo->audio_device      = 0;          pChannelInfo->audio_device      = 0;
891      pChannelInfo->audio_channels    = 0;          pChannelInfo->audio_channels    = 0;
892      pChannelInfo->audio_routing     = NULL;          pChannelInfo->audio_routing     = NULL;
893      pChannelInfo->instrument_file   = NULL;          pChannelInfo->instrument_file   = NULL;
894      pChannelInfo->instrument_nr     = 0;          pChannelInfo->instrument_nr     = 0;
895      pChannelInfo->instrument_status = 0;          pChannelInfo->instrument_name   = NULL;
896      pChannelInfo->midi_device       = 0;          pChannelInfo->instrument_status = 0;
897      pChannelInfo->midi_port         = 0;          pChannelInfo->midi_device       = 0;
898      pChannelInfo->midi_channel      = 0;          pChannelInfo->midi_port         = 0;
899      pChannelInfo->volume            = 0.0;          pChannelInfo->midi_channel      = 0;
900            pChannelInfo->midi_map          = 0;
901            pChannelInfo->volume            = 0.0;
902            pChannelInfo->mute              = 0;
903            pChannelInfo->solo              = 0;
904  }  }
905    
906  void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo )  void lscp_channel_info_free ( lscp_channel_info_t *pChannelInfo )
907  {  {
908      if (pChannelInfo->engine_name)          if (pChannelInfo->engine_name)
909          free(pChannelInfo->engine_name);                  free(pChannelInfo->engine_name);
910      if (pChannelInfo->audio_routing)          if (pChannelInfo->audio_routing)
911          lscp_szsplit_destroy(pChannelInfo->audio_routing);                  lscp_szsplit_destroy(pChannelInfo->audio_routing);
912      if (pChannelInfo->instrument_file)          if (pChannelInfo->instrument_file)
913          free(pChannelInfo->instrument_file);                  free(pChannelInfo->instrument_file);
914            if (pChannelInfo->instrument_name)
915                    free(pChannelInfo->instrument_name);
916    }
917    
918      lscp_channel_info_init(pChannelInfo);  void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo )
919    {
920            lscp_channel_info_free(pChannelInfo);
921            lscp_channel_info_init(pChannelInfo);
922  }  }
923    
924    
# Line 475  void lscp_channel_info_reset ( lscp_chan Line 927  void lscp_channel_info_reset ( lscp_chan
927    
928  void lscp_driver_info_init ( lscp_driver_info_t *pDriverInfo )  void lscp_driver_info_init ( lscp_driver_info_t *pDriverInfo )
929  {  {
930      pDriverInfo->description = NULL;          pDriverInfo->description = NULL;
931      pDriverInfo->version     = NULL;          pDriverInfo->version     = NULL;
932      pDriverInfo->parameters  = NULL;          pDriverInfo->parameters  = NULL;
933    }
934    
935    void lscp_driver_info_free ( lscp_driver_info_t *pDriverInfo )
936    {
937            if (pDriverInfo->description)
938                    free(pDriverInfo->description);
939            if (pDriverInfo->version)
940                    free(pDriverInfo->version);
941            lscp_szsplit_destroy(pDriverInfo->parameters);
942  }  }
943    
944  void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo )  void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo )
945  {  {
946      if (pDriverInfo->description)          lscp_driver_info_free(pDriverInfo);
947          free(pDriverInfo->description);          lscp_driver_info_init(pDriverInfo);
948      if (pDriverInfo->version)  }
949          free(pDriverInfo->version);  
950      lscp_szsplit_destroy(pDriverInfo->parameters);  
951    //-------------------------------------------------------------------------
952    // Device info struct functions.
953    
954    void lscp_device_info_init ( lscp_device_info_t *pDeviceInfo )
955    {
956            pDeviceInfo->driver = NULL;
957            lscp_plist_alloc(&(pDeviceInfo->params));
958    }
959    
960    void lscp_device_info_free ( lscp_device_info_t *pDeviceInfo )
961    {
962            if (pDeviceInfo->driver)
963                    free(pDeviceInfo->driver);
964            lscp_plist_free(&(pDeviceInfo->params));
965    }
966    
967    void lscp_device_info_reset ( lscp_device_info_t *pDeviceInfo )
968    {
969            lscp_device_info_free(pDeviceInfo);
970            lscp_device_info_init(pDeviceInfo);
971    }
972    
973    
974    //-------------------------------------------------------------------------
975    // Device channel/port info struct functions.
976    
977      lscp_driver_info_init(pDriverInfo);  void lscp_device_port_info_init ( lscp_device_port_info_t *pDevicePortInfo )
978    {
979            pDevicePortInfo->name = NULL;
980            lscp_plist_alloc(&(pDevicePortInfo->params));
981    }
982    
983    void lscp_device_port_info_free ( lscp_device_port_info_t *pDevicePortInfo )
984    {
985            if (pDevicePortInfo->name)
986                    free(pDevicePortInfo->name);
987            lscp_plist_free(&(pDevicePortInfo->params));
988    }
989    
990    void lscp_device_port_info_reset ( lscp_device_port_info_t *pDevicePortInfo )
991    {
992            lscp_device_port_info_free(pDevicePortInfo);
993            lscp_device_port_info_init(pDevicePortInfo);
994    }
995    
996    
997    //-------------------------------------------------------------------------
998    // Parameter struct helper functions.
999    
1000    void lscp_param_info_init ( lscp_param_info_t *pParamInfo )
1001    {
1002            pParamInfo->type          = LSCP_TYPE_NONE;
1003            pParamInfo->description   = NULL;
1004            pParamInfo->mandatory     = 0;
1005            pParamInfo->fix           = 0;
1006            pParamInfo->multiplicity  = 0;
1007            pParamInfo->depends       = NULL;
1008            pParamInfo->defaultv      = NULL;
1009            pParamInfo->range_min     = NULL;
1010            pParamInfo->range_max     = NULL;
1011            pParamInfo->possibilities = NULL;
1012    }
1013    
1014    void lscp_param_info_free ( lscp_param_info_t *pParamInfo )
1015    {
1016            if (pParamInfo->description)
1017                    free(pParamInfo->description);
1018            lscp_szsplit_destroy(pParamInfo->depends);
1019            if (pParamInfo->defaultv)
1020                    free(pParamInfo->defaultv);
1021            if (pParamInfo->range_min)
1022                    free(pParamInfo->range_min);
1023            if (pParamInfo->range_max)
1024                    free(pParamInfo->range_max);
1025            lscp_szsplit_destroy(pParamInfo->possibilities);
1026    }
1027    
1028    void lscp_param_info_reset ( lscp_param_info_t *pParamInfo )
1029    {
1030            lscp_param_info_free(pParamInfo);
1031            lscp_param_info_init(pParamInfo);
1032    }
1033    
1034    
1035    //-------------------------------------------------------------------------
1036    // Concatenate a parameter list (key='value'...) into a string,
1037    // appending a crlf terminator.
1038    
1039    int lscp_param_concat ( char *pszBuffer, int cchMaxBuffer, lscp_param_t *pParams )
1040    {
1041            int cchBuffer, cchParam, i;
1042    
1043            if (pszBuffer == NULL)
1044                    return 0;
1045    
1046            cchBuffer = strlen(pszBuffer);
1047            for (i = 0; pParams && pParams[i].key && pParams[i].value; i++) {
1048                    cchParam = strlen(pParams[i].key) + strlen(pParams[i].value) + 4;
1049                    if (cchBuffer + cchParam + 2 < cchMaxBuffer) {
1050                            sprintf(pszBuffer + cchBuffer, " %s='%s'", pParams[i].key, pParams[i].value);
1051                            cchBuffer += cchParam;
1052                    }
1053            }
1054            
1055            if (cchBuffer + 2 < cchMaxBuffer) {
1056                    pszBuffer[cchBuffer++] = '\r';
1057                    pszBuffer[cchBuffer++] = '\n';
1058                    pszBuffer[cchBuffer ]  = (char) 0;
1059            }
1060            
1061            return cchBuffer;
1062    }
1063    
1064    
1065    //-------------------------------------------------------------------------
1066    // MIDI instrument info struct helper functions.
1067    
1068    void lscp_midi_instrument_info_init ( lscp_midi_instrument_info_t *pInstrInfo )
1069    {
1070            pInstrInfo->name              = NULL;
1071            pInstrInfo->engine_name       = NULL;
1072            pInstrInfo->instrument_file   = NULL;
1073            pInstrInfo->instrument_nr     = 0;
1074            pInstrInfo->instrument_name   = NULL;
1075            pInstrInfo->load_mode         = LSCP_LOAD_DEFAULT;
1076            pInstrInfo->volume            = 0.0;
1077    }
1078    
1079    void lscp_midi_instrument_info_free ( lscp_midi_instrument_info_t *pInstrInfo )
1080    {
1081            if (pInstrInfo->name)
1082                    free(pInstrInfo->name);
1083            if (pInstrInfo->engine_name)
1084                    free(pInstrInfo->engine_name);
1085            if (pInstrInfo->instrument_file)
1086                    free(pInstrInfo->instrument_file);
1087            if (pInstrInfo->instrument_name)
1088                    free(pInstrInfo->instrument_name);
1089    }
1090    
1091    void lscp_midi_instrument_info_reset ( lscp_midi_instrument_info_t *pInstrInfo )
1092    {
1093            lscp_midi_instrument_info_free(pInstrInfo);
1094            lscp_midi_instrument_info_init(pInstrInfo);
1095  }  }
1096    
1097    

Legend:
Removed from v.144  
changed lines
  Added in v.977

  ViewVC Help
Powered by ViewVC