Csound Csound-dev Csound-tekno Search About

Re: API - message callback

Date2007-08-01 14:08
FromVictor Lazzarini
SubjectRe: API - message callback
I never noticed that kind of behaviour on syntax
errors. It always worked fine just to build a string
with vsnprintf() and then send it on its way. Other
hosts do the same (eg. Rory's Lettuce) and I have
never heard any complaint.

Victor
>
>
> Well - I should have known.  I found the culprit.  Its
> calling the   callback for every character .. only doing
> this for syntax errors   though - so special code must be
> written to handle this case .. of   course the message
> handler doesn't know what it is going to receive   so ..
> special code must always be used.  It seems to me this
> synterr   function should construct a string and then call
> the message handler   once.
>
>
> void synterr(CSOUND *csound, const char *s, ...)
> {
>      va_list args;
>      char    *cp;
>      int     c;
>
>      csound->MessageS(csound, CSOUNDMSG_ERROR, Str("error:
>  "));
>      va_start(args, s);
>      csound->MessageV(csound, CSOUNDMSG_ERROR, s, args);
>      va_end(args);
>
>
>      /* FIXME - Removed temporarily for debugging
>       * This function may not be necessary at all in the
> end if some   of this is
>       * done in the parser
>       */
>      if (ST(linadr) != NULL && (cp =
> ST(linadr)[ST(curline)]) != NULL #if
> defined(ENABLE_NEW_PARSER)
>          && !csound->oparms->newParser
> #endif
>      ) {
>        csound->MessageS(csound, CSOUNDMSG_ERROR,
>                                 Str(", line %d:\n"),
> ST(curline));
>        do {
>          csound->MessageS(csound, CSOUNDMSG_ERROR, "%c",
> (c = *cp++));
>        } while (c != '\n');
>      }
>      else {
>        csound->MessageS(csound, CSOUNDMSG_ERROR, "\n");
>      }
>      csound->synterrcnt++;
> }
>
>
> greg
>
> On Jul 31, 2007, at 5:22 PM, Victor Lazzarini wrote:
>
> > I'm just eliminating the '\n' characters, because
> > PD's post() adds them and I don't want two newlines
> > after every msg string. It's just a formatting issue,
> > you don't need to do it if you are
> > just using printf() or fprintf() etc.
> >
> >>
> >> i understand using that using vsnprintf would allow me
> to >> get it to   work .. few questions though:
> >>
> >>
> >> if i == 0 and csmess[i] == '\0'
> >>     wouldn't  x->csmess[i - 1] = ' '  be illegal?
> >>
> >>
> >> I haven't analyzed the stream .. but is it just that
> 0's >> are being   written into it and this just replaces
> the >> character before it with a   space?  Why are some
> strings >> formatted correctly in the first place?    Why
> is any of >> this buffer manipulation necessary in the
> first place? >>
> >> greg
> >>
> >>
> >> On Jul 31, 2007, at 2:48 PM, Victor Lazzarini wrote:
> >>
> >>> Use vsnprintf(...).
> >>>
> >>> This is an example callback from csoundapi_tilde.c:
> >>>
> >>> static void message_callback(CSOUND *csound,
> >>>                    int attr, const char *format
> ,va_list >>>      valist){ int i;
> >>>      t_csoundapi *x = (t_csoundapi *)
> >>> csoundGetHostData(csound);
> >>>
> >>>      if(x->csmess != NULL)
> >>>      vsnprintf(x->csmess, MAXMESSTRING, format,
> valist); >>>      for(i=0;i >>>        if(x->csmess != NULL && x->csmess[i] == '\0'){
> >>>          x->csmess[i-1]= ' ';
> >>>          break;
> >>>        }
> >>>     if(x->csmess != NULL && x->messon) post(x->csmess)
> ; >>>   }
> >>>
> >>>
> >>>>
> >>>>
> >>>> I'm using the message callback because I want to pass
> >> the >> message   elsewhere (file, network, etc..):
> >>>>
> >>>> Here is my function:
> >>>>
> >>>> void csoundMessageHandler(CSOUND *csound, int attr,
> >> const >> char   *format, va_list valist) {
> >>>>     char messageData[256];
> >>>>      vsprintf(messageData, format, valist);
> >>>>      va_end(valist);
> >>>>
> >>>>     printf("messageData: %s\n", messageData);
> >>>> }
> >>>>
> >>>> Here is how I register it:
> >>>>      csoundSetMessageCallback(csound,
> >>>> csoundMessageHandler);
> >>>>
> >>>>
> >>>> Here is some of the output:
> >>>> messageData: rtaudio: PortAudio module enabled ...
> >>>> messageData: using callback interface
> >>>>
> >>>> messageData: rtmidi: PortMIDI module enabled
> >>>>
> >>>> messageData: orch compiler:
> >>>>
> >>>> messageData: 17 lines read
> >>>>
> >>>> messageData:
> >>>> messageData: instr
> >>>> messageData: 1
> >>>> messageData:
> >>>>
> >>>> messageData: error:
> >>>> messageData: input arg 'aOsc' used before defined
> >>>> messageData: , line 15:
> >>>>
> >>>> messageData:
> >>>> messageData: o
> >>>> messageData: u
> >>>> messageData: t
> >>>> messageData: s
> >>>> messageData:
> >>>> messageData: a
> >>>> messageData: O
> >>>> messageData: s
> >>>> messageData: c
> >>>> messageData: ,
> >>>> messageData:
> >>>> messageData: a
> >>>> messageData: O
> >>>> messageData: s
> >>>> messageData: c
> >>>> messageData:
> >>>>
> >>>> messageData: error:
> >>>> messageData: input arg 'aOsc' used before defined
> >>>> messageData: , line 15:
> >>>>
> >>>> messageData:
> >>>> messageData: o
> >>>> messageData: u
> >>>> messageData: t
> >>>> messageData: s
> >>>> messageData:
> >>>> messageData: a
> >>>> messageData: O
> >>>> messageData: s
> >>>> messageData: c
> >>>> messageData: ,
> >>>> messageData:
> >>>> messageData: a
> >>>> messageData: O
> >>>> messageData: s
> >>>> messageData: c
> >>>> messageData:
> >>>>
> >>>> messageData: 2 syntax errors in orchestra.
> compilation >>>> invalid messageData:
> >>>>
> >>>>
> >>>> It only seems to happen on errors (which are the most
> >>>> important   messages).   Is there a way to avoid
> these >>>> newlines so it can be   readable?
> >>>>
> >>>> thanks
> >>>> greg
> >>>>
> >>>>
> >>> --
> >>> Send bugs reports to this list.
> >>> To unsubscribe, send email to
> >> csound-unsubscribe@lists.bath.ac.uk >
> >>
> >> --
> >> Send bugs reports to this list.
> >> To unsubscribe, send email to
> >> csound-unsubscribe@lists.bath.ac.uk
> > --
> > Send bugs reports to this list.
> > To unsubscribe, send email to
> csound-unsubscribe@lists.bath.ac.uk >
>
>

Date2007-08-01 14:32
FromGreg Thompson
SubjectRe: API - message callback

Isn't is possible that the host does the buffering automatically on the other end?

Try the following and see what happens when a syntax error occurs.  The '\n' in the printf will let you see the segmentation.  

void csoundMessageHandler(CSOUND *csound, int attr, const
char   *format, va_list valist) {
    char messageData[256];
     vsprintf(messageData, format, valist);
     va_end(valist);

    printf("messageData: %s\n", messageData);
}


Anyway, I wrote a buffering function to solve the problem ... I'm not proud of it - it could have been written in a more elegant manner - but just to give you an idea of how difficult it was to make the syntax error messages readable on the other end of my application.  So far, it seems to get the job done.


void csoundMessageHandler(CSOUND *csound, int attr, const char *format, va_list valist) {
    CsoundInstance *instance;
    OSC_Message *oscMessage;
    char messageData[256];

    vsprintf(messageData, format, valist);
    va_end(valist);

    instance = (CsoundInstance*)csoundGetHostData(csound);

    oscMessage = OSC_Message_init();
    OSC_Message_setPath(oscMessage, "/csound");

    if( strchr( messageData, '\n' ) ) {        
        // see if we have anything in our buffer...
        if( instance->messageBufferIndex > 0 ) {
            // just go ahead and output what's there - flush it

            // term string
            instance->messageBuffer[ instance->messageBufferIndex ] = '\n'; 
            instance->messageBuffer[ instance->messageBufferIndex+1 ] = '\0'; 

        

            OSC_Message_addStringArgument(oscMessage, instance->messageBuffer);
            TCP_Client_List_sendMessage(instance->clientList, oscMessage);

            

            OSC_Message_reset(oscMessage);            
        }

        

        OSC_Message_addStringArgument(oscMessage, messageData);
        TCP_Client_List_sendMessage(instance->clientList, oscMessage);

        

        instance->messageBufferIndex = 0;
    } else {
        char *dest, *source;
        int remainingCharsToCopy;
        int msgDataLength;

        msgDataLength = strlen(messageData);

                

        remainingCharsToCopy = msgDataLength;
        source = messageData;

        while( remainingCharsToCopy > 0 ) {
            int charsLeft = MESSAGE_BUFFER_SIZE - instance->messageBufferIndex;
            dest = instance->messageBuffer + instance->messageBufferIndex;

            

            if( charsLeft >= remainingCharsToCopy ) {
                // we have enough room to copy the entire msg data
                strncpy( dest, source, remainingCharsToCopy );

                

                instance->messageBufferIndex += remainingCharsToCopy;
                remainingCharsToCopy = 0;
            } else {
                // we do not have enough room, so fit what we can
                strncpy( dest, source, charsLeft );                

                

                instance->messageBuffer[ MESSAGE_BUFFER_SIZE ] = '\0'; // term string

                

                // update counts and pointers
                source += charsLeft;
                instance->messageBufferIndex = 0;
                remainingCharsToCopy -= charsLeft;

                

                // and output it
                OSC_Message_reset(oscMessage);
                OSC_Message_addStringArgument(oscMessage, instance->messageBuffer);

                

                TCP_Client_List_sendMessage(instance->clientList, oscMessage);
            }
        }        
    }

    OSC_Message_destroy(oscMessage);
}


BEFORE THE BUFFER FUNCTION
Csound:  PortAudio real-time audio module for Csound
Csound:  0dBFS level = 32768.0
Csound:  Csound version 5.05 (float samples) Mar 17 2007
Csound:  libsndfile-1.0.17
Csound:  orchname:  _ControlsFromCsound_orcref.orc
Csound:  scorename: _ControlsFromCsound_scoref.sco
Csound:  rtaudio: PortAudio module enabled ...  Csound:  using callback interface
Csound:  rtmidi: PortMIDI module enabled
Csound:  orch compiler:
Csound:  22 lines read
Csound:         Csound:  instr  Csound:  1      Csound: 
Csound:  error:   Csound:  input arg 'giSiner' used before defined Csound:  , line 13:
Csound:  a Csound:  O Csound:  s Csound:  c Csound:     Csound:  o Csound:  s Csound:  c Csound:  i Csound:  l Csound:        Csound:  i Csound:  A Csound:  m Csound:  p Csound:  e Csound:  , Csound:    Csound:  c Csound:  p Csound:  s Csound:  p Csound:  c Csound:  h Csound:  ( Csound:  i Csound:  P Csound:  i Csound:  t Csound:  c Csound:  h Csound:  ) Csound:  , Csound:    Csound:  g Csound:  i Csound:  S Csound:  i Csound:  n Csound:  e Csound:  r Csound: 
Csound:  error:   Csound:  input arg 'iAmpe' used before defined Csound:  , line 13:
Csound:  a Csound:  O Csound:  s Csound:  c Csound:     Csound:  o Csound:  s Csound:  c Csound:  i Csound:  l Csound:        Csound:  i Csound:  A Csound:  m Csound:  p Csound:  e Csound:  , Csound:    Csound:  c Csound:  p Csound:  s Csound:  p Csound:  c Csound:  h Csound:  ( Csound:  i Csound:  P Csound:  i Csound:  t Csound:  c Csound:  h Csound:  ) Csound:  , Csound:    Csound:  g Csound:  i Csound:  S Csound:  i Csound:  n Csound:  e Csound:  r Csound: 
Csound:  error:   Csound:  input arg 'aBlah' used before defined Csound:  , line 21:
Csound:    Csound:    Csound:    Csound:    Csound:    Csound:    Csound:    Csound:    Csound:  o Csound:  u Csound:  t Csound:  s Csound:   Csound:  a Csound:  B Csound:  l Csound:  a Csound:  h Csound:  , Csound:    Csound:  a Csound:  O Csound:  s Csound:  c Csound: 
Csound:  3 syntax errors in orchestra.  compilation invalid Csound: 
Server Error:  4 /initialize - failed to compile


AFTER THE BUFFER FUNCTION
Csound:  PortAudio real-time audio module for Csound
Csound:  0dBFS level = 32768.0
Csound:  Csound version 5.05 (float samples) Mar 17 2007
Csound:  libsndfile-1.0.17
Csound:  orchname:  _ControlsFromCsound_orcref.orc
Csound:  scorename: _ControlsFromCsound_scoref.sco
Csound:  rtaudio: PortAudio module enabled ...
Csound:  rtmidi: PortMIDI module enabled
Csound:  orch compiler:
Csound:  22 lines read
Csound:         instr   1
Csound:  error:  input arg 'giSiner' used before defined
Csound:  aOsc   oscil   iAmpe, cpspch(iPitch), giSiner
Csound:  error:  input arg 'iAmpe' used before defined
Csound:  aOsc   oscil   iAmpe, cpspch(iPitch), giSiner
Csound:  error:  input arg 'aBlah' used before defined
Csound:          outs   aBlah, aOsc
Csound:  3 syntax errors in orchestra.  compilation invalid
Server Error:  4 /initialize - failed to compile



greg


On Aug 1, 2007, at 9:08 AM, Victor Lazzarini wrote:

I never noticed that kind of behaviour on syntax
errors. It always worked fine just to build a string
with vsnprintf() and then send it on its way. Other
hosts do the same (eg. Rory's Lettuce) and I have
never heard any complaint.

Victor


Well - I should have known.  I found the culprit.  Its
calling the   callback for every character .. only doing
this for syntax errors   though - so special code must be
written to handle this case .. of   course the message
handler doesn't know what it is going to receive   so ..
special code must always be used.  It seems to me this
synterr   function should construct a string and then call
the message handler   once.


void synterr(CSOUND *csound, const char *s, ...)
{
     va_list args;
     char    *cp;
     int     c;

     csound->MessageS(csound, CSOUNDMSG_ERROR, Str("error:
 "));
     va_start(args, s);
     csound->MessageV(csound, CSOUNDMSG_ERROR, s, args);
     va_end(args);


     /* FIXME - Removed temporarily for debugging
      * This function may not be necessary at all in the
end if some   of this is
      * done in the parser
      */
     if (ST(linadr) != NULL && (cp =
ST(linadr)[ST(curline)]) != NULL #if
defined(ENABLE_NEW_PARSER)
         && !csound->oparms->newParser
#endif
     ) {
       csound->MessageS(csound, CSOUNDMSG_ERROR,
                                Str(", line %d:\n"),
ST(curline));
       do {
         csound->MessageS(csound, CSOUNDMSG_ERROR, "%c",
(c = *cp++));
       } while (c != '\n');
     }
     else {
       csound->MessageS(csound, CSOUNDMSG_ERROR, "\n");
     }
     csound->synterrcnt++;
}


greg

On Jul 31, 2007, at 5:22 PM, Victor Lazzarini wrote:

I'm just eliminating the '\n' characters, because
PD's post() adds them and I don't want two newlines
after every msg string. It's just a formatting issue,
you don't need to do it if you are
just using printf() or fprintf() etc.


i understand using that using vsnprintf would allow me
to >> get it to   work .. few questions though:


if i == 0 and csmess[i] == '\0'
    wouldn't  x->csmess[i - 1] = ' '  be illegal?


I haven't analyzed the stream .. but is it just that
0's >> are being   written into it and this just replaces
the >> character before it with a   space?  Why are some
strings >> formatted correctly in the first place?    Why
is any of >> this buffer manipulation necessary in the
first place? >>
greg


On Jul 31, 2007, at 2:48 PM, Victor Lazzarini wrote:

Use vsnprintf(...).

This is an example callback from csoundapi_tilde.c:

static void message_callback(CSOUND *csound,
                   int attr, const char *format
,va_list >>>      valist){ int i;
     t_csoundapi *x = (t_csoundapi *)
csoundGetHostData(csound);

     if(x->csmess != NULL)
     vsnprintf(x->csmess, MAXMESSTRING, format,
valist); >>>      for(i=0;i<MAXMESSTRING;i++)
       if(x->csmess != NULL && x->csmess[i] == '\0'){
         x->csmess[i-1]= ' ';
         break;
       }
    if(x->csmess != NULL && x->messon) post(x->csmess)
; >>>   }




I'm using the message callback because I want to pass
the >> message   elsewhere (file, network, etc..):

Here is my function:

void csoundMessageHandler(CSOUND *csound, int attr,
const >> char   *format, va_list valist) {
    char messageData[256];
     vsprintf(messageData, format, valist);
     va_end(valist);

    printf("messageData: %s\n", messageData);
}

Here is how I register it:
     csoundSetMessageCallback(csound,
csoundMessageHandler);


Here is some of the output:
messageData: rtaudio: PortAudio module enabled ...
messageData: using callback interface

messageData: rtmidi: PortMIDI module enabled

messageData: orch compiler:

messageData: 17 lines read

messageData:
messageData: instr
messageData: 1
messageData:

messageData: error:
messageData: input arg 'aOsc' used before defined
messageData: , line 15:

messageData:
messageData: o
messageData: u
messageData: t
messageData: s
messageData:
messageData: a
messageData: O
messageData: s
messageData: c
messageData: ,
messageData:
messageData: a
messageData: O
messageData: s
messageData: c
messageData:

messageData: error:
messageData: input arg 'aOsc' used before defined
messageData: , line 15:

messageData:
messageData: o
messageData: u
messageData: t
messageData: s
messageData:
messageData: a
messageData: O
messageData: s
messageData: c
messageData: ,
messageData:
messageData: a
messageData: O
messageData: s
messageData: c
messageData:

messageData: 2 syntax errors in orchestra.
compilation >>>> invalid messageData:


It only seems to happen on errors (which are the most
important   messages).   Is there a way to avoid
these >>>> newlines so it can be   readable?

thanks
greg


--
Send bugs reports to this list.
To unsubscribe, send email to

--
Send bugs reports to this list.
To unsubscribe, send email to
--
Send bugs reports to this list.
To unsubscribe, send email to


-- 
Send bugs reports to this list.
To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk