Status of PhEventRead and friends?

The docs and examples for PhEventRead, PhEventArm, PhAttach,
PhEventNext all seem to be talking about Photon 1.14 under QNX4. Are
they usable under Neutrino?

If yes, the prototype for PhEventRead is:

extern int PhEventRead(pid_t ,void *,unsigned);

which does not seem to have enough information to actually function,
and besides which, the pid_t should either be a int rcvid (apparently
always 0, so useless), or an int that is the pulse number, or better,
a void* which is the whole received message.

If no, what are the alternatives to PhEventRead? I heard a rumour
that PtAppAddInput was not implemented for user-defined pulses yet.

Thanks,
Andrew

P.S. - even if PtAppAddInput is working, I would still like to be able
to use PhEventRead, PhEventNext to “roll my own” event loop. Is this
going to be possible in future?

Previously, Wojtek Lerch wrote in qdn.public.qnxrtp.photon:

Andrew Thomas <> Andrew@cogent.ca> > wrote:
The docs and examples for PhEventRead, PhEventArm, PhAttach,
PhEventNext all seem to be talking about Photon 1.14 under QNX4. Are
they usable under Neutrino?

Even more: they are actually used by PtInit() and PtMainLoop().

I tried a little test, based loosely on the example in the PhEventRead
documentation (which also needs updating to Photon 2). The results
are odd. I create a PtWindow, and watch every event. Some events are
classified as Photon events and some are unrecognized. For example,
left-click inside the window, and you will see unrecognized events.
Am I doing something wrong here?

/* ---------------------------------- */

/* Compile with:
gcc -Wall dtest.c -o dtest -lphoton
*/

#include <stdio.h>
#include <Pt.h>

#define EVENT_SIZE sizeof( PhEvent_t ) + 1000

int main (int argc, char **argv)
{
int rcvid;
char msg[EVENT_SIZE];
PtWidget_t *w;

struct _Ph_ctrl *ctrl;

ctrl = PhAttach (NULL, NULL);
if (PhEventArm() == -1)
printf (“PhEventArm failed\n”);
PtInit (NULL);

w = PtCreateWidget (PtWindow, NULL, 0, NULL);
PtRealizeWidget (w);

while(1)
{
rcvid = MsgReceive(ctrl->channel, &msg, sizeof(msg), NULL);
printf (“Message received\n”);
switch (PhEventRead(rcvid, msg, EVENT_SIZE))
{
case Ph_EVENT_MSG:
PtEventHandler (msg);
printf (" Handled\n");
break;
case 0:
MsgReply (rcvid, 0, “unsupported”, 12);
printf (" Unknown\n");
break;
case -1:
perror (“PhEventRead failed”);
break;
}
}
return (0);
}

/* ---------------------------------- */

/* Compile with:
gcc -Wall dtest.c -o dtest -lphoton
*/

#include <stdio.h
#include <Pt.h

#define EVENT_SIZE sizeof( PhEvent_t ) + 1000

int main (int argc, char **argv)
{
int rcvid;
char msg[EVENT_SIZE];
PtWidget_t *w;

struct _Ph_ctrl *ctrl;

ctrl = PhAttach (NULL, NULL);

Also, if I insert the line:

ctrl->channel = ChannelCreate(0);

right here, then no events get delivered. Examining in the debugger
shows that the _Ph_ctrl structure has identical contents with or
without, but if I try to create my own channel, no events get
delivered. How am I supposed to supply my own channel to the
PhEventArm? I can see from the debugger that the channel is not
created (at least, not filled into ctrl) until PhEventArm is called,
so where do I supply my channel?

if (PhEventArm() == -1)
printf (“PhEventArm failed\n”);
PtInit (NULL);

w = PtCreateWidget (PtWindow, NULL, 0, NULL);
PtRealizeWidget (w);

while(1)
{
rcvid = MsgReceive(ctrl->channel, &msg, sizeof(msg), NULL);
printf (“Message received\n”);
switch (PhEventRead(rcvid, msg, EVENT_SIZE))
{
case Ph_EVENT_MSG:
PtEventHandler (msg);
printf (" Handled\n");
break;
case 0:
MsgReply (rcvid, 0, “unsupported”, 12);
printf (" Unknown\n");
break;
case -1:
perror (“PhEventRead failed”);
break;
}
}
return (0);
}

/* ---------------------------------- */

Andrew Thomas <Andrew@cogent.ca> wrote:

The docs and examples for PhEventRead, PhEventArm, PhAttach,
PhEventNext all seem to be talking about Photon 1.14 under QNX4. Are
they usable under Neutrino?

Even more: they are actually used by PtInit() and PtMainLoop().

If yes, the prototype for PhEventRead is:

