Changeset 3230


Ignore:
Timestamp:
10/20/07 03:30:20 (6 years ago)
Author:
abraxa
Message:

Add gesture recognition (up/down=volume; left/right=ffwd/rew; stroke+hold=repeat)
Fix bug #893 by changing color for "Add Playlist" button label

Location:
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/TODO

    r3208 r3230  
    2020Documentation: 
    2121        Update wiki 
     22 
     23Playlist management features: 
     24        Search alphabetically 
     25        Jump to track 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/editor_page.c

    r2959 r3230  
    302302        gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(image), TRUE, TRUE, 0); 
    303303 
    304         alignment = label_create(&label, "Sans 6", "black", 0, 0, 0, 0, PANGO_ELLIPSIZE_NONE); 
     304        alignment = label_create(&label, "Sans 6", "white", 0, 0, 0, 0, PANGO_ELLIPSIZE_NONE); 
    305305        gtk_label_set_text(GTK_LABEL(label), _("Add Tracks")); 
    306306        gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(alignment), TRUE, TRUE, 0); 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main_page.c

    r3208 r3230  
    4444 
    4545 
     46#include <math.h> 
     47 
    4648/// Contains all main window widgets that need to be changeable 
    47 struct _main_widgets 
     49struct 
    4850{ 
    4951        GtkWidget *cover_image; 
     
    6466GtkWidget *omp_main_window = NULL; 
    6567 
     68/// Possible gestures 
     69typedef enum 
     70{ 
     71        OMP_MAIN_GESTURE_NONE, 
     72        OMP_MAIN_GESTURE_LEFT, 
     73        OMP_MAIN_GESTURE_RIGHT, 
     74        OMP_MAIN_GESTURE_UP, 
     75        OMP_MAIN_GESTURE_DOWN 
     76} omp_main_gesture; 
     77 
     78/// Holds the necessary infos to record and identify the gestures 
     79struct 
     80{ 
     81        gboolean pressed; 
     82        GTimeVal start_time; 
     83        guint x_origin, y_origin; 
     84        guint last_x, last_y; 
     85        gboolean cursor_idle;                                           // TRUE if cursor isn't moving 
     86 
     87        gint radius, angle; 
     88        omp_main_gesture gesture; 
     89        gboolean repeating; 
     90        guint repeat_timeout; 
     91} main_gesture_data; 
     92 
    6693// Forward declarations for internal use 
    6794void omp_main_set_label(omp_main_label_type label_type, gchar *caption); 
     
    78105 
    79106/** 
     107 * Self-explanatory :) 
     108 */ 
     109gint min(gint a, gint b) 
     110{ 
     111        return (a > b) ? b : a; 
     112} 
     113 
     114/** 
     115 * Self-explanatory :) 
     116 */ 
     117gint max(gint a, gint b) 
     118{ 
     119        return (a > b) ? a : b; 
     120} 
     121 
     122/** 
    80123 * Event handler for the expand button 
    81124 */ 
     
    159202{ 
    160203        error_dialog("Not implemented yet, sorry :)"); 
     204} 
     205 
     206/** 
     207 * Tries to determine which gesture the user has performed and fills the gesture data struct accordingly 
     208 * @param x X coordinate of current pressure point 
     209 * @param y Y coordinate of current pressure point 
     210 */ 
     211void 
     212omp_main_gesture_identify(guint x, guint y) 
     213{ 
     214        #define MIN_RADIUS 15 
     215 
     216        gint delta_x, delta_y, gamma; 
     217 
     218        // Perform rect->polar conversion of the differential cursor movement 
     219        delta_x = x - main_gesture_data.x_origin; 
     220        delta_y = y - main_gesture_data.y_origin; 
     221 
     222        main_gesture_data.radius = sqrt(delta_x * delta_x + delta_y * delta_y); 
     223 
     224        // angle = arccos(gamma) but arccos() is too slow to compute -> range comparison 
     225        // We shift the comma by 3 digits so we can use integer math 
     226        gamma = delta_x*1000 / main_gesture_data.radius; 
     227 
     228        if (main_gesture_data.radius > MIN_RADIUS) 
     229        { 
     230 
     231                // Determine direction of movement 
     232                if (gamma < -707) 
     233                { 
     234                        main_gesture_data.gesture = OMP_MAIN_GESTURE_LEFT; 
     235 
     236                } else { 
     237 
     238                        if (gamma > 707) 
     239                        { 
     240                                main_gesture_data.gesture = OMP_MAIN_GESTURE_RIGHT; 
     241                        } else { 
     242                                main_gesture_data.gesture = (delta_y < 0) ? OMP_MAIN_GESTURE_UP : OMP_MAIN_GESTURE_DOWN; 
     243                        } 
     244 
     245                } 
     246 
     247        } else { 
     248 
     249                // Radius too small 
     250                main_gesture_data.gesture = OMP_MAIN_GESTURE_NONE; 
     251        } 
     252 
     253} 
     254 
     255/** 
     256 * Performs the action the current gesture commands 
     257 */ 
     258void 
     259omp_main_gesture_trigger() 
     260{ 
     261        if (main_gesture_data.gesture == OMP_MAIN_GESTURE_NONE) return; 
     262 
     263        switch (main_gesture_data.gesture) 
     264        { 
     265                case OMP_MAIN_GESTURE_LEFT: 
     266                { 
     267                        omp_main_rewind_clicked(NULL, NULL); 
     268                        break; 
     269                } 
     270 
     271                case OMP_MAIN_GESTURE_RIGHT: 
     272                { 
     273                        omp_main_fast_forward_clicked(NULL, NULL); 
     274                        break; 
     275                } 
     276 
     277                case OMP_MAIN_GESTURE_UP: 
     278                { 
     279                        omp_playback_set_volume(min(100, omp_playback_get_volume()+10)); 
     280                        break; 
     281                } 
     282 
     283                case OMP_MAIN_GESTURE_DOWN: 
     284                { 
     285                        omp_playback_set_volume(max(0, omp_playback_get_volume()-10)); 
     286                        break; 
     287                } 
     288 
     289                default: break; 
     290        } 
     291} 
     292 
     293/** 
     294 * This callback repeatedly performs the action the current gesture commands 
     295 */ 
     296static gboolean 
     297omp_main_gesture_repeat_callback(gpointer data) 
     298{ 
     299        if (!main_gesture_data.repeating) return FALSE; 
     300 
     301        omp_main_gesture_trigger(); 
     302 
     303        return TRUE; 
     304} 
     305 
     306/** 
     307 * Sets up the repeat timeout if the touchscreen is being pressed for a certain amount of time 
     308 */ 
     309void 
     310omp_main_gesture_check_repeat() 
     311{ 
     312        #define REPEAT_TIME_TRESHOLD_USEC 0750000 
     313        #define REPEAT_INTERVAL_MSEC 1000 
     314 
     315        GTimeVal current_time, delta_t; 
     316 
     317        if (!main_gesture_data.repeating) 
     318        { 
     319                // Calculate duration of touchscreen press 
     320                g_get_current_time(&current_time); 
     321                delta_t.tv_sec  = current_time.tv_sec  - main_gesture_data.start_time.tv_sec; 
     322                delta_t.tv_usec = current_time.tv_usec - main_gesture_data.start_time.tv_usec; 
     323 
     324                if (delta_t.tv_usec >= REPEAT_TIME_TRESHOLD_USEC) 
     325                { 
     326                        main_gesture_data.repeating = TRUE; 
     327                        g_timeout_add(REPEAT_INTERVAL_MSEC, omp_main_gesture_repeat_callback, NULL); 
     328                } 
     329 
     330        } 
     331} 
     332 
     333/** 
     334 * Gets called whenever the cursor has been moved, handling gesture recognition and triggering 
     335 */ 
     336gboolean 
     337omp_main_pointer_moved(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) 
     338{ 
     339        #define MAX_DELTA_LAST 3 
     340        gint delta_last_x, delta_last_y; 
     341 
     342//      g_printf("Pointer: X=%d /\t Y=%d /\t state=%d /\t is_hint=%d\n", 
     343//              (gint)event->x, (gint)event->y, event->state, event->is_hint); 
     344 
     345        if (main_gesture_data.pressed) 
     346        { 
     347                delta_last_x = abs((guint)event->x - main_gesture_data.last_x); 
     348                delta_last_y = abs((guint)event->y - main_gesture_data.last_y); 
     349 
     350                // Did the cursor move a substantial amount? 
     351                if ( (delta_last_x > MAX_DELTA_LAST) && (delta_last_y > MAX_DELTA_LAST) ) 
     352                { 
     353                        // Yes it did, so it's most likely being moved 
     354                        main_gesture_data.cursor_idle = FALSE; 
     355                        main_gesture_data.last_x = event->x; 
     356                        main_gesture_data.last_y = event->y; 
     357 
     358                        // Make sure we won't trigger anymore (if we were before, that is) 
     359                        main_gesture_data.repeating = FALSE; 
     360//                      g_printf("-- movement\n"); 
     361 
     362                } else { 
     363//                      g_printf("-- NO movement\n"); 
     364 
     365                        // Cursor is idle, so lets update the gesture data if it wasn't idle before 
     366                        if (!main_gesture_data.cursor_idle) 
     367                                omp_main_gesture_identify(event->x, event->y); 
     368 
     369                        omp_main_gesture_check_repeat(); 
     370 
     371                        main_gesture_data.cursor_idle = TRUE; 
     372                } 
     373        } 
     374 
     375        return FALSE; 
     376} 
     377 
     378/** 
     379 * Gets called whenever the touchscreen has been pressed, handling gesture recognition and triggering 
     380 */ 
     381gboolean 
     382omp_main_pointer_pressed(GtkWidget *widget, GdkEventButton *event, gpointer user_data) 
     383{ 
     384//      g_printf("- Pressed: X=%d /\t Y=%d /\t state=%d /\t button=%d\n", 
     385//              (gint)event->x, (gint)event->y, event->state, event->button); 
     386 
     387        main_gesture_data.pressed = TRUE; 
     388        g_get_current_time(&main_gesture_data.start_time); 
     389        main_gesture_data.x_origin = event->x; 
     390        main_gesture_data.y_origin = event->y; 
     391        main_gesture_data.last_x = event->x; 
     392        main_gesture_data.last_y = event->y; 
     393        main_gesture_data.cursor_idle = FALSE; 
     394        main_gesture_data.gesture = OMP_MAIN_GESTURE_NONE; 
     395        main_gesture_data.repeating = FALSE; 
     396 
     397        return FALSE; 
     398} 
     399 
     400/** 
     401 * Gets called whenever the touchscreen has been released, handling gesture recognition and triggering 
     402 */ 
     403gboolean 
     404omp_main_pointer_released(GtkWidget *widget, GdkEventButton *event, gpointer user_data) 
     405{ 
     406//      g_printf("- Released: X=%d /\t Y=%d /\t state=%d /\t button=%d\n", 
     407//              (gint)event->x, (gint)event->y, event->state, event->button); 
     408 
     409        // Stop repeat trigger if necessary - or trigger action 
     410        if (main_gesture_data.repeating) 
     411        { 
     412                main_gesture_data.repeating = FALSE; 
     413        } else { 
     414                omp_main_gesture_trigger(); 
     415        } 
     416 
     417        main_gesture_data.pressed = FALSE; 
     418 
     419        return FALSE; 
    161420} 
    162421 
     
    481740                G_CALLBACK(omp_main_update_volume), NULL); 
    482741 
     742        // Set up gesture recognition handlers 
     743        gtk_widget_add_events(eventbox, 
     744                GDK_POINTER_MOTION_MASK |  
     745                GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); 
     746 
     747        main_gesture_data.pressed = FALSE; 
     748 
     749        g_signal_connect(G_OBJECT(eventbox), "motion-notify-event", G_CALLBACK(omp_main_pointer_moved), NULL); 
     750        g_signal_connect(G_OBJECT(eventbox), "button-press-event", G_CALLBACK(omp_main_pointer_pressed), NULL); 
     751        g_signal_connect(G_OBJECT(eventbox), "button-release-event", G_CALLBACK(omp_main_pointer_released), NULL); 
     752 
    483753        // Make widgets visible - can't use gtk_widget_show_all() here as some widgets should stay hidden 
    484754        gtk_widget_show(vbox); 
Note: See TracChangeset for help on using the changeset viewer.