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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3664 - (show annotations) (download)
Sun Dec 22 12:53:26 2019 UTC (4 years, 3 months ago) by schoenebeck
File MIME type: text/plain
File size: 28380 byte(s)
Improved connection error handling:

* Expose actual system error codes via client interface
  instead of just -1 whenever a syscall failed.

* Added new client interface function:
    lscp_client_connection_lost();
  for checking whether client lost connection to server.

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

  ViewVC Help
Powered by ViewVC