extern int PhEventRead(pid_t ,void *,unsigned);

which does not seem to have enough information to actually function,
and besides which, the pid_t should either be a int rcvid (apparently
always 0, so useless), or an int that is the pulse number, or better,
a void* which is the whole received message.

Yes, it is the rcvid. I think the docs have already been corrected
internally.

And yes, the void* is the whole received message. The function simply
checks if rcvid is zero and the contents of the message match the
Photon pulse.

If no, what are the alternatives to PhEventRead? I heard a rumour
that PtAppAddInput was not implemented for user-defined pulses yet.

PtAppAddInput() in the released QNX 6 does not handle user pulse
codes. Pulses with code > 0 are ignored; in the next release, they
will invoke input procs attached to pid zero.

Pulses allocated with PtAppCreatePulse() do work. But I guess that’s
not what you meant by “user-defined pulses”, is it…

P.S. - even if PtAppAddInput is working, I would still like to be able
to use PhEventRead, PhEventNext to “roll my own” event loop. Is this
going to be possible in future?

It is possible already. Our main loop is a proof.

But keep in mind that it might be difficult to make your main loop
compatible with the widget library. Our main loop (or, more accurately,
our PtProcessEvent()) contains a significant amount of code that
supports things like workprocs, input procs, PtEnter() and PtLeave(),
and probably a few other things that I don’t remember about right now.
It would be very difficult for you to support them all in your own code
without knowing all sorts of undocumented details. What’s even worse,
some of those details will change in future versions of the Photon
library.


Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.

Andrew Thomas <Andrew@cogent.ca> wrote:
: Also, if I insert the line:

: ctrl->channel = ChannelCreate(0);

: right here, then no events get delivered. Examining in the debugger
: shows that the _Ph_ctrl structure has identical contents with or
: without, but if I try to create my own channel, no events get
: delivered. How am I supposed to supply my own channel to the
: PhEventArm? I can see from the debugger that the channel is not
: created (at least, not filled into ctrl) until PhEventArm is called,
: so where do I supply my channel?

I don’t know if this will help, but here’s how the example currently looks:

#define EVENT_SIZE sizeof( PhEvent_t ) + 1000

main( int argc, char *argv[] )
{
int rcvid, chid;
PhEvent_t *event;
struct app_msg msg;

if( initialize() == -1 )
exit( EXIT_FAILURE );

if( NULL == ( event = malloc( EVENT_SIZE ) ) )
exit( EXIT_FAILURE );
PhEventArm();
chid = PhChannelAttach( 0, -1, NULL );

while( 1 ) {
rcvid = MsgReceive( chid, &msg, sizeof( msg ), NULL );
switch( PhEventRead( rcvid, event, EVENT_SIZE ) ) {
case Ph_EVENT_MSG:
PtEventHandler( event );
break;
case 0:
process_app_msg( &msg );
break;
case -1:
perror( “PhEventRead failed” );
break;
}
}
}


Steve Reid stever@qnx.com
TechPubs (Technical Publications)
QNX Software Systems

Previously, Wojtek Lerch wrote in qdn.public.qnxrtp.photon:

Andrew Thomas <> Andrew@cogent.ca> > wrote:
/* Compile with:
gcc -Wall dtest.c -o dtest -lphoton

Are you really using -lphoton? That’s the Photon 1.14 library. Use -lph
for the Photon 2 library.

Eep. Yes, I really am. I changed to -lph and a different bug went
away (see other thread about scrollbar). The unrecognized messages
are still occurring (see below).

If you want to create your own channel, give it to PhChannelAttach()
before calling PhEventArm().

Thanks. This works perfectly. I guess I just needed to know that the
function existed.

switch (PhEventRead(rcvid, msg, EVENT_SIZE))
{
case Ph_EVENT_MSG:

case 0:

case -1:

You don’t seem to handle Ph_RESIZE_MSG here – perhaps your buffer is
too small?

I added:

case Ph_RESIZE_MSG:
MsgReply (rcvid, 0, “unsupported”, 12);
printf (" Need resize\n");

It never gets exercised, so that’s not it. There seem to be
unrecognizable messages in the system. There is one that always
occurs with a button-up after left-clicking in the window. Did you
try running my example?

Regards,
Andrew

Previously, Steve Reid wrote in qdn.public.qnxrtp.photon:

I don’t know if this will help, but here’s how the example currently
looks:

I think this example is incomplete:

#define EVENT_SIZE sizeof( PhEvent_t ) + 1000

main( int argc, char *argv[] )
{
int rcvid, chid;
PhEvent_t *event;
struct app_msg msg;

if( initialize() == -1 )
exit( EXIT_FAILURE );

if( NULL == ( event = malloc( EVENT_SIZE ) ) )
exit( EXIT_FAILURE );

You need to call at least PhAttach(NULL, NULL) before the PhEventArm().

PhEventArm();
chid = PhChannelAttach( 0, -1, NULL );

The order of these is very important. In your example, the PhEventArm
comes before the PhChannelAttach because the call to PhChannelAttach
is really just querying the channel that PhEventArm created.

In my case, I have to call:

PhChannelAttach (mychid, mycoid, NULL);
PhEventArm();

in that order, because I want PhEventArm to use the channel that I
passed to PhChannelAttach. Obviously the example cannot do both, but
the docs don’t appear to contain this interesting relationship.

while( 1 ) {
rcvid = MsgReceive( chid, &msg, sizeof( msg ), NULL );
switch( PhEventRead( rcvid, event, EVENT_SIZE ) ) {
case Ph_EVENT_MSG:
PtEventHandler( event );
break;

Wojtek pointed out that there is a case missing for

case Ph_RESIZE_MSG:
msg = realloc (msg, PhGetMsgSize(msg));
break;

Which means that in your example, you must change the declaration of
msg from

struct app_msg msg;

to:
struct app_msg msg;
and add:
msg = (struct app_msg
) malloc (sizeof (struct app_msg));

case 0:
process_app_msg( &msg );
break;
case -1:
perror( “PhEventRead failed” );
break;
}
}
}

As a general note about examples, it would be really nice if they were
to compile as presented, if possible. The calls to initialize() and
to process_app_msg() are just fluff whose sole apparent purpose is to
act as comments. Replace them with comments, and add the one
#include <Ph.h> at the top, and this would compile and run. It would
let you at least figure out whether your example was sane, and provide
some means of regression testing as the API is modified.

Regards,
Andrew

Andrew Thomas <Andrew@cogent.ca> wrote:

/* Compile with:
gcc -Wall dtest.c -o dtest -lphoton

Are you really using -lphoton? That’s the Photon 1.14 library. Use -lph
for the Photon 2 library.

struct _Ph_ctrl *ctrl;

ctrl = PhAttach (NULL, NULL);

Also, if I insert the line:

ctrl->channel = ChannelCreate(0);

Don’t do that – it just confuses the library. PhEventArm() will create
a channel if you don’t have one already.

right here, then no events get delivered. Examining in the debugger
shows that the _Ph_ctrl structure has identical contents with or
without, but if I try to create my own channel, no events get
delivered. How am I supposed to supply my own channel to the
PhEventArm? I can see from the debugger that the channel is not
created (at least, not filled into ctrl) until PhEventArm is called,
so where do I supply my channel?

If you want to create your own channel, give it to PhChannelAttach()
before calling PhEventArm().

switch (PhEventRead(rcvid, msg, EVENT_SIZE))
{
case Ph_EVENT_MSG:

case 0:

case -1:

You don’t seem to handle Ph_RESIZE_MSG here – perhaps your buffer is
too small?

case Ph_RESIZE_MSG :
msg = realloc( msg, PhGetMsgSize(msg) );


Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.

Andrew Thomas <Andrew@cogent.ca> wrote:

Previously, Steve Reid wrote in qdn.public.qnxrtp.photon:

Wojtek pointed out that there is a case missing for

case Ph_RESIZE_MSG:
msg = realloc (msg, PhGetMsgSize(msg));
break;

Which means that in your example, you must change the declaration of
msg from

struct app_msg msg;

to:
struct app_msg msg;
and add:
msg = (struct app_msg
) malloc (sizeof (struct app_msg));

Actually, you need to remember the current size of your buffer and pass
it to both MsgReceive() and PhEventRead().

\

Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.

Andrew Thomas <Andrew@cogent.ca> wrote:

It never gets exercised, so that’s not it. There seem to be
unrecognizable messages in the system. There is one that always
occurs with a button-up after left-clicking in the window. Did you
try running my example?

I have now. :slight_smile:

Yes, I am also getting those “Unknown” messages. They seem to be extra
Photon pulses – for some reason, Photon sends you more pulses than
events. Sometimes this can be normal (e.g. when you just have wiped out
your event queue by destroying a window), but I didn’t expect it to
happen when you just click on the window.

Unfortunately, PhEventRead() doesn’t distinguish between that and a
truly unrecognized message. Our PtProcessEvent() knows how to recognize
the Photon pulse after PhEventRead() returns zero – I think the
cleanest way for you to be able to recognize it is by defining your own
pulse and giving it to the third arg of PhChannelAttach().


Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.

Yes, I am also getting those “Unknown” messages. They seem to be extra
Photon pulses – for some reason, Photon sends you more pulses than
events. Sometimes this can be normal (e.g. when you just have wiped out
your event queue by destroying a window), but I didn’t expect it to
happen when you just click on the window.

Unfortunately, PhEventRead() doesn’t distinguish between that and a
truly unrecognized message. Our PtProcessEvent() knows how to recognize
the Photon pulse after PhEventRead() returns zero – I think the
cleanest way for you to be able to recognize it is by defining your own
pulse and giving it to the third arg of PhChannelAttach().

Isn’t this mildly evil? PhEventRead is supposed to distinguish Photon
events from non-Photon events. This spurious pulse is clearly a
Photon event, so PhEventRead isn’t doing its job. As a work-around I
can attach my own pulse with PhChannelAttach, but the better solution
is for PhEventRead to correctly categorize the event as a Photon
event, and then let PhProcessEvent just drop it if it doesn’t need to
do anything.

I think we should be calling this a bug in PhEventRead.

Cheers,
Andrew

Previously, Wojtek Lerch wrote in qdn.public.qnxrtp.photon:

Isn’t this mildly evil? PhEventRead is supposed to distinguish Photon
events from non-Photon events. This spurious pulse is clearly a
Photon event, so PhEventRead isn’t doing its job. As a work-around I
can attach my own pulse with PhChannelAttach, but the better solution
is for PhEventRead to correctly categorize the event as a Photon
event, and then let PhProcessEvent just drop it if it doesn’t need to
do anything.

No, the spurious pulse is not what we call a “Photon event”. In Photon
terminology, a “Photon event” is a particular kind of message. The
spurious pulse is not that kind of message.

The pulse is just a notification telling you that there’s a Photon event
that you can receive; the reason we call the pulse spurious is because
there was no Photon event to receive.

Ok, let’s get this straight. The purpose of PhEventRead is to do the
following:

  1. classify a message as being either Photon or non-Photon
  2. read the event from the Photon server if necessary
  3. (possibly) format the result so that PhProcessEvent can deal with
    it.

Now, sometimes the Photon server generates a message to the
application, and PhEventRead says it is not a Photon event. From a
user’s perspective, this is mis-classification. Photon generated it,
but PhEventRead says it did not. If this is the intended behaviour,
then I suggest that you change the functional specification of
PhEventRead to:

  1. classify some messages from Photon as Photon events,
    mis-classifying some of them according to an undocumented,
    non-random set of internal rules that may change at any time.

  2. and 3) remain the same.

You would have to change the documentation to match.

If this is what was really intended from PhEventRead, then I suggest
that you hunt down the author of PhEventRead, slap him upside the head
with a handful of wet spaghetti, and enroll him in Comp. Sci. 101.

This is a bug.

Regards,
Andrew

Andrew Thomas <Andrew@cogent.ca> wrote:

Yes, I am also getting those “Unknown” messages. They seem to be extra
Photon pulses – for some reason, Photon sends you more pulses than
events. Sometimes this can be normal (e.g. when you just have wiped out
your event queue by destroying a window), but I didn’t expect it to
happen when you just click on the window.

Unfortunately, PhEventRead() doesn’t distinguish between that and a
truly unrecognized message. Our PtProcessEvent() knows how to recognize
the Photon pulse after PhEventRead() returns zero – I think the
cleanest way for you to be able to recognize it is by defining your own
pulse and giving it to the third arg of PhChannelAttach().

Isn’t this mildly evil? PhEventRead is supposed to distinguish Photon
events from non-Photon events. This spurious pulse is clearly a
Photon event, so PhEventRead isn’t doing its job. As a work-around I
can attach my own pulse with PhChannelAttach, but the better solution
is for PhEventRead to correctly categorize the event as a Photon
event, and then let PhProcessEvent just drop it if it doesn’t need to
do anything.

No, the spurious pulse is not what we call a “Photon event”. In Photon
terminology, a “Photon event” is a particular kind of message. The
spurious pulse is not that kind of message.

The pulse is just a notification telling you that there’s a Photon event
that you can receive; the reason we call the pulse spurious is because
there was no Photon event to receive.


\

Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.

Andrew Thomas <Andrew@cogent.ca> wrote:

The pulse is just a notification telling you that there’s a Photon event
that you can receive; the reason we call the pulse spurious is because
there was no Photon event to receive.

Actually, the docs specifically say that PhEventRead() should fail with
ENOMSG if the message was a spurious Photon pulse:

Photon may close a region (for example, via the window manager)
before you read the pending event. As a result, PhEventRead() may
indicate that no event is pending even though you were notified
otherwise. In this case, PhEventRead() returns -1 and sets errno to
ENOMSG.

Returning zero is indeed a bug. It was probably introduced while
porting Photon to Neutrino.

I’ll add it to the bug list. :slight_smile:


Wojtek Lerch (wojtek@qnx.com) QNX Software Systems Ltd.