Actually I thought of a more general event loop scheme.
There's a event queue (may unified with the thread queue, maybe not), 
The ADC code pushes "raw" button events, e.g., BUTTON_PLAY or BUTTON_NONE;

Every plugin/menu/gui thing has a get_event() - handle_event() loop, where
usually you'd call handle_default_event(). 
This function will keep track of special things (e.g, button repeat, button
combos or double-clicks) and will push the ACTION_MENU or ACTION_CANCEL
events into the queue, where translation is controlled by similar structs
with a usually accepted default.

R.

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Jonathan Gordon
Sent: Monday, July 24, 2006 2:40 PM
To: Rockbox development
Subject: Re: half-idea for #ifdef and key deifnition hell...

Hey all,
OK, well I've had a bit more of a play with implementing this idea and I
want to show you what it looks like now before I have it finished and you
all decide its not workable.

ok, so here is what goes in the existing button.h file (although that file
will get rediculously long so maybe split this up...?)

/****** new action handling code below *****/ enum {
    ACTION_UNUSED = -1, /* use this for the return of _PRE's */
    ACTION_NONE = 0,
    /* directions */
    ACTION_UP,
    ACTION_DOWN,
    ACTION_LEFT,
    ACTION_RIGHT,
    ACTION_PGUP,
    ACTION_PGDOWN,
    ACTION_PGLEFT,
    ACTION_PGRIGHT,
    /* actions */
    ACTION_ACCEPT,
    ACTION_SELECT,
    ACTION_MENU,
    ACTION_BACK,
    ACTION_CONTEXT,
    ACTION_EXIT,
    /* special stuff */

    ACTION_KEYCOUNT,
#if (BUTTON_REMOTE != 0 )
     /* directions */
    ACTION_RC_UP,
    ACTION_RC_DOWN,
    ACTION_RC_LEFT,
    ACTION_RC_RIGHT,
    ACTION_RC_PGUP,
    ACTION_RC_PGDOWN,
    ACTION_RC_PGLEFT,
    ACTION_RC_PGRIGHT,
    /* actions */
    ACTION_RC_ACCEPT,
    ACTION_RC_SELECT,
    ACTION_RC_MENU,
    ACTION_RC_BACK,
    ACTION_RC_CONTEXT,
    ACTION_RC_EXIT,
    /* special stuff */

    ACTION_RC_KEYCOUNT = ACTION_RC_EXIT+1-ACTION_KEYCOUNT, #endif

};

struct ButtonItem {
    int button_code;
    int ret_code;
    int pre_button_relative_index;
} ;
static struct ButtonItem DefaultButtons[] {
    /* Each target goes under here, each ACTION must be configured! */
    /* REMEMBER To put REPEATS for logical actions */ #if (CONFIG_KEYPAD ==
IRIVER_H100_PAD)\
    || (CONFIG_KEYPAD == IRIVER_H300_PAD)

    /* directions */
    { BUTTON_UP, ACTION_UP, 0},
    { BUTTON_UP|BUTTON_REPEAT, ACTION_UP, 0},
    { BUTTON_DOWN, ACTION_DOWN, 0},
    { BUTTON_DOWN|BUTTON_REPEAT, ACTION_DOWN, 0},
    { BUTTON_LEFT, ACTION_LEFT, 0},
    { BUTTON_LEFT|BUTTON_REPEAT, ACTION_LEFT, 0},
    { BUTTON_RIGHT, ACTION_RIGHT, 0},
    { BUTTON_RIGHT|BUTTON_REPEAT, ACTION_RIGHT, 0},

    { BUTTON_ON, ACTION_UNUSED, 0},
    { BUTTON_UP|BUTTON_ON, ACTION_PGUP, 1},
    { BUTTON_UP|BUTTON_ON|BUTTON_REPEAT, ACTION_PGUP, 2},
    { BUTTON_DOWN|BUTTON_ON, ACTION_PGDOWN,3},
    { BUTTON_DOWN|BUTTON_ON|BUTTON_REPEAT, ACTION_PGDOWN, 4},
    { BUTTON_LEFT|BUTTON_ON, ACTION_PGLEFT, 5},
    { BUTTON_LEFT|BUTTON_ON|BUTTON_REPEAT, ACTION_PGLEFT, 6},
    { BUTTON_RIGHT|BUTTON_ON, ACTION_PGRIGHT, 7},
    { BUTTON_RIGHT|BUTTON_ON|BUTTON_REPEAT, ACTION_PGRIGHT, 8},
    /* actions */
    { BUTTON_ON, ACTION_UNUSED, 0},
    { BUTTON_ON|BUTTON_REL, ACTION_ACCEPT, 1},
    { BUTTON_SELECT, ACTION_UNUSED, 0 }, /* SELECT and CONTEXT _PRE */
    { BUTTON_SELECT|BUTTON_REL, ACTION_SELECT, 1 },
    { BUTTON_MODE, ACTION_MENU, 0 },
    { BUTTON_STOP, ACTION_BACK, 0 },
    { BUTTON_SELECT|BUTTON_REPEAT, ACTION_CONTEXT, 4 },
    { BUTTON_OFF, ACTION_EXIT, 0 },
    /* special stuff */

    /* Remote Control Buttons */

#else if 0
    /* new targets */
#endif /* target button defines */
};


***********************

Ok, The enum at the top is hopefully a list of all actions that can be
performed in the main code. These will be defined for all targets so goodbye
#ifdef in the button loop. (Even if they are not configured with a button
combo you can still use them in the button loop without a problem).

Now the ButtonItem struct.
Button_code is the button combo for this item.
ret_val is the ACTION_* enum to return if this combo is pressed lastly the
pre_button_relative_index is the relative index of the button that used to
act like the _pre, this button will only return the ret_code if that other
button was the last combo pressed.

Lastly, the DefaultButtons array stores the standard codes for all targets
(only iriver has been done so far).
Some points for the values there:
each ACTION_* should have a combo assigned to it, but nothing will go wrong
if it doesnt.
some of the actions have the same ACTION_* value to make handling repeat
presses simple.
{ BUTTON_ON, ACTION_UNUSED, 0}, is used twice for the _pre combo, this isnt
a problem and is only used to make finding the pre_index easier...
hopefully you can see how much simpler that _pre combo checking is compared
to the current system.

So, then the button loop would look something like switch (get_action()) {
    case ACTION_UP:
....
}

Some problems tho.
I dont have an ipod so I dont know if this system can work for it,
apparently thats where we will have the most difficulty? I reckon it will be
fine, but ti really needs someone who owns an ipod and has some time to see
if they can fill in the DefaultButton struct for it.
The other thing is the funny stuff like double click, short-long presses and
tripple presses etc. my feelings on them is that they are done so
infrequently that they should be done by the caller and not the main button
checking code.
Also, The default keys are gonna run us into trouble eventually (probably in
plugins), so there will be another button function which accepts an array of
ButtonItems which will be checked before the DefaultButtons.

comments?

Reply via email to