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

Legend:
Removed from v.103  
changed lines
  Added in v.963

  ViewVC Help
Powered by ViewVC