How to determine if the button is pressed or not in L4 Dope?

Norman Feske nf2 at inf.tu-dresden.de
Thu Jun 26 12:46:50 CEST 2008


Hi Lynette,

> Thanks for your advice. I already read dope-users-guide.txt and vscrtest.c
> and use button event. The application uses ffmpeg to watch video in L4 dope.
> 
> 
> Right now, I am writing the pause function but there is a button problem
> occurred. The sequence is that user presses play button and a new window pop
> out with video and two buttons (pause, exit) in it. When the video is shown,
> the pause or exit button event doesn't work until the video finished.
> Because I use while loop to read the video frame after set up the window,
> the button event have to wait for the while loop finished.
> 
> I have tried using thread to synchronize the event but I failed. Now, I try
> to find out the way to  determine if the button is pressed or not and put
> the if conditional within while loop. Or maybe I was wrong. Does anyone know
> how to solve it? Thanks.

Thank you for this more detailed description. Now I see the problem.
Generally, as you guessed right, you can request the state of a button
by using the 'dope_req' function. For example, to request the state of
your pause button, you may do the following:

  char buf[8];
  dope_req(app_id, buf, sizeof(buf), "pause.state");

The result is either the ascii string "0" (button not pressed) or "1"
(button is pressed). However, as you have noticed, DOpE never returns
the "1". The reason is that DOpE only lets the user press a button
after the application associated an event handler for the button via
the 'dope_bind' function. So the button is not press-able (the button
does not change its visual state when you click on it anyway). So we
have to tell DOpE somehow that we want the button to be press-able.
To achive this, you can just call the bind-method of the button widget
and leave the bind-argument string empty:

  dope_cmd(app_id, "pause.bind(\"commit\", \"\")");

BTW, this mechanism is also internally used by 'dope_bind',
which specifies the information about the callback function
as bind argument.

Now we have signaled interest in commit events for the pause button
and DOpE will give the proper visual feedback on mouse clicks
and it will return a "1" when you request the "state" attribute.

As a reference, I have used the following code for testing:

In the main function:

  dope_cmd(app_id, "pause = new Button(-text Pause)");
  dope_cmd(app_id, "mg.place(pause, -column 1 -row 101)");
  dope_cmd(app_id, "pause.bind(\"commit\", \"\")");

  dope_cmd(app_id, "spin = new Button(-text Spin)");
  dope_cmd(app_id, "mg.place(spin, -column 1 -row 100)");
  dope_bind(app_id, "spin", "commit", spin_callback, (void *)0);

The callback function for the spin button:

  static void spin_callback(dope_event *e, void *arg) {
    char buf[8];
    while (1) {
      dope_req(app_id, buf, sizeof(buf), "pause.state");
      printf("%s\n", buf);
    }
  }

You mentioned that you already tried using a separate worker
thread for decoding the video. I think this solution would
be more elegant than performing long-taking computations
from within an event callback function. Generally, a callback
function should only trigger a state change of the application
and immediately return. It should never perform long-taking
operations or even implement a custom event loop ;-)
For the clarity of your application, it may be worthwhile for
you to try again your worker-thread idea.

Best regards
Norman




More information about the l4-hackers mailing list