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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 158 - (show annotations) (download)
Tue Jun 29 16:39:11 2004 UTC (15 years, 9 months ago) by capela
File MIME type: text/plain
File size: 16847 byte(s)
Initial split parameter array code.

1 // common.c
2 //
3 /****************************************************************************
4 liblscp - LinuxSampler Control Protocol API
5 Copyright (C) 2004, 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 Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 // The main client requester call executive.
53 lscp_status_t lscp_client_call ( lscp_client_t *pClient, const char *pszQuery )
54 {
55 fd_set fds; // File descriptor list for select().
56 int fd, fdmax; // Maximum file descriptor number.
57 struct timeval tv; // For specifying a timeout value.
58 int iSelect; // Holds select return status.
59 int iTimeout;
60 int cchQuery;
61 char achResult[LSCP_BUFSIZ];
62 int cchResult;
63 const char *pszSeps = ":[]";
64 char *pszResult;
65 char *pszToken;
66 char *pch;
67 int iErrno;
68
69 lscp_status_t ret = LSCP_FAILED;
70
71 if (pClient == NULL)
72 return ret;
73
74 pszResult = NULL;
75 iErrno = -1;
76
77 // Check if command socket socket is still valid.
78 if (pClient->cmd.sock == INVALID_SOCKET) {
79 pszResult = "Connection closed or no longer valid";
80 lscp_client_set_result(pClient, pszResult, iErrno);
81 return ret;
82 }
83
84 // Send data, and then, wait for the result...
85 cchQuery = strlen(pszQuery);
86 if (send(pClient->cmd.sock, pszQuery, cchQuery, 0) < cchQuery) {
87 lscp_socket_perror("_lscp_client_call: send");
88 pszResult = "Failure during send operation";
89 lscp_client_set_result(pClient, pszResult, iErrno);
90 return ret;
91 }
92
93 // Prepare for waiting on select...
94 fd = (int) pClient->cmd.sock;
95 FD_ZERO(&fds);
96 FD_SET((unsigned int) fd, &fds);
97 fdmax = fd;
98
99 // Use the timeout select feature...
100 iTimeout = pClient->iTimeout;
101 if (iTimeout > 1000) {
102 tv.tv_sec = iTimeout / 1000;
103 iTimeout -= tv.tv_sec * 1000;
104 }
105 else tv.tv_sec = 0;
106 tv.tv_usec = iTimeout * 1000;
107
108 // Wait for event...
109 iSelect = select(fdmax + 1, &fds, NULL, NULL, &tv);
110 if (iSelect > 0 && FD_ISSET(fd, &fds)) {
111 // May recv now...
112 cchResult = recv(pClient->cmd.sock, achResult, sizeof(achResult), 0);
113 if (cchResult > 0) {
114 // Assume early success.
115 ret = LSCP_OK;
116 // Always force the result to be null terminated (and trim trailing CRLFs)!
117 while (cchResult > 0 && (achResult[cchResult - 1] == '\n' || achResult[cchResult- 1] == '\r'))
118 cchResult--;
119 achResult[cchResult] = (char) 0;
120 // Check if the response it's an error or warning message.
121 if (strncasecmp(achResult, "WRN:", 4) == 0)
122 ret = LSCP_WARNING;
123 else if (strncasecmp(achResult, "ERR:", 4) == 0)
124 ret = LSCP_ERROR;
125 // So we got a result...
126 if (ret == LSCP_OK) {
127 // Reset errno in case of success.
128 iErrno = 0;
129 // Is it a special successful response?
130 if (strncasecmp(achResult, "OK[", 3) == 0) {
131 // Parse the OK message, get the return string under brackets...
132 pszToken = lscp_strtok(achResult, pszSeps, &(pch));
133 if (pszToken)
134 pszResult = lscp_strtok(NULL, pszSeps, &(pch));
135 }
136 else pszResult = achResult;
137 // The result string is now set to the command response, if any.
138 } else {
139 // Parse the error/warning message, skip first colon...
140 pszToken = lscp_strtok(achResult, pszSeps, &(pch));
141 if (pszToken) {
142 // Get the error number...
143 pszToken = lscp_strtok(NULL, pszSeps, &(pch));
144 if (pszToken) {
145 iErrno = atoi(pszToken);
146 // And make the message text our final result.
147 pszResult = lscp_strtok(NULL, pszSeps, &(pch));
148 }
149 }
150 // The result string is set to the error/warning message text.
151 }
152 }
153 else if (cchResult == 0) {
154 // Damn, server disconnected, we better free everything down here.
155 lscp_socket_agent_free(&(pClient->evt));
156 lscp_socket_agent_free(&(pClient->cmd));
157 // Fake a result message.
158 ret = LSCP_QUIT;
159 pszResult = "Server terminated the connection";
160 iErrno = (int) ret;
161 } else {
162 // What's down?
163 lscp_socket_perror("_lscp_client_call: recv");
164 pszResult = "Failure during receive operation";
165 }
166 } // Check if select has timed out.
167 else if (iSelect == 0) {
168 // Fake a result message.
169 ret = LSCP_TIMEOUT;
170 pszResult = "Timeout during receive operation";
171 iErrno = (int) ret;
172 }
173 else lscp_socket_perror("_lscp_client_call: select");
174
175 // Make the result official...
176 lscp_client_set_result(pClient, pszResult, iErrno);
177
178 return ret;
179 }
180
181
182 //-------------------------------------------------------------------------
183 // Other general utility functions.
184
185 // Trimming left spaces...
186 char *lscp_ltrim ( char *psz )
187 {
188 while (isspace(*psz))
189 psz++;
190 return psz;
191 }
192
193 // Unquote an in-split string.
194 char *lscp_unquote ( char **ppsz, int dup )
195 {
196 char chQuote;
197 char *psz = *ppsz;
198
199 while (isspace(*psz))
200 ++psz;
201 if (*psz == '\"' || *psz == '\'') {
202 chQuote = *psz++;
203 while (isspace(*psz))
204 ++psz;
205 if (dup)
206 psz = strdup(psz);
207 *ppsz = psz;
208 if (*ppsz) {
209 while (**ppsz && **ppsz != chQuote)
210 ++(*ppsz);
211 if (**ppsz) {
212 while (isspace(*(*ppsz - 1)) && *ppsz > psz)
213 --(*ppsz);
214 *(*ppsz)++ = (char) 0;
215 }
216 }
217 }
218 else if (dup) {
219 psz = strdup(psz);
220 *ppsz = psz;
221 }
222
223 return psz;
224 }
225
226
227 // Custom tokenizer.
228 char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )
229 {
230 char *pszToken;
231
232 if (pchBuffer == NULL)
233 pchBuffer = *ppch;
234
235 pchBuffer += strspn(pchBuffer, pszSeps);
236 if (*pchBuffer == '\0')
237 return NULL;
238
239 pszToken = pchBuffer;
240 pchBuffer = strpbrk(pszToken, pszSeps);
241 if (pchBuffer == NULL) {
242 *ppch = strchr(pszToken, '\0');
243 } else {
244 *pchBuffer = '\0';
245 *ppch = pchBuffer + 1;
246 while (**ppch && strchr(pszSeps, **ppch))
247 (*ppch)++;
248 }
249
250 return pszToken;
251 }
252
253
254 // Split a comma separated string into a null terminated array of strings.
255 char **lscp_szsplit_create ( const char *pszCsv, const char *pszSeps )
256 {
257 char *pszHead, *pch;
258 int iSize, i, j, cchSeps;
259 char **ppszSplit, **ppszNewSplit;
260
261 // Initial size is one chunk away.
262 iSize = LSCP_SPLIT_CHUNK1;
263 // Allocate and split...
264 ppszSplit = (char **) malloc(iSize * sizeof(char *));
265 if (ppszSplit == NULL)
266 return NULL;
267
268 // Make a copy of the original string.
269 i = 0;
270 pszHead = (char *) pszCsv;
271 if ((ppszSplit[i++] = lscp_unquote(&pszHead, 1)) == NULL) {
272 free(ppszSplit);
273 return NULL;
274 }
275
276 // Go on for it...
277 cchSeps = strlen(pszSeps);
278 while ((pch = strpbrk(pszHead, pszSeps)) != NULL) {
279 // Pre-advance to next item.
280 pszHead = pch + cchSeps;
281 // Trim and null terminate current item.
282 while (isspace(*(pch - 1)) && pch > ppszSplit[0])
283 --pch;
284 *pch = (char) 0;
285 // Make it official.
286 ppszSplit[i++] = lscp_unquote(&pszHead, 0);
287 // Do we need to grow?
288 if (i >= iSize) {
289 // Yes, but only grow in chunks.
290 iSize += LSCP_SPLIT_CHUNK1;
291 // Allocate and copy to new split array.
292 ppszNewSplit = (char **) malloc(iSize * sizeof(char *));
293 if (ppszNewSplit) {
294 for (j = 0; j < i; j++)
295 ppszNewSplit[j] = ppszSplit[j];
296 free(ppszSplit);
297 ppszSplit = ppszNewSplit;
298 }
299 }
300 }
301
302 // NULL terminate split array.
303 for ( ; i < iSize; i++)
304 ppszSplit[i] = NULL;
305
306 return ppszSplit;
307 }
308
309
310 // Free allocated memory of a legal null terminated array of strings.
311 void lscp_szsplit_destroy ( char **ppszSplit )
312 {
313 // Our split string is always the first item, if any.
314 if (ppszSplit && ppszSplit[0])
315 free(ppszSplit[0]);
316 // Now free the array itself.
317 if (ppszSplit)
318 free(ppszSplit);
319 }
320
321
322 #ifdef LSCP_SZSPLIT_COUNT
323
324 // Return the number of items of a null terminated array of strings.
325 int lscp_szsplit_count ( char **ppszSplit )
326 {
327 int i = 0;
328 while (ppszSplit && ppszSplit[i])
329 i++;
330 return i;
331 }
332
333 // Return the allocated number of items of a splitted string array.
334 int lscp_szsplit_size ( char **ppszSplit )
335 {
336 return LSCP_SPLIT_SIZE(lscp_szsplit_count(ppszSplit));
337 }
338
339 #endif // LSCP_SZSPLIT_COUNT
340
341
342 // Split a comma separated string into a -1 terminated array of positive integers.
343 int *lscp_isplit_create ( const char *pszCsv, const char *pszSeps )
344 {
345 char *pchHead, *pch;
346 int iSize, i, j, cchSeps;
347 int *piSplit, *piNewSplit;
348
349 // Initial size is one chunk away.
350 iSize = LSCP_SPLIT_CHUNK1;
351 // Allocate and split...
352 piSplit = (int *) malloc(iSize * sizeof(int));
353 if (piSplit == NULL)
354 return NULL;
355
356 // Make a copy of the original string.
357 i = 0;
358 pchHead = (char *) pszCsv;
359 if ((piSplit[i++] = atoi(pchHead)) < 0) {
360 free(piSplit);
361 return NULL;
362 }
363
364 // Go on for it...
365 cchSeps = strlen(pszSeps);
366 while ((pch = strpbrk(pchHead, pszSeps)) != NULL) {
367 // Pre-advance to next item.
368 pchHead = pch + cchSeps;
369 // Make it official.
370 piSplit[i++] = atoi(pchHead);
371 // Do we need to grow?
372 if (i >= iSize) {
373 // Yes, but only grow in chunks.
374 iSize += LSCP_SPLIT_CHUNK1;
375 // Allocate and copy to new split array.
376 piNewSplit = (int *) malloc(iSize * sizeof(int));
377 if (piNewSplit) {
378 for (j = 0; j < i; j++)
379 piNewSplit[j] = piSplit[j];
380 free(piSplit);
381 piSplit = piNewSplit;
382 }
383 }
384 }
385
386 // NULL terminate split array.
387 for ( ; i < iSize; i++)
388 piSplit[i] = -1;
389
390 return piSplit;
391 }
392
393
394 // Destroy a integer splitted array.
395 void lscp_isplit_destroy ( int *piSplit )
396 {
397 if (piSplit)
398 free(piSplit);
399 }
400
401
402 #ifdef LSCP_ISPLIT_COUNT
403
404 // Compute a string list valid item count.
405 int lscp_isplit_count ( int *piSplit )
406 {
407 int i = 0;
408 while (piSplit && piSplit[i] >= 0)
409 i++;
410 return i;
411 }
412
413 // Compute a string list size.
414 int lscp_isplit_size ( int *piSplit )
415 {
416 return LSCP_SPLIT_SIZE(lscp_isplit_count(piSplit));
417 }
418
419 #endif // LSCP_ISPLIT_COUNT
420
421
422 // Split a string into a null terminated array of parameter items.
423 lscp_param_t *lscp_psplit_create ( const char *pszCsv, const char *pszSeps1, const char *pszSeps2 )
424 {
425 char *pszHead, *pch;
426 int iSize, i, j, cchSeps1, cchSeps2;
427 lscp_param_t *ppSplit, *ppNewSplit;
428
429 pszHead = strdup(pszCsv);
430 if (pszHead == NULL)
431 return NULL;
432
433 iSize = LSCP_SPLIT_CHUNK1;
434 ppSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t));
435 if (ppSplit == NULL) {
436 free(pszHead);
437 return NULL;
438 }
439
440 cchSeps1 = strlen(pszSeps1);
441 cchSeps2 = strlen(pszSeps2);
442
443 i = 0;
444 while ((pch = strpbrk(pszHead, pszSeps1)) != NULL) {
445 ppSplit[i].key = pszHead;
446 pszHead = pch + cchSeps1;
447 *pch = (char) 0;
448 ppSplit[i].value.psz = lscp_unquote(&pszHead, 0);
449 if ((pch = strpbrk(pszHead, pszSeps2)) != NULL) {
450 pszHead = pch + cchSeps2;
451 *pch = (char) 0;
452 }
453 if (++i >= iSize) {
454 iSize += LSCP_SPLIT_CHUNK1;
455 ppNewSplit = (lscp_param_t *) malloc(iSize * sizeof(lscp_param_t));
456 if (ppNewSplit) {
457 for (j = 0; j < i; j++) {
458 ppNewSplit[j].key = ppSplit[j].key;
459 ppNewSplit[j].value.psz = ppSplit[j].value.psz;
460 }
461 free(ppSplit);
462 ppSplit = ppNewSplit;
463 }
464 }
465 }
466
467 if (i < 1)
468 free(pszHead);
469
470 for ( ; i < iSize; i++) {
471 ppSplit[i].key = NULL;
472 ppSplit[i].value.psz = NULL;
473 }
474
475 return ppSplit;
476 }
477
478
479 // Destroy a parameter list array.
480 void lscp_psplit_destroy ( lscp_param_t *ppSplit )
481 {
482 if (ppSplit && ppSplit[0].key)
483 free(ppSplit[0].key);
484 if (ppSplit)
485 free(ppSplit);
486 }
487
488
489 #ifdef LSCP_PSPLIT_COUNT
490
491 // Compute a parameter list valid item count.
492 int lscp_psplit_count ( lscp_param_t *ppSplit )
493 {
494 int i = 0;
495 while (ppSplit && ppSplit[i].key)
496 i++;
497 return i;
498 }
499
500 // Compute a parameter list size.
501 int lscp_psplit_size ( lscp_param_t *ppSplit )
502 {
503 return LSCP_SPLIT_SIZE(lscp_psplit_count(ppSplit));
504 }
505
506 #endif // LSCP_PSPLIT_COUNT
507
508
509 //-------------------------------------------------------------------------
510 // Engine info struct helper functions.
511
512 void lscp_engine_info_init ( lscp_engine_info_t *pEngineInfo )
513 {
514 pEngineInfo->description = NULL;
515 pEngineInfo->version = NULL;
516 }
517
518 void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo )
519 {
520 if (pEngineInfo->description)
521 free(pEngineInfo->description);
522 if (pEngineInfo->version)
523 free(pEngineInfo->version);
524
525 lscp_engine_info_init(pEngineInfo);
526 }
527
528
529 //-------------------------------------------------------------------------
530 // Channel info struct helper functions.
531
532 void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )
533 {
534 pChannelInfo->engine_name = NULL;
535 pChannelInfo->audio_device = 0;
536 pChannelInfo->audio_channels = 0;
537 pChannelInfo->audio_routing = NULL;
538 pChannelInfo->instrument_file = NULL;
539 pChannelInfo->instrument_nr = 0;
540 pChannelInfo->instrument_status = 0;
541 pChannelInfo->midi_device = 0;
542 pChannelInfo->midi_port = 0;
543 pChannelInfo->midi_channel = 0;
544 pChannelInfo->volume = 0.0;
545 }
546
547 void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo )
548 {
549 if (pChannelInfo->engine_name)
550 free(pChannelInfo->engine_name);
551 if (pChannelInfo->audio_routing)
552 lscp_szsplit_destroy(pChannelInfo->audio_routing);
553 if (pChannelInfo->instrument_file)
554 free(pChannelInfo->instrument_file);
555
556 lscp_channel_info_init(pChannelInfo);
557 }
558
559
560 //-------------------------------------------------------------------------
561 // Driver info struct functions.
562
563 void lscp_driver_info_init ( lscp_driver_info_t *pDriverInfo )
564 {
565 pDriverInfo->description = NULL;
566 pDriverInfo->version = NULL;
567 pDriverInfo->parameters = NULL;
568 }
569
570 void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo )
571 {
572 if (pDriverInfo->description)
573 free(pDriverInfo->description);
574 if (pDriverInfo->version)
575 free(pDriverInfo->version);
576 lscp_szsplit_destroy(pDriverInfo->parameters);
577
578 lscp_driver_info_init(pDriverInfo);
579 }
580
581
582 // end of common.c

  ViewVC Help
Powered by ViewVC