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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 144 - (show annotations) (download)
Thu Jun 24 18:25:11 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 14684 byte(s)
* Major change to client event protocol interface on attempt
  to comply with draft-protocol v.11.

* New function entries added: lscp_load_instrument_non_modal(),
  lscp_set_channel_audio_device() and lscp_set_channel_midi_device().

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 // 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 //-------------------------------------------------------------------------
423 // Engine info struct helper functions.
424
425 void lscp_engine_info_init ( lscp_engine_info_t *pEngineInfo )
426 {
427 pEngineInfo->description = NULL;
428 pEngineInfo->version = NULL;
429 }
430
431 void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo )
432 {
433 if (pEngineInfo->description)
434 free(pEngineInfo->description);
435 if (pEngineInfo->version)
436 free(pEngineInfo->version);
437
438 lscp_engine_info_init(pEngineInfo);
439 }
440
441
442 //-------------------------------------------------------------------------
443 // Channel info struct helper functions.
444
445 void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )
446 {
447 pChannelInfo->engine_name = NULL;
448 pChannelInfo->audio_device = 0;
449 pChannelInfo->audio_channels = 0;
450 pChannelInfo->audio_routing = NULL;
451 pChannelInfo->instrument_file = NULL;
452 pChannelInfo->instrument_nr = 0;
453 pChannelInfo->instrument_status = 0;
454 pChannelInfo->midi_device = 0;
455 pChannelInfo->midi_port = 0;
456 pChannelInfo->midi_channel = 0;
457 pChannelInfo->volume = 0.0;
458 }
459
460 void lscp_channel_info_reset ( lscp_channel_info_t *pChannelInfo )
461 {
462 if (pChannelInfo->engine_name)
463 free(pChannelInfo->engine_name);
464 if (pChannelInfo->audio_routing)
465 lscp_szsplit_destroy(pChannelInfo->audio_routing);
466 if (pChannelInfo->instrument_file)
467 free(pChannelInfo->instrument_file);
468
469 lscp_channel_info_init(pChannelInfo);
470 }
471
472
473 //-------------------------------------------------------------------------
474 // Driver info struct functions.
475
476 void lscp_driver_info_init ( lscp_driver_info_t *pDriverInfo )
477 {
478 pDriverInfo->description = NULL;
479 pDriverInfo->version = NULL;
480 pDriverInfo->parameters = NULL;
481 }
482
483 void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo )
484 {
485 if (pDriverInfo->description)
486 free(pDriverInfo->description);
487 if (pDriverInfo->version)
488 free(pDriverInfo->version);
489 lscp_szsplit_destroy(pDriverInfo->parameters);
490
491 lscp_driver_info_init(pDriverInfo);
492 }
493
494
495 // end of common.c

  ViewVC Help
Powered by ViewVC