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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 103 by capela, Fri Jun 4 14:32:51 2004 UTC revision 948 by capela, Tue Nov 28 15:31:20 2006 UTC
# Line 1  Line 1 
1  // client.c  // common.c
2  //  //
3  /****************************************************************************  /****************************************************************************
4     liblscp - LinuxSampler Control Protocol API     liblscp - LinuxSampler Control Protocol API
5     Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved.     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     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public     modify it under the terms of the GNU Lesser General Public
# Line 14  Line 14 
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15     Lesser General Public License for more details.     Lesser General Public License for more details.
16    
17     You should have received a copy of the GNU Lesser General Public     You should have received a copy of the GNU General Public License along
18     License along with this library; if not, write to the Free Software     with this program; if not, write to the Free Software Foundation, Inc.,
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20    
21  *****************************************************************************/  *****************************************************************************/
22    
# Line 25  Line 25 
25  #include <ctype.h>  #include <ctype.h>
26    
27    
28  // Chunk size magic:  // Split chunk size magic:
29  // LSCP_SPLIT_CHUNK1 = 2 ^ LSCP_SPLIT_CHUNK2  // LSCP_SPLIT_CHUNK1 := 2 ^ LSCP_SPLIT_CHUNK2
30  #define LSCP_SPLIT_CHUNK1   4  #define LSCP_SPLIT_CHUNK1   4
31  #define LSCP_SPLIT_CHUNK2   2  #define LSCP_SPLIT_CHUNK2   2
32  // Chunk size legal calculator.  // Chunk size legal calculator.
# Line 34  Line 34 
34    
35    
36  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
37  // General utility functions.  // 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...  // Trimming left spaces...
279  char *lscp_ltrim ( char *psz )  char *lscp_ltrim ( char *psz )
# Line 77  char *lscp_unquote ( char **ppsz, int du Line 316  char *lscp_unquote ( char **ppsz, int du
316      return psz;      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.  // Custom tokenizer.
333  char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )  char *lscp_strtok ( char *pchBuffer, const char *pszSeps, char **ppch )
# Line 137  char **lscp_szsplit_create ( const char Line 388  char **lscp_szsplit_create ( const char
388              --pch;              --pch;
389          *pch = (char) 0;          *pch = (char) 0;
390          // Make it official.          // Make it official.
391          ppszSplit[i++] = lscp_unquote(&pszHead, 0);          ppszSplit[i] = lscp_unquote(&pszHead, 0);
392          // Do we need to grow?          // Do we need to grow?
393          if (i >= iSize) {          if (++i >= iSize) {
394              // Yes, but only grow in chunks.              // Yes, but only grow in chunks.
395              iSize += LSCP_SPLIT_CHUNK1;              iSize += LSCP_SPLIT_CHUNK1;
396              // Allocate and copy to new split array.              // Allocate and copy to new split array.
# Line 193  int lscp_szsplit_size ( char **ppszSplit Line 444  int lscp_szsplit_size ( char **ppszSplit
444  #endif // LSCP_SZSPLIT_COUNT  #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.  // Engine info struct helper functions.
853    
# Line 202  void lscp_engine_info_init ( lscp_engine Line 857  void lscp_engine_info_init ( lscp_engine
857      pEngineInfo->version     = NULL;      pEngineInfo->version     = NULL;
858  }  }
859    
860  void lscp_engine_info_reset ( lscp_engine_info_t *pEngineInfo )  void lscp_engine_info_free ( lscp_engine_info_t *pEngineInfo )
861  {  {
862      if (pEngineInfo->description)      if (pEngineInfo->description)
863          free(pEngineInfo->description);          free(pEngineInfo->description);
864      if (pEngineInfo->version)      if (pEngineInfo->version)
865          free(pEngineInfo->version);          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);      lscp_engine_info_init(pEngineInfo);
872  }  }
873    
# Line 218  void lscp_engine_info_reset ( lscp_engin Line 877  void lscp_engine_info_reset ( lscp_engin
877    
878  void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )  void lscp_channel_info_init ( lscp_channel_info_t *pChannelInfo )
879  {  {
880      pChannelInfo->engine_name     = NULL;      pChannelInfo->engine_name       = NULL;
881      pChannelInfo->audio_device    = 0;      pChannelInfo->audio_device      = 0;
882      pChannelInfo->audio_channels  = 0;      pChannelInfo->audio_channels    = 0;
883      pChannelInfo->audio_routing   = NULL;      pChannelInfo->audio_routing     = NULL;
884      pChannelInfo->instrument_file = NULL;      pChannelInfo->instrument_file   = NULL;
885      pChannelInfo->instrument_nr   = 0;      pChannelInfo->instrument_nr     = 0;
886      pChannelInfo->midi_device     = 0;      pChannelInfo->instrument_name   = NULL;
887      pChannelInfo->midi_port       = 0;      pChannelInfo->instrument_status = 0;
888      pChannelInfo->midi_channel    = 0;      pChannelInfo->midi_device       = 0;
889      pChannelInfo->volume          = 0.0;      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_reset ( lscp_channel_info_t *pChannelInfo )  void lscp_channel_info_free ( lscp_channel_info_t *pChannelInfo )
897  {  {
898      if (pChannelInfo->engine_name)      if (pChannelInfo->engine_name)
899          free(pChannelInfo->engine_name);          free(pChannelInfo->engine_name);
# Line 238  void lscp_channel_info_reset ( lscp_chan Line 901  void lscp_channel_info_reset ( lscp_chan
901          lscp_szsplit_destroy(pChannelInfo->audio_routing);          lscp_szsplit_destroy(pChannelInfo->audio_routing);
902      if (pChannelInfo->instrument_file)      if (pChannelInfo->instrument_file)
903          free(pChannelInfo->instrument_file);          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);      lscp_channel_info_init(pChannelInfo);
912  }  }
913    
# Line 253  void lscp_driver_info_init ( lscp_driver Line 922  void lscp_driver_info_init ( lscp_driver
922      pDriverInfo->parameters  = NULL;      pDriverInfo->parameters  = NULL;
923  }  }
924    
925  void lscp_driver_info_reset ( lscp_driver_info_t *pDriverInfo )  void lscp_driver_info_free ( lscp_driver_info_t *pDriverInfo )
926  {  {
927      if (pDriverInfo->description)      if (pDriverInfo->description)
928          free(pDriverInfo->description);          free(pDriverInfo->description);
929      if (pDriverInfo->version)      if (pDriverInfo->version)
930          free(pDriverInfo->version);          free(pDriverInfo->version);
931      lscp_szsplit_destroy(pDriverInfo->parameters);      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);      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  // end of common.c

Legend:
Removed from v.103  
changed lines
  Added in v.948

  ViewVC Help
Powered by ViewVC