Index: apps/SOURCES =================================================================== RCS file: /cvsroot/rockbox/apps/SOURCES,v retrieving revision 1.44 diff -u -b -r1.44 SOURCES --- apps/SOURCES 26 Mar 2006 11:33:41 -0000 1.44 +++ apps/SOURCES 24 Jun 2006 15:11:21 -0000 @@ -81,3 +81,6 @@ #endif metadata.c tagcache.c +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +ipod_scroll_wheel_gui.c +#endif Index: apps/ipod_scroll_wheel_gui.c =================================================================== RCS file: apps/ipod_scroll_wheel_gui.c diff -N apps/ipod_scroll_wheel_gui.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ apps/ipod_scroll_wheel_gui.c 24 Jun 2006 15:11:21 -0000 @@ -0,0 +1,164 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) TP Diffenbach (2006) + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" + +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) + +#include "button.h" +#include "settings.h" +#include "logf.h" +#include "list.h" +#include "screen_access.h" +#include "statusbar.h" +#include "ipod_scroll_wheel_gui.h" + + struct scroll_accel_jump { + enum { NOACCEL, PAGE, PERCENT } jump_type ; + unsigned int amount ; + unsigned int lines ; +} ; + +struct scroll_accel_jump scroll_accel_jumps[] = { { NOACCEL, 0, 0 }, { PAGE, 1, 0 }, { PAGE, 8, 0 } , { PERCENT, 10, 0 } } ; + +static void calculate_jump_lines( struct scroll_accel_jump* j, unsigned int list_items, unsigned int screen_lines ) { + j->lines = j->jump_type == PERCENT + ? ( j->amount * list_items ) / 100 + : j->amount * screen_lines ; +} + +static inline unsigned int list_items( struct gui_list* list ) { + return list->nb_items ; +} + +static inline unsigned int screen_lines( struct gui_list* list ) { + return list->display->nb_lines ; +} + +static struct scroll_accel_jump* find_accel_for_list( + struct gui_list* list, struct scroll_accel_jump* jump, unsigned int raw_accel ) { + unsigned int l_items = list_items( list ) ; + unsigned int s_lines = screen_lines( list ) ; + + /* never accel in a list <= page long */ + if( raw_accel == 0 || l_items <= s_lines ) { + return jump ; + } + + /* otherwise, find the highest possible accel */ + calculate_jump_lines( jump + raw_accel, l_items, s_lines ) ; + + while( raw_accel > 1 ) { + calculate_jump_lines( jump + raw_accel - 1, l_items, s_lines ) ; + if( jump[ raw_accel ].lines > jump[ raw_accel - 1 ].lines ) break ; + --raw_accel ; + } + return jump + raw_accel ; +} + +static void display_ipod_scroll_wheel_acceration( int accel, int speed ) { + static int previous_accel = -1 ; + static int previous_speed = 0 ; + if( previous_accel != accel || previous_speed != speed ) { + gui_statusbar_draw_scroll_accel( &screens[ SCREEN_MAIN ], accel, speed ) ; + previous_accel = accel ; + previous_speed = speed ; + } +} + + +/* public functions declared in header */ +/* these next two really belong in list.c */ +void gui_synclist_select_forward_n_lines( struct gui_synclist* lists, unsigned int lines ) +{ + int i; + FOR_NB_SCREENS(i) + gui_list_select_next_page(&(lists->gui_list[i]), lines ); +} + +void gui_synclist_select_back_n_lines( struct gui_synclist* lists, unsigned int lines ) +{ + int i; + FOR_NB_SCREENS(i) + gui_list_select_previous_page(&(lists->gui_list[i]), lines); +} + + +/* this goes away in production, I think */ +static get_ipod_scroll_wheel_acceration_and_cps( int* speed ) { + int cps = get_ipod_scroll_wheel_clicks_per_second() ; + *speed = cps ; + unsigned int acps = cps < 0 ? -cps : cps ; + int a = acps < global_settings.ipod_scroll_wheel_acceleration_fast + ? 0 + : ( acps < global_settings.ipod_scroll_wheel_acceleration_faster + ? 1 + : ( acps < global_settings.ipod_scroll_wheel_acceleration_fastest + ? 2 + : 3 ) ) ; +#ifdef ROCKBOX_HAS_LOGF + logf( "g:%d,%d", cps, a ) ; +#endif + return a ; +} + + +/* dispatch the correct synclist function depending on scroll acceleration factor */ +void gui_synclist_handle_accel( struct gui_synclist * lists, enum screen_type screen, enum list_dir dir) +{ + int cps ; + struct scroll_accel_jump* jump = find_accel_for_list( + &(lists->gui_list[ screen ] ), scroll_accel_jumps, get_ipod_scroll_wheel_acceration_and_cps( &cps ) ) ; + + if( jump->jump_type == NOACCEL ) { + if( dir == FORWARD ) + gui_synclist_select_next( lists ) ; + else + gui_synclist_select_previous( lists ) ; + } else { + if( dir == FORWARD ) + gui_synclist_select_forward_n_lines( lists, jump->lines ) ; + else + gui_synclist_select_back_n_lines( lists, jump->lines ) ; + } + + display_ipod_scroll_wheel_acceration( jump - scroll_accel_jumps, cps ) ; +} + + unsigned int get_ipod_scroll_wheel_acceration( void ) { + int cps = get_ipod_scroll_wheel_clicks_per_second() ; + + unsigned int acps = cps < 0 ? -cps : cps ; + int a = acps < global_settings.ipod_scroll_wheel_acceleration_fast + ? 0 + : ( acps < global_settings.ipod_scroll_wheel_acceleration_faster + ? 1 + : ( acps < global_settings.ipod_scroll_wheel_acceleration_fastest + ? 2 + : 3 ) ) ; + + return a ; + } + +unsigned int get_and_display_ipod_scroll_wheel_acceration( void ) { + int cps ; + int a = get_ipod_scroll_wheel_acceration_and_cps( &cps ) ; + display_ipod_scroll_wheel_acceration( a, cps ) ; + return a ; +} +#endif Index: apps/ipod_scroll_wheel_gui.h =================================================================== RCS file: apps/ipod_scroll_wheel_gui.h diff -N apps/ipod_scroll_wheel_gui.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ apps/ipod_scroll_wheel_gui.h 24 Jun 2006 15:11:21 -0000 @@ -0,0 +1,43 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) TP Diffenbach (2006) + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _IPOD_SCROLL_WHEEL_GUI_H_ +#define _IPOD_SCROLL_WHEEL_GUI_H_ +#include "config.h" + +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +#include "list.h" +#include "screen_access.h" + +extern void gui_synclist_select_forward_n_lines(struct gui_synclist* lists, unsigned int lines ) ; +extern void gui_synclist_select_back_n_lines(struct gui_synclist* lists, unsigned int lines ) ; + +enum list_dir { BACKWARD, FORWARD } ; +/* dispatch the correct synclist function depending on scroll acceleration factor + * may adjust the actual accelration depending on list length + * displays adjusted acceleration to the statusbar (if the statusbar is on, clients don't need to check) +*/ +extern void gui_synclist_handle_accel( struct gui_synclist* lists, enum screen_type screen, enum list_dir dir) ; + +/* returns the accelreation */ +extern unsigned int get_ipod_scroll_wheel_acceration( void ) ; + +/* returns the accelreation and displays it to the statusbar (if the statusbar is on, clients don't need to check) */ +extern unsigned int get_and_display_ipod_scroll_wheel_acceration( void ) ; + +#endif +#endif Index: apps/settings.c =================================================================== RCS file: /cvsroot/rockbox/apps/settings.c,v retrieving revision 1.389 diff -u -b -r1.389 settings.c --- apps/settings.c 6 Jun 2006 22:23:40 -0000 1.389 +++ apps/settings.c 24 Jun 2006 15:11:22 -0000 @@ -563,6 +563,11 @@ {1, S_O(warnon_erase_dynplaylist), false, "warn when erasing dynamic playlist", off_on }, +#if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI) + {9, S_O(ipod_scroll_wheel_acceleration_fast), 55, "ipod scroll wheel fast threshold in clicks/sec", NULL }, /* 0...511 */ + {9, S_O(ipod_scroll_wheel_acceleration_faster), 110, "ipod scroll wheel faster threshold in clicks/sec", NULL }, /* 0...511 */ + {9, S_O(ipod_scroll_wheel_acceleration_fastest), 165, "ipod scroll wheel fastest threshold in clicks/sec", NULL }, /* 0...511 */ +#endif /* If values are just added to the end, no need to bump the version. */ /* new stuff to be added at the end */ Index: apps/settings.h =================================================================== RCS file: /cvsroot/rockbox/apps/settings.h,v retrieving revision 1.219 diff -u -b -r1.219 settings.h --- apps/settings.h 25 May 2006 13:34:51 -0000 1.219 +++ apps/settings.h 24 Jun 2006 15:11:23 -0000 @@ -495,6 +495,12 @@ #ifdef HAVE_LCD_BITMAP unsigned char kbd_file[MAX_FILENAME+1]; /* last keyboard */ #endif + +#if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI) + unsigned int ipod_scroll_wheel_acceleration_fast ; + unsigned int ipod_scroll_wheel_acceleration_faster ; + unsigned int ipod_scroll_wheel_acceleration_fastest ; +#endif }; enum optiontype { INT, BOOL }; Index: apps/settings_menu.c =================================================================== RCS file: /cvsroot/rockbox/apps/settings_menu.c,v retrieving revision 1.257 diff -u -b -r1.257 settings_menu.c --- apps/settings_menu.c 6 Jun 2006 22:23:41 -0000 1.257 +++ apps/settings_menu.c 24 Jun 2006 15:11:24 -0000 @@ -1950,6 +1950,7 @@ return result; } +static bool ipod_scroll_wheel_acceleration_by_speed_menu( void ) ; static bool system_settings_menu(void) { @@ -1976,6 +1977,7 @@ #ifdef CONFIG_CHARGING { ID2P(LANG_CAR_ADAPTER_MODE), car_adapter_mode }, #endif + { ID2P(LANG_IPOD_SCROLL_WHEEL_SPEED), ipod_scroll_wheel_acceleration_by_speed_menu }, }; m=menu_init( items, sizeof(items) / sizeof(*items), NULL, @@ -2006,3 +2008,46 @@ menu_exit(m); return result; } + +static bool ipod_scroll_wheel_set_acceleration_by_speed( int* var, const unsigned char* desc ) +{ + return set_int( desc, "s", UNIT_SEC, var, + NULL, 5, 1, 500, NULL ); +} + +static bool ipod_scroll_wheel_acceleration_by_speed_fast( void ) +{ + return ipod_scroll_wheel_set_acceleration_by_speed( + &global_settings.ipod_scroll_wheel_acceleration_fast, + str(LANG_IPOD_SCROLL_WHEEL_FAST) ) ; +} + +static bool ipod_scroll_wheel_acceleration_by_speed_faster( void ) +{ + return ipod_scroll_wheel_set_acceleration_by_speed( + &global_settings.ipod_scroll_wheel_acceleration_faster, + str(LANG_IPOD_SCROLL_WHEEL_FASTER) ) ; +} + +static bool ipod_scroll_wheel_acceleration_by_speed_fastest( void ) +{ + return ipod_scroll_wheel_set_acceleration_by_speed( + &global_settings.ipod_scroll_wheel_acceleration_fastest, + str(LANG_IPOD_SCROLL_WHEEL_FASTEST) ) ; +} + +static bool ipod_scroll_wheel_acceleration_by_speed_menu( void ) +{ + struct menu_item items[] = { + { ID2P(LANG_IPOD_SCROLL_WHEEL_FAST), ipod_scroll_wheel_acceleration_by_speed_fast }, + { ID2P(LANG_IPOD_SCROLL_WHEEL_FASTER), ipod_scroll_wheel_acceleration_by_speed_faster }, + { ID2P(LANG_IPOD_SCROLL_WHEEL_FASTEST), ipod_scroll_wheel_acceleration_by_speed_fastest }, + }; + + int m=menu_init( items, sizeof(items) / sizeof(*items), NULL, + NULL, NULL, NULL); + bool result = menu_run(m); + menu_exit(m); + return result; +} + Index: apps/gui/list.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/list.c,v retrieving revision 1.21 diff -u -b -r1.21 list.c --- apps/gui/list.c 4 Jun 2006 17:14:17 -0000 1.21 +++ apps/gui/list.c 24 Jun 2006 15:11:25 -0000 @@ -30,6 +30,11 @@ #include "scrollbar.h" #include "statusbar.h" #include "textarea.h" +#include "logf.h" + +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +#include "ipod_scroll_wheel_gui.h" +#endif #ifdef HAVE_LCD_CHARCELLS #define SCROLL_LIMIT 1 @@ -43,7 +48,7 @@ static bool offset_out_of_view = false; #endif - +static struct gui_list* last_list_displayed = 0 ; void gui_list_init(struct gui_list * gui_list, list_get_name callback_get_item_name, @@ -62,6 +67,10 @@ #ifdef HAVE_LCD_BITMAP gui_list->offset_position = 0; #endif + gui_list->last_displayed_selected_item = -1 ; + gui_list->last_displayed_start_item = -1 ; + gui_list->old_cursor_x = -1 ; + gui_list->old_cursor_y = -1 ; } void gui_list_set_display(struct gui_list * gui_list, struct screen * display) @@ -173,12 +182,49 @@ text_pos = 1; #endif - gui_textarea_clear(display); + //gui_textarea_clear(display); #ifdef HAVE_LCD_BITMAP screen_set_xmargin(display, text_pos); #endif - for(i = 0;i < display->nb_lines;i++) + unsigned long start = USEC_TIMER ; // remove in production code + bool optimize = false ; // remove in production code + int nsi = gui_list->start_item ; + int n ; + /* tagcache is sneaky, and reuses the same gui_list for all its lists; + * this complicates our pointer check, + * and necessitates the default case on the button switch in gui_synclist_do_button + */ + if( gui_list == last_list_displayed && nsi == gui_list->last_displayed_start_item ) { + optimize = true ; // remove in production code + n = gui_list->last_displayed_selected_item - nsi ; + int m = gui_list->selected_item - nsi ; + if( m < n ) { + i = m ; + ++n ; + } else { //if( n > m ) { + i = n ; + n = m + 1 ; + } + //~ } else { + //~ return ; + //~ } + + int old_cursor_x = gui_list->old_cursor_x ; + if( old_cursor_x != -1 ) { + screen_put_cursorxy(display, old_cursor_x, gui_list->old_cursor_y, false); + } + } else { + gui_textarea_clear(display); + i = 0 ; + n = display->nb_lines ; + gui_list->last_displayed_start_item = nsi ; + last_list_displayed = gui_list ; + } + + gui_list->last_displayed_selected_item = gui_list->selected_item ; + + for( ; i < n ; ++i ) { char entry_buffer[MAX_PATH]; unsigned char *entry_name; @@ -191,6 +237,7 @@ entry_name = gui_list->callback_get_item_name(current_item, gui_list->data, entry_buffer); + #ifdef HAVE_LCD_BITMAP /* position the string at the correct offset place */ int item_offset; @@ -232,8 +279,13 @@ display->puts_scroll(text_pos, i, entry_name); #endif - if(draw_cursor) + if(draw_cursor) { screen_put_cursorxy(display, cursor_pos, i, true); + gui_list->old_cursor_x = cursor_pos ; + gui_list->old_cursor_y = i ; + } else { + gui_list->old_cursor_x = -1 ; + } } else {/* normal item */ @@ -254,6 +306,12 @@ screen_put_iconxy(display, icon_pos, i, icon); } } + +#ifdef ROCKBOX_HAS_LOGF + unsigned long end = USEC_TIMER ; // remove in production code + logf( "ld %s %d", optimize ? "o" : "n", end - start ) ; // remove in production code +#endif + #ifdef HAVE_LCD_BITMAP /* Draw the scrollbar if needed*/ if(draw_scrollbar) @@ -613,7 +671,11 @@ #ifdef LIST_RC_PREV case LIST_RC_PREV | BUTTON_REPEAT: #endif +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) + gui_synclist_handle_accel( lists, SCREEN_MAIN, BACKWARD ) ; +#else gui_synclist_select_previous(lists); +#endif gui_synclist_draw(lists); yield(); return LIST_PREV; @@ -629,7 +691,11 @@ case LIST_RC_NEXT | BUTTON_REPEAT: #endif +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) + gui_synclist_handle_accel( lists, SCREEN_MAIN, FORWARD ) ; +#else gui_synclist_select_next(lists); +#endif gui_synclist_draw(lists); yield(); return LIST_NEXT; @@ -700,6 +766,14 @@ yield(); return LIST_PREV; #endif + + case BUTTON_NONE: + return 0 ; + + default: + last_list_displayed = 0 ; + return 0 ; } + return 0; } Index: apps/gui/list.h =================================================================== RCS file: /cvsroot/rockbox/apps/gui/list.h,v retrieving revision 1.19 diff -u -b -r1.19 list.h --- apps/gui/list.h 22 Jun 2006 06:38:57 -0000 1.19 +++ apps/gui/list.h 24 Jun 2006 15:11:25 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: list.h,v 1.19 2006-06-22 06:38:57 amiconn Exp $ + * $Id: list.h,v 1.18 2006-04-03 08:51:08 bger Exp $ * * Copyright (C) 2005 by Kevin Ferrare * @@ -53,15 +53,19 @@ #define LIST_PGRIGHT (BUTTON_ON | BUTTON_RIGHT) #define LIST_PGLEFT (BUTTON_ON | BUTTON_LEFT) +#ifdef CONFIG_REMOTE_KEYPAD #define LIST_RC_NEXT BUTTON_RC_RIGHT #define LIST_RC_PREV BUTTON_RC_LEFT +#endif /* CONFIG_REMOTE_KEYPAD */ #elif CONFIG_KEYPAD == PLAYER_PAD #define LIST_NEXT BUTTON_RIGHT #define LIST_PREV BUTTON_LEFT +#ifdef CONFIG_REMOTE_KEYPAD #define LIST_RC_NEXT BUTTON_RC_RIGHT #define LIST_RC_PREV BUTTON_RC_LEFT +#endif /* CONFIG_REMOTE_KEYPAD */ #elif CONFIG_KEYPAD == ONDIO_PAD #define LIST_NEXT BUTTON_DOWN @@ -149,6 +153,10 @@ bool limit_scroll; /* The data that will be passed to the callback function YOU implement */ void * data; + int last_displayed_selected_item ; + int last_displayed_start_item ; + int old_cursor_x ; + int old_cursor_y ; }; /* @@ -282,6 +290,15 @@ int nb_lines); /* + * Advance/retreat in the list by n percent of the total list elements, + * by at least one line if percent_lines != 0 + * - gui_list : the list structure + * - percent_lines : the percent of the total number of lines to try to move the cursor + * postive adavnces forward, negative retreats back, 0 has no effect + */ +extern void gui_list_select_relative_percent( struct gui_list * gui_list, + int percent_lines ) ; +/* * Adds an item to the list (the callback will be asked for one more item) * - gui_list : the list structure */ Index: apps/gui/statusbar.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/statusbar.c,v retrieving revision 1.26 diff -u -b -r1.26 statusbar.c --- apps/gui/statusbar.c 21 Jun 2006 18:41:57 -0000 1.26 +++ apps/gui/statusbar.c 24 Jun 2006 15:11:26 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: statusbar.c,v 1.26 2006-06-21 18:41:57 amiconn Exp $ + * $Id: statusbar.c,v 1.25 2006-06-06 22:23:52 amiconn Exp $ * * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002) * @@ -93,6 +93,20 @@ 7*ICONS_SPACING #define STATUSBAR_LOCKR_WIDTH 5 +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +#define STATUSBAR_SCROLL_ACCEL_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH + \ + STATUSBAR_VOLUME_WIDTH + \ + STATUSBAR_PLAY_STATE_WIDTH + \ + STATUSBAR_PLAY_MODE_WIDTH + \ + STATUSBAR_SHUFFLE_WIDTH + \ + STATUSBAR_LOCKM_WIDTH + \ + STATUSBAR_LOCKR_WIDTH + \ + 8*ICONS_SPACING +#define STATUSBAR_SCROLL_ACCEL_WIDTH 48 +#endif + #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) #define STATUSBAR_DISK_WIDTH 12 #define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \ @@ -203,7 +217,14 @@ memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info))) { display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) + display->fillrect(0, 0, STATUSBAR_SCROLL_ACCEL_X_POS, STATUSBAR_HEIGHT); + display->fillrect(STATUSBAR_SCROLL_ACCEL_X_POS + STATUSBAR_SCROLL_ACCEL_WIDTH, 0, + display->width-(STATUSBAR_SCROLL_ACCEL_X_POS + STATUSBAR_SCROLL_ACCEL_WIDTH), + STATUSBAR_HEIGHT); +#else display->fillrect(0, 0, display->width, STATUSBAR_HEIGHT); +#endif display->set_drawmode(DRMODE_SOLID); #else @@ -222,12 +243,10 @@ STATUSBAR_PLUG_X_POS, STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH, STATUSBAR_HEIGHT); -#endif /* HAVE_USB_POWER */ -#ifdef CONFIG_CHARGING -#ifdef HAVE_USB_POWER else -#endif +#endif /* HAVE_USB_POWER */ /* draw power plug if charging */ +#ifdef CONFIG_CHARGING if (bar->info.inserted) display->mono_bitmap(bitmap_icons_7x8[Icon_Plug], STATUSBAR_PLUG_X_POS, @@ -236,7 +255,8 @@ #endif bar->redraw_volume = gui_statusbar_icon_volume(bar, bar->info.volume); - gui_statusbar_icon_play_state(display, current_playmode() + Icon_Play); + gui_statusbar_icon_play_state(display, current_playmode() + + Icon_Play); switch (bar->info.repeat) { #if (AB_REPEAT_ENABLE == 1) @@ -553,6 +573,34 @@ } #endif +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +/* + * Print scroll accel to status bar + * Note this function is funny; unlike all the others, it's NOT called by gui_statusbar_draw + */ +void gui_statusbar_draw_scroll_accel(struct screen* display, int accel, int speed ) +{ + if(!global_settings.statusbar) + return; + + unsigned char buffer[ 10 ]; + unsigned int width, height; + snprintf(buffer, sizeof(buffer), "%d %d", accel, speed ); + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(STATUSBAR_SCROLL_ACCEL_X_POS, 0, + STATUSBAR_SCROLL_ACCEL_WIDTH, STATUSBAR_HEIGHT); + display->set_drawmode(DRMODE_SOLID); + display->setfont(FONT_SYSFIXED); + display->getstringsize(buffer, &width, &height); + if (height <= STATUSBAR_HEIGHT) { + display->putsxy(STATUSBAR_SCROLL_ACCEL_X_POS, STATUSBAR_Y_POS, buffer); + } + display->setfont(FONT_UI); + display->update_rect( STATUSBAR_SCROLL_ACCEL_X_POS, STATUSBAR_Y_POS, + STATUSBAR_SCROLL_ACCEL_WIDTH, STATUSBAR_HEIGHT ) ; +} +#endif + #endif /* HAVE_LCD_BITMAP */ void gui_syncstatusbar_init(struct gui_syncstatusbar * bars) Index: apps/gui/statusbar.h =================================================================== RCS file: /cvsroot/rockbox/apps/gui/statusbar.h,v retrieving revision 1.16 diff -u -b -r1.16 statusbar.h --- apps/gui/statusbar.h 6 Jun 2006 22:23:52 -0000 1.16 +++ apps/gui/statusbar.h 24 Jun 2006 15:11:26 -0000 @@ -111,6 +111,16 @@ void gui_statusbar_time(struct screen * display, int hour, int minute); #endif +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) +/* + * Print scroll accel to status bar + * Note this function is funny; unlike all the others, it's NOT called by gui_statusbar_draw + * it updtes teh screen on its own, + * and it is public so outside clients can call it + */ +extern void gui_statusbar_draw_scroll_accel(struct screen* display, int accel, int speed ) ; +#endif + struct gui_syncstatusbar { Index: apps/lang/english.lang =================================================================== RCS file: /cvsroot/rockbox/apps/lang/english.lang,v retrieving revision 1.252 diff -u -b -r1.252 english.lang --- apps/lang/english.lang 25 May 2006 13:34:51 -0000 1.252 +++ apps/lang/english.lang 24 Jun 2006 15:11:29 -0000 @@ -8529,3 +8529,59 @@ *: "Remote Scrolling Options" + + id: LANG_IPOD_SCROLL_WHEEL_SPEED + desc: "Ipod Scroll Wheel Acceleration By Speed" Submenu in "System" menu + user: + + *: "Ipod Scroll Wheel Acceleration" + + + *: "Ipod Scroll Wheel Acceleration" + + + *: "Ipod Scroll Wheel Acceleration" + + + + id: LANG_IPOD_SCROLL_WHEEL_FAST + desc: "Ipod Scroll Wheel By Speed Fast Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu + user: + + *: "Minimum speed for 'fast' acceleration" + + + *: "Minimum speed for 'fast' acceleration" + + + *: "Minimum speed for 'fast' acceleration" + + + + id: LANG_IPOD_SCROLL_WHEEL_FASTER + desc: "Ipod Scroll Wheel By Speed Faster Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu + user: + + *: "Minimum speed for 'faster' acceleration" + + + *: "Minimum speed for 'faster' acceleration" + + + *: "Minimum speed for 'faster' acceleration" + + + + id: LANG_IPOD_SCROLL_WHEEL_FASTEST + desc: "Ipod Scroll Wheel By Speed Fastest Threshold" Submenu in "Ipod Scroll Wheel Acceleration By Speed" menu + user: + + *: "Minimum speed for 'fastest' acceleration" + + + *: "Minimum speed for 'fastest' acceleration" + + + *: "Minimum speed for 'fastest' acceleration" + + Index: firmware/drivers/button.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/button.c,v retrieving revision 1.143 diff -u -b -r1.143 button.c --- firmware/drivers/button.c 6 Jun 2006 22:23:41 -0000 1.143 +++ firmware/drivers/button.c 24 Jun 2006 15:11:31 -0000 @@ -39,6 +39,7 @@ #include "power.h" #include "system.h" #include "powermgmt.h" +#include "logf.h" #ifdef HAVE_REMOTE_LCD #include "lcd-remote.h" @@ -86,12 +87,38 @@ static bool remote_button_hold_only(void); #endif -#if CONFIG_KEYPAD == IPOD_4G_PAD +#if CONFIG_KEYPAD == IPOD_4G_PAD && !defined(IPOD_MINI) /* Variable to use for setting button status in interrupt handler */ int int_btn = BUTTON_NONE; + +void ipod_4g_button_int( void ) ; + +static int accumulated_wheel_scroll_delta = 0 ; +unsigned long wheel_scroll_down_microsecond_tick = 0 ; +unsigned long wheel_scroll_key_microsecond_tick = 0 ; +unsigned long wheel_scroll_key_microsecond_tick_elapsed = 0 ; +const unsigned long ONE_MILLION = 1000000 ; + +int get_accumulated_wheel_scroll_delta( void ) { + return accumulated_wheel_scroll_delta ; +} + +int get_ipod_scroll_wheel_clicks_per_second( void ) { + unsigned long wst = wheel_scroll_key_microsecond_tick ; + int accum = accumulated_wheel_scroll_delta ; + unsigned int abs_accum = accum < 0 ? -accum : accum ; + unsigned long wste = wheel_scroll_key_microsecond_tick_elapsed ; + if( wste == wst ) wst = wheel_scroll_down_microsecond_tick ; + unsigned long diff = wste - wst ; + unsigned int r = diff ? ( ( abs_accum * ONE_MILLION ) / diff ) : 0 ; +#ifdef ROCKBOX_HAS_LOGF + logf( "d1,%d,%d", wst, wste ) ; + logf( "d2,%d,%d,%d", diff, accum, r ) ; #endif + return accum < 0 ? -r : r ; +} + -#if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI) static void opto_i2c_init(void) { int i, curr_value; @@ -156,37 +183,58 @@ /* NB: highest wheel = 0x5F, clockwise increases */ int new_wheel_value = (status << 9) >> 25; backlight_on(); + + if( old_wheel_value == -1 ) { + /* -1 is a sentinal value, meaning there is no old value + * because the finger was lifted and thus, no key to emit + */ + old_wheel_value = new_wheel_value ; + accumulated_wheel_scroll_delta = 0 ; + wheel_scroll_down_microsecond_tick = USEC_TIMER ; + + } else { + /* calculate the delta regardless of whether we'll add a key + * for the use of the acceleration fucntion + */ /* The queue should have no other events when scrolling */ - if (queue_empty(&button_queue) && old_wheel_value >= 0) { /* This is for later = BUTTON_SCROLL_TOUCH;*/ int wheel_delta = new_wheel_value - old_wheel_value; - unsigned long data; - int wheel_keycode; if (wheel_delta < -48) wheel_delta += 96; /* Forward wrapping case */ else if (wheel_delta > 48) wheel_delta -= 96; /* Backward wrapping case */ - if (wheel_delta > 4) { - wheel_keycode = BUTTON_SCROLL_FWD; - } else if (wheel_delta < -4) { - wheel_keycode = BUTTON_SCROLL_BACK; - } else goto wheel_end; + if( wheel_delta > 4 || wheel_delta < -4 ) { + /* ignore anything less than a jiggle factor */ - data = (wheel_delta << 16) | new_wheel_value; - queue_post(&button_queue, wheel_keycode | wheel_repeat, - (void *)data); + if ( queue_empty(&button_queue) ) { + /* only post a scroll button if the queue is empty */ + int wheel_keycode = wheel_delta > 0 ? BUTTON_SCROLL_FWD : BUTTON_SCROLL_BACK ; + unsigned long data = (wheel_delta << 16) | new_wheel_value; + wheel_scroll_key_microsecond_tick = wheel_scroll_key_microsecond_tick_elapsed ; + accumulated_wheel_scroll_delta = 0 ; + queue_post(&button_queue, wheel_keycode | wheel_repeat, (void *)data); if (!wheel_repeat) wheel_repeat = BUTTON_REPEAT; } - old_wheel_value = new_wheel_value; + accumulated_wheel_scroll_delta += wheel_delta ; + old_wheel_value = new_wheel_value ; + wheel_scroll_key_microsecond_tick_elapsed = USEC_TIMER ; + + } else goto wheel_end ; /* not clear this is still needed, basically skips call to opto_i2c_init() */ + } + } else if (old_wheel_value >= 0) { /* scroll wheel up */ old_wheel_value = -1; wheel_repeat = 0; + accumulated_wheel_scroll_delta = 0 ; + wheel_scroll_down_microsecond_tick = 0 ; + wheel_scroll_key_microsecond_tick = 0 ; + wheel_scroll_key_microsecond_tick_elapsed = 0 ; } } else if (status == 0xffffffff) { @@ -211,6 +259,7 @@ udelay(50); outl(0x0, 0x7000c140); int_btn = ipod_4g_button_read(); + outl(inl(0x7000c104) | 0xC000000, 0x7000c104); outl(0x400a1f00, 0x7000c100); Index: firmware/export/button.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/button.h,v retrieving revision 1.50 diff -u -b -r1.50 button.h --- firmware/export/button.h 26 Mar 2006 22:20:27 -0000 1.50 +++ firmware/export/button.h 24 Jun 2006 15:11:31 -0000 @@ -33,7 +33,7 @@ #define HAS_BUTTON_HOLD #endif extern struct event_queue button_queue; - +extern unsigned long wheel_scroll_tick ; void button_init (void); long button_get (bool block); long button_get_w_tmo(int ticks); @@ -233,6 +233,21 @@ #define BUTTON_REMOTE 0 +#if (CONFIG_KEYPAD == IPOD_4G_PAD) +extern int get_accumulated_wheel_scroll_delta( void ) ; +extern int get_ipod_scroll_wheel_clicks_per_second( void ) ; +//enum wheel_acceleration { ACCEL_NONE, ACCEL_FAST, ACCEL_FASTER, ACCEL_FASTEST } ; +//extern enum wheel_acceleration get_ipod_scroll_wheel_acceration( unsigned int* pq1, unsigned int* pq1a ) ; +/* warning to clients calling get_ipod_scroll_wheel_acceration: + * Calling this function may have side-effects; + * this function should be called once per call to button_get + * or button_get_w_tmo, and results locally cached as needed. + * In particular, some acceleration implementations + * may need to reset a calculated delta when + * get_ipod_scroll_wheel_acceration is called. + */ +#endif + /* This is for later #define BUTTON_SCROLL_TOUCH 0x00000200 */