/[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 946 by capela, Mon Nov 27 18:33:02 2006 UTC revision 948 by capela, Tue Nov 28 15:31:20 2006 UTC
# Line 107  lscp_status_t lscp_client_recv ( lscp_cl Line 107  lscp_status_t lscp_client_recv ( lscp_cl
107    
108    
109  // The main client requester call executive.  // The main client requester call executive.
110  lscp_status_t lscp_client_call ( lscp_client_t *pClient, const char *pszQuery )  lscp_status_t lscp_client_call ( lscp_client_t *pClient, const char *pszQuery, int iResult )
111  {  {
112      int    cchQuery;      int    cchQuery;
113      char   achResult[LSCP_BUFSIZ];      char   achBuffer[LSCP_BUFSIZ];
114      int    cchResult;      int    cchBuffer;
115      const  char *pszSeps = ":[]";      const  char *pszSeps = ":[]";
116      char  *pszResult;      char  *pszBuffer;
117      char  *pszToken;      char  *pszToken;
118      char  *pch;      char  *pch;
119      int    iErrno;      int    iErrno;
120        char  *pszResult;
121        int    cchResult;
122        
123      lscp_status_t ret = LSCP_FAILED;      lscp_status_t ret = LSCP_FAILED;
124        
125      if (pClient == NULL)      if (pClient == NULL)
126          return ret;          return ret;
127        
     pszResult = NULL;  
128      iErrno = -1;      iErrno = -1;
129        cchResult = 0;
130        pszResult = NULL;
131        pszBuffer = NULL;
132        
133      // Check if command socket socket is still valid.      // Check if command socket socket is still valid.
134      if (pClient->cmd.sock == INVALID_SOCKET) {      if (pClient->cmd.sock == INVALID_SOCKET) {
135          pszResult = "Connection closed or no longer valid";          pszResult = "Connection closed or no longer valid";
136          lscp_client_set_result(pClient, pszResult, iErrno);          lscp_client_set_result(pClient, pszResult, iErrno);
137          return ret;          return ret;
138      }      }
139        
140          // Check if last transaction has timed out, in which case      // Check if last transaction has timed out, in which case
141          // we'll retry wait and flush for some pending garbage...      // we'll retry wait and flush for some pending garbage...
142          if (pClient->iTimeoutCount > 0) {      if (pClient->iTimeoutCount > 0) {
143                  cchResult = sizeof(achResult);          // We'll hope to get rid of timeout trouble...
144                  ret = lscp_client_recv(pClient, achResult, &cchResult, pClient->iTimeout);          pClient->iTimeoutCount = 0;
145                  if (ret == LSCP_OK) {          cchBuffer = sizeof(achBuffer);
146                          // We've got rid of timeout trouble (hopefully).          ret = lscp_client_recv(pClient, achBuffer, &cchBuffer, pClient->iTimeout);
147                          pClient->iTimeoutCount = 0;          if (ret != LSCP_OK) {
148                  } else {              // Things seems to be unresolved. Fake a result message.
149                          // Things are worse than before. Fake a result message.              iErrno = (int) ret;
150                          iErrno = (int) ret;              pszResult = "Failure during flush timeout operation";
151                          pszResult = "Failure during flush timeout operation";              lscp_client_set_result(pClient, pszResult, iErrno);
152                          lscp_client_set_result(pClient, pszResult, iErrno);              return ret;
153                          return ret;          }
154                  }      }
155          }      
   
156      // Send data, and then, wait for the result...      // Send data, and then, wait for the result...
157      cchQuery = strlen(pszQuery);      cchQuery = strlen(pszQuery);
158      if (send(pClient->cmd.sock, pszQuery, cchQuery, 0) < cchQuery) {      if (send(pClient->cmd.sock, pszQuery, cchQuery, 0) < cchQuery) {
# Line 158  lscp_status_t lscp_client_call ( lscp_cl Line 161  lscp_status_t lscp_client_call ( lscp_cl
161          lscp_client_set_result(pClient, pszResult, iErrno);          lscp_client_set_result(pClient, pszResult, iErrno);
162          return ret;          return ret;
163      }      }
164        
165      // Wait for receive event...      // Keep receiving while result is not the expected one:
166      cchResult = sizeof(achResult);      // single-line result (iResult = 0) : one single CRLF ends the receipt;
167      ret = lscp_client_recv(pClient, achResult, &cchResult, pClient->iTimeout);      // multi-line result  (iResult > 0) : one "." followed by a last CRLF;
168        
169      switch (ret) {      while (pszResult == NULL) {
170        
171        case LSCP_OK:          // Wait for receive event...
172          // Always force the result to be null terminated (and trim trailing CRLFs)!          cchBuffer = sizeof(achBuffer) - 1;
173          while (cchResult > 0 && (achResult[cchResult - 1] == '\n' || achResult[cchResult- 1] == '\r'))          ret = lscp_client_recv(pClient, achBuffer, &cchBuffer, pClient->iTimeout);
174              cchResult--;      
175          achResult[cchResult] = (char) 0;          switch (ret) {
176          // Check if the response it's an error or warning message.      
177          if (strncasecmp(achResult, "WRN:", 4) == 0)            case LSCP_OK:
178              ret = LSCP_WARNING;              // Always force the result to be null terminated.
179          else if (strncasecmp(achResult, "ERR:", 4) == 0)              achBuffer[cchBuffer] = (char) 0;
180              ret = LSCP_ERROR;              // Check if the response it's an error or warning message.
181          // So we got a result...              if (strncasecmp(achBuffer, "WRN:", 4) == 0)
182          if (ret == LSCP_OK) {                  ret = LSCP_WARNING;
183              // Reset errno in case of success.              else if (strncasecmp(achBuffer, "ERR:", 4) == 0)
184              iErrno = 0;                  ret = LSCP_ERROR;
185              // Is it a special successful response?              // So we got a result...
186              if (strncasecmp(achResult, "OK[", 3) == 0) {              if (ret == LSCP_OK) {
187                  // Parse the OK message, get the return string under brackets...                  // Reset errno in case of success.
188                  pszToken = lscp_strtok(achResult, pszSeps, &(pch));                  iErrno = 0;
189                  if (pszToken)                  // Is it a special successful response?
190                      pszResult = lscp_strtok(NULL, pszSeps, &(pch));                  if (iResult < 1 && strncasecmp(achBuffer, "OK[", 3) == 0) {
191              }                      // Parse the OK message, get the return string under brackets...
192              else pszResult = achResult;                      pszToken = lscp_strtok(achBuffer, pszSeps, &(pch));
193              // The result string is now set to the command response, if any.                      if (pszToken)
194          } else {                          pszResult = lscp_strtok(NULL, pszSeps, &(pch));
195              // Parse the error/warning message, skip first colon...                  } else {
196              pszToken = lscp_strtok(achResult, pszSeps, &(pch));                      // It can be specially long response...
197              if (pszToken) {                      cchResult += sizeof(achBuffer);
198                  // Get the error number...                      pszResult  = malloc(cchResult + 1);
199                  pszToken = lscp_strtok(NULL, pszSeps, &(pch));                      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) {                  if (pszToken) {
230                      iErrno = atoi(pszToken);                      // Get the error number...
231                      // And make the message text our final result.                      pszToken = lscp_strtok(NULL, pszSeps, &(pch));
232                      pszResult = lscp_strtok(NULL, pszSeps, &(pch));                      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              // The result string is set to the error/warning message text.              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          }          }
         break;  
   
       case LSCP_TIMEOUT:  
                 // We have trouble...  
                 pClient->iTimeoutCount++;  
         // Fake a result message.  
         pszResult = "Timeout during receive operation";  
         iErrno = (int) ret;  
         break;  
   
       case LSCP_QUIT:  
         // Fake a result message.  
         pszResult = "Server terminated the connection";  
         iErrno = (int) ret;  
         break;  
   
       case LSCP_FAILED:  
       default:  
         // What's down?  
         pszResult = "Failure during receive operation";  
         break;  
262      }      }
263        
264      // Make the result official...      // Make the result official...
265      lscp_client_set_result(pClient, pszResult, iErrno);      lscp_client_set_result(pClient, pszResult, iErrno);
266        
267        // Free long-buffer, if any...
268        if (pszBuffer)
269            free(pszBuffer);
270        
271      return ret;      return ret;
272  }  }
273    
# Line 678  int lscp_plist_size ( lscp_param_t **ppL Line 718  int lscp_plist_size ( lscp_param_t **ppL
718  #endif // LSCP_PLIST_COUNT  #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.  // Server info struct helper functions.
829    

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

  ViewVC Help
Powered by ViewVC