Index: apps/menu.c =================================================================== --- apps/menu.c (revision 14809) +++ apps/menu.c (working copy) @@ -263,6 +263,45 @@ } } } + +#ifdef GATHER_CALL_STATS +static void reorder_menu_items_by_freq(const struct menu_item_ex *menu) +{ + int type; + const struct menu_item_ex **items; + const struct menu_item_ex *tmp; + int item_count; + int i, j, max, max_index; + + /* Is this a reordable menu? */ + type = menu->flags & MENU_TYPE_MASK; + /* TODO: sort other menu as well (e.g. items within sound settings) */ + if (type != MT_MENU) + { + return; + } + + items = menu->submenus; + item_count = MENU_GET_COUNT(menu->flags); + for (i=0; icall_stats->call_count; + max_index = i; + for (j=i+1; jcall_stats->call_count > max) + { + max = items[j]->call_stats->call_count; + max_index = j; + } + } + tmp = items[i]; + items[i] = items[max_index]; + items[max_index] = tmp; + } +} +#endif /* GATHER_CALL_STATS */ + #define MAX_OPTIONS 32 bool do_setting_from_menu(const struct menu_item_ex *temp) { @@ -307,6 +346,13 @@ gui_buttonbar_set(&buttonbar, "<<<", "", ""); gui_buttonbar_draw(&buttonbar); #endif + +#ifdef GATHER_CALL_STATS + DEBUGF("Drawing menu of type %d\n", menu->flags&MENU_TYPE_MASK); + /* Reorder menu items (most frequently selected go to the top) */ + reorder_menu_items_by_freq(menu); +#endif + init_menu_lists(menu,&lists,selected,true); in_stringlist = ((menu->flags&MENU_TYPE_MASK) == MT_RETURN_ID); @@ -418,6 +464,12 @@ #endif selected = get_menu_selection(gui_synclist_get_sel_pos(&lists), menu); temp = menu->submenus[selected]; +#ifdef GATHER_CALL_STATS + DEBUGF("Selected item: id='%s', call_cnt=%d, type=%d\n", + temp->call_stats->item_id, temp->call_stats->call_count, + temp->flags&MENU_TYPE_MASK); + temp->call_stats->call_count++; +#endif redraw_lists = true; if (in_stringlist) type = (menu->flags&MENU_TYPE_MASK); @@ -544,4 +596,3 @@ } return ret; } - Index: apps/menu.h =================================================================== --- apps/menu.h (revision 14809) +++ apps/menu.h (working copy) @@ -25,6 +25,9 @@ #include "icons.h" #include "root_menu.h" /* needed for MENU_* return codes */ +/* Define the following if the statistics about the selected menu + items should be gathered */ +#define GATHER_CALL_STATS enum menu_item_type { MT_MENU = 0, @@ -94,6 +97,12 @@ int icon_id; } *menu_get_name_and_icon; }; +#ifdef GATHER_CALL_STATS + struct s_call_stats { + const char * const item_id; /* id of the item, should be unique across all menues */ + int call_count; /* How many times this item was selected */ + } *call_stats; +#endif }; typedef int (*menu_callback_type)(int action, @@ -124,23 +133,37 @@ - callback: The callback function to call for this menu item. */ +/*#ifdef GATHER_CALL_STATS*/ +#define STATS_STRUCT(name) \ + static struct s_call_stats name##_##call_stats = \ + {#name, 0}; +#define ITEMS_STATS(name) , &name##_##call_stats +/* +#elif +#define STATS_STRUCT(name) +#define ITEMS_STATS(name) +#endif +*/ + /* Use this to put a setting into a menu. The setting must appear in settings_list.c. If the setting is not configured properly, the menu will display "Not Done yet!" When the user selects this item the setting select screen will load, when that screen exits the user wll be back in the menu */ #define MENUITEM_SETTING(name,var,callback) \ + STATS_STRUCT(name) \ static const struct menu_item_ex name = \ - {MT_SETTING, {.variable = (void*)var},{callback}}; + {MT_SETTING, {.variable = (void*)var},{callback} ITEMS_STATS(name)}; /* Use this for settings which have a differnt title in their setting screen than in the menu (e.g scroll options */ #define MENUITEM_SETTING_W_TEXT(name, var, str, callback ) \ static const struct menu_callback_with_desc name##__ = \ {callback,str, Icon_NOICON}; \ + STATS_STRUCT(name) \ static const struct menu_item_ex name = \ {MT_SETTING_W_TEXT|MENU_HAS_DESC, {.variable = (void*)var }, \ - {.callback_and_desc = & name##__}}; + {.callback_and_desc = & name##__} ITEMS_STATS(name)}; /* Use this To create a list of Strings (or ID2P()'s ) When the user enters this list and selects one, the menu will exit @@ -150,27 +173,31 @@ static const char *name##_[] = {__VA_ARGS__}; \ static const struct menu_callback_with_desc name##__ = \ {callback,str, Icon_NOICON}; \ + STATS_STRUCT(name) \ static const struct menu_item_ex name = \ {MT_RETURN_ID|MENU_HAS_DESC| \ MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \ - { .strings = name##_},{.callback_and_desc = & name##__}}; + { .strings = name##_},{.callback_and_desc = & name##__} \ + ITEMS_STATS(name)}; /* causes do_menu() to return a value associated with the item */ -#define MENUITEM_RETURNVALUE(name, str, val, cb, icon) \ - static const struct menu_callback_with_desc name##_ = {cb,str,icon}; \ - static const struct menu_item_ex name = \ - { MT_RETURN_VALUE|MENU_HAS_DESC, { .value = val}, \ - {.callback_and_desc = & name##_}}; +#define MENUITEM_RETURNVALUE(name, str, val, cb, icon) \ + static const struct menu_callback_with_desc name##_ = {cb,str,icon}; \ + STATS_STRUCT(name) \ + static const struct menu_item_ex name = \ + { MT_RETURN_VALUE|MENU_HAS_DESC, { .value = val}, \ + {.callback_and_desc = & name##_} ITEMS_STATS(name)}; /* same as above, except the item name is dynamic */ #define MENUITEM_RETURNVALUE_DYNTEXT(name, val, cb, text_callback, \ text_cb_data, icon) \ - static const struct menu_get_name_and_icon name##_ \ + static const struct menu_get_name_and_icon name##_ \ = {cb,text_callback,text_cb_data,icon}; \ - static const struct menu_item_ex name = \ + STATS_STRUCT(name) \ + static const struct menu_item_ex name = \ { MT_RETURN_VALUE|MENU_DYNAMIC_DESC, { .value = val}, \ - {.menu_get_name_and_icon = & name##_}}; + {.menu_get_name_and_icon = & name##_} ITEMS_STATS(name)}; /* Use this to put a function call into the menu. When the user selects this item the function will be run, @@ -182,9 +209,11 @@ static const struct menu_callback_with_desc name##_ = {callback,str,icon}; \ static const struct menu_func name##__ = {{(void*)func}, param}; \ /* should be const, but recording_settings wont let us do that */ \ + STATS_STRUCT(name) \ const struct menu_item_ex name = \ { MT_FUNCTION_CALL|MENU_HAS_DESC|flags, \ - { .function = & name##__}, {.callback_and_desc = & name##_}}; + { .function = & name##__}, {.callback_and_desc = & name##_} \ + ITEMS_STATS(name)}; /* As above, except the text is dynamic */ #define MENUITEM_FUNCTION_DYNTEXT(name, flags, func, param, \ @@ -192,9 +221,11 @@ static const struct menu_get_name_and_icon name##_ \ = {callback,text_callback,text_cb_data,icon}; \ static const struct menu_func name##__ = {{(void*)func}, param}; \ + STATS_STRUCT(name) \ static const struct menu_item_ex name = \ { MT_FUNCTION_CALL|MENU_DYNAMIC_DESC|flags, \ - { .function = & name##__}, {.menu_get_name_and_icon = & name##_}}; + { .function = & name##__}, {.menu_get_name_and_icon = & name##_} \ + ITEMS_STATS(name)}; /* Use this to actually create a menu. the ... argument is a list of pointers to any of the above macro'd variables. @@ -202,10 +233,12 @@ #define MAKE_MENU( name, str, callback, icon, ... ) \ static const struct menu_item_ex *name##_[] = {__VA_ARGS__}; \ static const struct menu_callback_with_desc name##__ = {callback,str,icon};\ + STATS_STRUCT(name) \ const struct menu_item_ex name = \ {MT_MENU|MENU_HAS_DESC| \ MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \ - { (void*)name##_},{.callback_and_desc = & name##__}}; + { .submenus = name##_},{.callback_and_desc = & name##__} \ + ITEMS_STATS(name)}; #endif /* End __MENU_H__ */ Index: apps/onplay.c =================================================================== --- apps/onplay.c (revision 14809) +++ apps/onplay.c (working copy) @@ -81,10 +81,12 @@ #define MAKE_ONPLAYMENU( name, str, callback, icon, ... ) \ static const struct menu_item_ex *name##_[] = {__VA_ARGS__}; \ static const struct menu_callback_with_desc name##__ = {callback,str,icon};\ + STATS_STRUCT(name) \ static const struct menu_item_ex name = \ {MT_MENU|MENU_HAS_DESC|MENU_EXITAFTERTHISMENU| \ MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \ - { (void*)name##_},{.callback_and_desc = & name##__}}; + { (void*)name##_},{.callback_and_desc = & name##__} \ + ITEMS_STATS(name)}; /* ----------------------------------------------------------------------- */