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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 948 - (show annotations) (download)
Tue Nov 28 15:31:20 2006 UTC (17 years, 4 months ago) by capela
File MIME type: text/plain
File size: 31618 byte(s)
* Fixed some compilation warnings due to suspicious type
  casting and unsused header macros.

* Changed deprecated copyright attribute to license
  and added ldconfig to post-(un)install steps
  to liblscp.spec (RPM).

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

  ViewVC Help
Powered by ViewVC