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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 952 - (show annotations) (download)
Tue Nov 28 22:46:32 2006 UTC (17 years, 4 months ago) by capela
File MIME type: text/plain
File size: 27295 byte(s)
Code cleanup; preparations for 0.4.1 release (hopefully).

1 // common.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 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
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
27
28 // Split chunk size magic:
29 // LSCP_SPLIT_CHUNK1 := 2 ^ LSCP_SPLIT_CHUNK2
30 #define LSCP_SPLIT_CHUNK1 4
31 #define LSCP_SPLIT_CHUNK2 2
32 // Chunk size legal calculator.
33 #define LSCP_SPLIT_SIZE(n) ((((n) >> LSCP_SPLIT_CHUNK2) + 1) << LSCP_SPLIT_CHUNK2)
34
35
36 //-------------------------------------------------------------------------
37 // 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);
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...
280 char *lscp_ltrim ( char *psz )
281 {
282 while (isspace(*psz))
283 psz++;
284 return psz;
285 }
286
287 // Unquote an in-split string.
288 char *lscp_unquote ( char **ppsz, int dup )
289 {
290 char chQuote;
291 char *psz = *ppsz;
292
293 while (isspace(*psz))
294 ++psz;
295 if (*psz == '\"' || *psz == '\'') {
296 chQuote = *psz++;
297 while (isspace(*psz))
298 ++psz;
299 if (dup)
300 psz = strdup(psz);
301 *ppsz = psz;
302 if (*ppsz) {
303 while (**ppsz && **ppsz != chQuote)
304 ++(*ppsz);
305 if (**ppsz) {
306 while (isspace(*(*ppsz - 1)) && *ppsz > psz)
307 --(*ppsz);
308 *(*ppsz)++ = (char) 0;
309 }
310 }
311 }
312 else if (dup) {
313 psz = strdup(psz);
314 *ppsz = psz;
315 }
316
317 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.
334 char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )
335 {
336 char *pszToken;
337
338 if (pchBuffer == NULL)
339 pchBuffer = *ppch;
340
341 pchBuffer += strspn(pchBuffer, pszSeps);
342 if (*pchBuffer == '\0')
343 return NULL;
344
345 pszToken = pchBuffer;
346 pchBuffer = strpbrk(pszToken, pszSeps);
347 if (pchBuffer == NULL) {
348 *ppch = strchr(pszToken, '\0');
349 } else {
350 *pchBuffer = '\0';
351 *ppch = pchBuffer + 1;
352 while (**ppch && strchr(pszSeps, **ppch))
353 (*ppch)++;
354 }
355
356 return pszToken;
357 }
358
359
360 // Split a comma separated string into a null terminated array of strings.
361 char **lscp_szsplit_create ( const char *pszCsv, const char *pszSeps )
362 {
363 char *pszHead, *pch;
364 int iSize, i, j, cchSeps;
365 char **ppszSplit, **ppszNewSplit;
366
367 // Initial size is one chunk away.
368 iSize = LSCP_SPLIT_CHUNK1;
369 // Allocate and split...
370 ppszSplit = (char **) malloc(iSize * sizeof(char *));
371 if (ppszSplit == NULL)
372 return NULL;
373
374 // Make a copy of the original string.
375 i = 0;
376 pszHead = (char *) pszCsv;
377 if ((ppszSplit[i++] = lscp_unquote(&pszHead, 1)) == NULL) {
378 free(ppszSplit);
379 return NULL;
380 }
381
382 // Go on for it...
383 cchSeps = strlen(pszSeps);
384 while ((pch = strpbrk(pszHead, pszSeps)) != NULL) {
385 // Pre-advance to next item.
386 pszHead = pch + cchSeps;
387 // Trim and null terminate current item.
388 while (isspace(*(pch - 1)) && pch > ppszSplit[0])
389 --pch;
390 *pch = (char) 0;
391 // Make it official.
392 ppszSplit[i] = lscp_unquote(&pszHead, 0);
393 // Do we need to grow?
394 if (++i >= iSize) {
395 // Yes, but only grow in chunks.
396 iSize += LSCP_SPLIT_CHUNK1;
397 // Allocate and copy to new split array.
398 ppszNewSplit = (char **) malloc(iSize * sizeof(char *));
399 if (ppszNewSplit) {
400 for (j = 0; j < i; j++)
401 ppszNewSplit[j] = ppszSplit[j];
402 free(ppszSplit);
403 ppszSplit = ppszNewSplit;
404 }
405 }
406 }
407
408 // NULL terminate split array.
409 for ( ; i < iSize; i++)
410 ppszSplit[i] = NULL;
411
412 return ppszSplit;
413 }
414
415
416 // Free allocated memory of a legal null terminated array of strings.
417 void lscp_szsplit_destroy ( char **ppszSplit )
418 {
419 // Our split string is always the first item, if any.
420 if (ppszSplit && ppszSplit[0])
421 free(ppszSplit[0]);
422 // Now free the array itself.
423 if (ppszSplit)
424 free(ppszSplit);
425 }
426
427
428 #ifdef LSCP_SZSPLIT_COUNT
429
430 // Return the number of items of a null terminated array of strings.
431 int lscp_szsplit_count ( char **ppszSplit )
432 {
433 int i = 0;
434 while (ppszSplit && ppszSplit[i])
435 i++;
436 return i;
437 }
438
439 // Return the allocated number of items of a splitted string array.
440 int lscp_szsplit_size ( char **ppszSplit )
441 {
442 return LSCP_SPLIT_SIZE(lscp_szsplit_count(ppszSplit));
443 }
444
445 #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.
854
855 void lscp_engine_info_init ( lscp_engine_info_t *pEngineInfo )
856 {
857 pEngineInfo->description = NULL;
858 pEngineInfo->version = NULL;
859 }
860
861 void lscp_engine_info_free ( lscp_engine_info_t *pEngineInfo )
862 {
863 if (pEngineInfo->description)
864 free(pEngineInfo->description);
865 if (pEngineInfo->version)
866 free(pEngineInfo->version);
867 }
868
869 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
876 //-------------------------------------------------------------------------
877 // Channel info struct helper functions.
878
879 void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )
880 {
881 pChannelInfo->engine_name = NULL;
882 pChannelInfo->audio_device = 0;
883 pChannelInfo->audio_channels = 0;
884 pChannelInfo->audio_routing = NULL;
885 pChannelInfo->instrument_file = NULL;
886 pChannelInfo->instrument_nr = 0;
887 pChannelInfo->instrument_name = NULL;
888 pChannelInfo->instrument_status = 0;
889 pChannelInfo->midi_device = 0;
890 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_free ( lscp_channel_info_t *pChannelInfo )
898 {
899 if (pChannelInfo->engine_name)
900 free(pChannelInfo->engine_name);
901 if (pChannelInfo->audio_routing)
902 lscp_szsplit_destroy(pChannelInfo->audio_routing);
903 if (pChannelInfo->instrument_file)
904 free(pChannelInfo->instrument_file);
905 if (pChannelInfo->instrument_name)
906 free(pChannelInfo->instrument_name);
907 }
908
909 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
916 //-------------------------------------------------------------------------
917 // Driver info struct functions.
918
919 void lscp_driver_info_init ( lscp_driver_info_t *pDriverInfo )
920 {
921 pDriverInfo->description = NULL;
922 pDriverInfo->version = NULL;
923 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 )
936 {
937 lscp_driver_info_free(pDriverInfo);
938 lscp_driver_info_init(pDriverInfo);
939 }
940
941
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 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
1089 // end of common.c

  ViewVC Help
Powered by ViewVC