Changeset 2631


Ignore:
Timestamp:
08/04/07 14:50:34 (6 years ago)
Author:
abraxa
Message:

Continued work on UI<->backend communication and gstreamer wrapping

Location:
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am

    r2613 r2631  
    1818        $(OMP_DEFINES) \ 
    1919        -I$(top_srcdir) \ 
    20         -I$(top_srcdir)/intl 
     20        -I$(top_srcdir)/intl\ 
     21        -g -DDEBUG 
    2122 
    2223INCLUDES = $(openmoko_mediaplayer_CFLAGS) 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c

    r2613 r2631  
    141141omp_config_restore_state() 
    142142{ 
     143        #ifdef DEBUG 
     144                g_print("Loading playlist and restoring playback state\n"); 
     145        #endif 
     146 
    143147        // This mustn't be called more than once 
    144148        g_assert(omp_config == NULL); 
     
    159163        if (!omp_playlist_set_current_track(omp_config->playlist_position)) 
    160164        { 
    161                 // Reset playlist state as it must have been modified since it was last loaded 
     165                // Reset playlist state as playlist must have been modified since it was last loaded 
    162166                omp_config->playlist_position = 0; 
    163167                omp_config->track_position = 0; 
    164         }  
     168                omp_playlist_set_current_track(0); 
     169        } 
    165170 
    166171        // Feed the track entity to the playback engine to obtain track information 
     
    363368        signal(SIGUSR1, handler_sigusr1); 
    364369 
    365         // Load config and restore playback state 
    366         omp_config_restore_state(); 
    367  
    368370        // Initialize playback, playlist and UI handling 
    369371        omp_main_window_create(); 
     
    371373        omp_playlist_init(); 
    372374        omp_main_connect_signals(); 
    373         omp_main_update_track_info(); 
     375        omp_config_restore_state(); 
    374376        omp_main_window_show(); 
    375377 
     
    385387        omp_playlist_free(); 
    386388        gst_deinit(); 
     389        g_free(ui_image_path); 
    387390 
    388391#ifdef DEBUG_MEM_PROFILE 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h

    r2613 r2631  
    5353        gchar playlist_file[256];                               ///< Path and file name of current (=last used) playlist 
    5454        gint playlist_position;                                 ///< Position within the playlist 
    55         gint track_position;                                            ///< Position to resume playback from within the last played track 
     55        glong track_position;                                           ///< Position to resume playback from within the last played track 
    5656}; 
    5757 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c

    r2613 r2631  
    6060GtkWidget *omp_main_window = NULL; 
    6161 
     62gboolean omp_main_time_slider_can_update = TRUE; 
     63gboolean omp_main_time_slider_was_dragged = FALSE; 
    6264 
    6365 
     
    6870omp_application_terminate() 
    6971{ 
    70         // Free resources 
    71         g_free(ui_image_path); 
    72  
    7372        // Tell GTK to leave the message loop 
    7473        gtk_main_quit(); 
     
    191190} 
    192191 
     192/** 
     193 * Gets called when the time slider's value got changed (yes, that means it gets called every second, too) 
     194 */ 
     195void 
     196omp_main_time_slider_changed(GtkRange *range, gpointer data) 
     197{ 
     198        if (omp_main_time_slider_was_dragged) 
     199        { 
     200                omp_main_time_slider_was_dragged = FALSE; 
     201 
     202                // Set new position and resume playback that was paused when dragging started 
     203                omp_playback_set_track_position(gtk_range_get_value(GTK_RANGE(range))); 
     204 
     205                // Update UI right away 
     206                gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position()); 
     207        } 
     208} 
     209 
     210/** 
     211 * Gets called when the user starts dragging the time slider 
     212 */ 
     213gboolean 
     214omp_main_time_slider_drag_start(GtkWidget *widget, GdkEventButton *event, gpointer user_data) 
     215{ 
     216        while (gtk_events_pending()) gtk_main_iteration(); 
     217 
     218        // Prevent UI callbacks from messing with the slider position 
     219        omp_main_time_slider_can_update = FALSE; 
     220} 
     221 
     222/** 
     223 * Gets called when the user stops dragging the time slider 
     224 */ 
     225gboolean 
     226omp_main_time_slider_drag_stop(GtkWidget *widget, GdkEventButton *event, gpointer user_data) 
     227{ 
     228        while (gtk_events_pending()) gtk_main_iteration(); 
     229 
     230        // Allow UI callbacks to alter the the slider position again 
     231        omp_main_time_slider_can_update = TRUE; 
     232 
     233        // Notify the slider change callback that this time we indeed want to change position 
     234        omp_main_time_slider_was_dragged = TRUE; 
     235} 
     236 
    193237void 
    194238omp_shuffle_button_callback(GtkWidget* widget, gpointer data) 
     
    226270 
    227271/** 
     272 * Event handler for the Fast Forward button 
     273 */ 
     274void 
     275omp_main_button_fast_forward_callback() 
     276{ 
     277        // Set new position and resume playback that was paused when dragging started 
     278        omp_playback_set_track_position(omp_playback_get_track_position()+BUTTON_SEEK_DISTANCE); 
     279 
     280        // Update UI right away 
     281        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position()); 
     282} 
     283 
     284/** 
     285 * Event handler for the Rewind button 
     286 */ 
     287void 
     288omp_main_button_rewind_callback() 
     289{ 
     290        // Set new position and resume playback that was paused when dragging started 
     291        omp_playback_set_track_position(omp_playback_get_track_position()-BUTTON_SEEK_DISTANCE); 
     292 
     293        // Update UI right away 
     294        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position()); 
     295} 
     296 
     297/** 
    228298 * Event handler for the Play/Pause button 
    229  * @todo State change, etc 
     299 * @todo Pixmap change 
    230300 */ 
    231301void 
    232302omp_main_button_play_pause_callback() 
    233303{ 
    234         omp_playback_play(); 
     304        if (omp_playback_get_state() != OMP_PLAYBACK_STATE_PLAYING) 
     305        { 
     306                omp_playback_play(); 
     307 
     308        } else { 
     309 
     310                omp_playback_pause(); 
     311        } 
    235312} 
    236313 
     
    283360        image = gtk_image_new_from_icon_name(image_name, 36); 
    284361        gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(image)); 
    285         g_object_unref(image); 
    286362 
    287363        return button; 
     
    389465        GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(main_widgets.time_hscale), GTK_CAN_FOCUS); 
    390466        gtk_widget_set_size_request(GTK_WIDGET(main_widgets.time_hscale), 338, 35); 
     467        gtk_range_set_update_policy(GTK_RANGE(main_widgets.time_hscale), GTK_UPDATE_DISCONTINUOUS); 
    391468        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 0.0); 
    392 //    g_signal_connect(G_OBJECT(time_hscale), "change_value", 
    393 //                  G_CALLBACK(omp_main_set_time), NULL); 
     469        g_signal_connect(G_OBJECT(main_widgets.time_hscale), "value_changed",                                   G_CALLBACK(omp_main_time_slider_changed), NULL); 
     470        g_signal_connect(G_OBJECT(main_widgets.time_hscale), "button-press-event",              G_CALLBACK(omp_main_time_slider_drag_start), NULL); 
     471        g_signal_connect(G_OBJECT(main_widgets.time_hscale), "button-release-event",    G_CALLBACK(omp_main_time_slider_drag_stop), NULL); 
    394472        gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(main_widgets.time_hscale)); 
    395473 
     
    484562 
    485563        // Rewind button 
    486         button = omp_button_create("gtk-media-rewind-ltr", NULL); 
     564        button = omp_button_create("gtk-media-rewind-ltr", G_CALLBACK(omp_main_button_rewind_callback)); 
    487565        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0); 
    488566        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START); 
     
    494572 
    495573        // Fast Forward button 
    496         button = omp_button_create("gtk-media-forward-ltr", NULL); 
     574        button = omp_button_create("gtk-media-forward-ltr", G_CALLBACK(omp_main_button_fast_forward_callback)); 
    497575        gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0); 
    498576        gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START); 
     
    537615        gtk_widget_show_all(GTK_WIDGET(bg_muxer)); 
    538616 
     617 
    539618        return; 
    540619} 
     
    548627omp_main_connect_signals() 
    549628{ 
    550         g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PREV_TRACK, G_CALLBACK(omp_main_update_track_info), NULL); 
    551         g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_NEXT_TRACK, G_CALLBACK(omp_main_update_track_info), NULL); 
    552 } 
    553  
     629        g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED,                   G_CALLBACK(omp_main_update_track_change), NULL); 
     630        g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED,          G_CALLBACK(omp_main_update_track_change), NULL); 
     631        g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED,        G_CALLBACK(omp_main_update_track_position), NULL); 
     632} 
    554633 
    555634/** 
    556635 * Evaluates current track information and updates the config/UI if necessary 
    557  */ 
    558 void 
    559 omp_main_update_track_info() 
     636 * @note This function only checks elements that don't change too often - for the rest we have specialized functions below 
     637 */ 
     638void 
     639omp_main_update_track_change() 
    560640{ 
    561641        static gint old_track_count = 0; 
    562642        static gint old_track_id = 0; 
    563  
     643        static gulong old_track_length = 0; 
     644 
     645        gulong track_length, track_position; 
    564646        gchar *text; 
    565647 
     
    573655                omp_config_update(); 
    574656 
    575                 // Update UI 
     657                // Update label 
    576658                text = g_strdup_printf(WIDGET_CAPTION_TRACK_NUM, omp_playlist_current_track_id+1, omp_playlist_track_count); 
    577659                gtk_label_set_text(GTK_LABEL(main_widgets.track_number_label), text); 
     
    579661        } 
    580662 
    581  
    582 } 
    583  
     663        // Got a track length change? 
     664        track_length = omp_playback_get_track_length(); 
     665 
     666        if (track_length != old_track_length) 
     667        { 
     668                old_track_length = track_length; 
     669                track_position = omp_playback_get_track_position(); 
     670 
     671                // Set new time slider increments 
     672                gtk_range_set_increments(GTK_RANGE(main_widgets.time_hscale), track_length/10, track_length/10); 
     673 
     674                // Update label and slider 
     675                text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME, 
     676                        track_position / 60, track_position % 60, 
     677                        track_length / 60, track_length % 60); 
     678                gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text); 
     679                g_free(text); 
     680 
     681                if (omp_main_time_slider_can_update) 
     682                { 
     683                        gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? track_length : 1); 
     684                        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position); 
     685                } 
     686        } 
     687} 
     688 
     689/** 
     690 * Updates the UI if the playback position changed 
     691 */ 
     692void 
     693omp_main_update_track_position() 
     694{ 
     695        static gulong old_track_position = 0; 
     696 
     697        gulong track_position, track_length; 
     698        gchar *text; 
     699 
     700        // Got a track length change? 
     701        track_position = omp_playback_get_track_position(); 
     702        { 
     703                old_track_position = track_position; 
     704                track_length = omp_playback_get_track_length(); 
     705 
     706                // Update UI 
     707                text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME, 
     708                        track_position / 60, track_position % 60, 
     709                        track_length / 60, track_length % 60); 
     710                gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text); 
     711                g_free(text); 
     712 
     713                if (omp_main_time_slider_can_update) 
     714                { 
     715                        gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? track_length : 1); 
     716                        gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position); 
     717                } 
     718        } 
     719 
     720} 
     721 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h

    r2613 r2631  
    3434#define WIDGET_CAPTION_VOLUME "%d%%" 
    3535 
     36// Determines how many seconds the engine will seek if the FFWD/REW buttons are clicked 
     37#define BUTTON_SEEK_DISTANCE 10 
     38 
    3639extern GtkWidget *omp_main_window; 
    3740 
     
    4346void omp_main_connect_signals(); 
    4447 
    45 void omp_main_update_track_info(); 
     48void omp_main_update_track_change(); 
     49void omp_main_update_track_position(); 
    4650 
    4751#endif 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c

    r2613 r2631  
    3131 
    3232GstElement *omp_gst_playbin = NULL; 
    33  
    34  
     33guint omp_playback_ui_timeout = 0; 
     34gboolean omp_playback_ui_timeout_halted; 
    3535 
    3636/** 
     
    4949 
    5050        // Create the signals we'll emit 
    51         g_signal_new(OMP_EVENT_PLAYBACK_EOS, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
     51        g_signal_new(OMP_EVENT_PLAYBACK_EOS,                                                            G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
     52        g_signal_new(OMP_EVENT_PLAYBACK_STATUS_CHANGED,                 G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
     53        g_signal_new(OMP_EVENT_PLAYBACK_POSITION_CHANGED,               G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
    5254 
    5355        // Set up gstreamer pipe and bins 
     
    8284/** 
    8385 * Attempts to load a track from an URI 
     86 * @return TRUE if successful, FALSE if failed 
    8487 */ 
    8588gboolean 
     
    9295        } 
    9396 
    94         // DEBUG 
    95         g_printf("Loading %s\n", uri); 
     97        #ifdef DEBUG 
     98                g_printf("Loading track: %s\n", uri); 
     99        #endif 
    96100 
    97101        gst_element_set_state(omp_gst_playbin, GST_STATE_NULL); 
    98102        g_object_set(G_OBJECT(omp_gst_playbin), "uri", uri, NULL); 
    99103        gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED); 
     104 
     105        return (gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE); 
     106} 
     107 
     108/** 
     109 * This callback gets called at least once per second if a track is playing 
     110 */ 
     111static gboolean 
     112omp_playback_ui_timeout_callback(gpointer data) 
     113{ 
     114        g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED); 
     115         
     116        if (omp_playback_ui_timeout_halted) 
     117        { 
     118                // Reset the timeout ID so we can prevent race conditions 
     119                omp_playback_ui_timeout = 0; 
     120                return FALSE; 
     121        } 
     122 
     123        return TRUE; 
    100124} 
    101125 
     
    106130omp_playback_play() 
    107131{ 
    108         // DEBUG 
    109         g_print("Starting playback\n"); 
    110  
     132        #ifdef DEBUG 
     133                g_print("Starting playback\n"); 
     134        #endif 
     135 
     136        // Set state 
    111137        gst_element_set_state(omp_gst_playbin, GST_STATE_PLAYING); 
     138        g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED); 
     139 
     140        // Add timer to update UI if necessary 
     141        // If the halt flag was set but the callback didn't run yet then we 
     142        // don't want to add another callback since we would have two then 
     143        omp_playback_ui_timeout_halted = FALSE; 
     144 
     145        if (!omp_playback_ui_timeout) 
     146        { 
     147                omp_playback_ui_timeout = g_timeout_add(PLAYBACK_UI_UPDATE_INTERVAL, omp_playback_ui_timeout_callback, NULL); 
     148        } 
     149} 
     150 
     151/** 
     152 * Suspends playback of the current stream 
     153 */ 
     154void 
     155omp_playback_pause() 
     156{ 
     157        #ifdef DEBUG 
     158                g_print("Suspending playback\n"); 
     159        #endif 
     160 
     161        // Set state 
     162        gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED); 
     163        g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED); 
     164 
     165        // Stop timer 
     166        omp_playback_ui_timeout_halted = TRUE; 
    112167} 
    113168 
    114169/** 
    115170 * Returns the current state the playback engine is in 
     171 * @todo Don't use system clock, might be out-of-sync with playbin clock? 
    116172 */ 
    117173gint 
     
    119175{ 
    120176        GstState state; 
    121         GstSystemClock *system_clock; 
     177        GstClock *clock; 
    122178 
    123179        // Poll state with an immediate timeout 
    124         system_clock = gst_system_clock_obtain(); 
    125         gst_element_get_state(GST_OBJECT(omp_gst_playbin), &state, NULL, gst_clock_get_time(system_clock)); 
    126         gst_object_unref(system_clock); 
    127  
    128         // The NULL element state is no different from READY for more abstract layers 
    129         if (state == GST_STATE_NULL) 
    130         { 
    131                 state = GST_STATE_READY; 
     180        clock = gst_system_clock_obtain(); 
     181        gst_element_get_state(GST_ELEMENT(omp_gst_playbin), &state, NULL, gst_clock_get_time(clock)); 
     182        gst_object_unref(clock); 
     183 
     184        // The NULL and READY element states are no different from PAUSED for more abstract layers 
     185        if ( (state == GST_STATE_NULL) || (state == GST_STATE_READY) ) 
     186        { 
     187                state = GST_STATE_PAUSED; 
    132188        } 
    133189 
    134190        return (gint)state; 
     191} 
     192 
     193/** 
     194 * Returns the number of seconds that the track has been playing so far 
     195 */ 
     196gulong 
     197omp_playback_get_track_position() 
     198{ 
     199        GstFormat format = GST_FORMAT_TIME; 
     200        gint64 position; 
     201 
     202        if (!omp_gst_playbin) 
     203        { 
     204                return 0; 
     205        } 
     206 
     207        // Return 0 if function returns FALSE, position otherwise 
     208        return (gst_element_query_position(omp_gst_playbin, &format, &position)) ? (position/GST_SECOND) : 0; 
     209} 
     210 
     211/** 
     212 * Sets the playback position of the currently loaded track 
     213 */ 
     214void 
     215omp_playback_set_track_position(glong position) 
     216{ 
     217        if (!omp_gst_playbin) 
     218        { 
     219                return; 
     220        } 
     221 
     222        gst_element_seek_simple(GST_ELEMENT(omp_gst_playbin), 
     223                GST_FORMAT_TIME, 
     224                GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 
     225                position*GST_SECOND); 
     226 
     227        g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED); 
     228} 
     229 
     230/** 
     231 * Returns the current track's playing length 
     232 */ 
     233gulong 
     234omp_playback_get_track_length() 
     235{ 
     236        GstFormat format = GST_FORMAT_TIME; 
     237        gint64 length; 
     238 
     239        if (!omp_gst_playbin) 
     240        { 
     241                return 0; 
     242        } 
     243 
     244        // Return 0 if function returns FALSE, track length otherwise 
     245        return (gst_element_query_duration(omp_gst_playbin, &format, &length)) ? (length/GST_SECOND) : 0; 
    135246} 
    136247 
     
    141252omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer data) 
    142253{ 
    143         // DEBUG 
    144         g_printf("End of stream reached.\n"); 
    145  
    146         gst_element_set_state(omp_gst_playbin, GST_STATE_NULL); 
     254        #ifdef DEBUG 
     255                g_printf("End of stream reached.\n"); 
     256        #endif 
     257 
     258        // Reset playback engine 
     259        gst_element_set_state(omp_gst_playbin, GST_STATE_READY); 
     260        omp_playback_set_track_position(0); 
     261 
    147262        g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_EOS); 
    148263 
     
    158273        GError *error; 
    159274 
    160         gst_message_parse_error(message, &error, NULL); 
    161         g_printerr("gstreamer error: %s\n", error->message); 
    162         g_error_free(error); 
     275        #ifdef DEBUG 
     276                gst_message_parse_error(message, &error, NULL); 
     277                g_printerr("gstreamer error: %s\n", error->message); 
     278                gst_message_unref(error); 
     279                g_error_free(error); 
     280        #endif 
    163281 
    164282        return TRUE; 
     
    173291        GError *error; 
    174292 
    175         gst_message_parse_error(message, &error, NULL); 
    176         g_printerr("gstreamer warning: %s\n", error->message); 
    177         g_error_free(error); 
     293        #ifdef DEBUG 
     294                gst_message_parse_warning(message, &error, NULL); 
     295                g_printerr("gstreamer warning: %s\n", error->message); 
     296                gst_message_unref(error); 
     297                g_error_free(error); 
     298        #endif 
    178299 
    179300        return TRUE; 
    180301} 
    181  
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h

    r2613 r2631  
    3131 
    3232#define OMP_EVENT_PLAYBACK_EOS "playback_end_of_stream" 
     33#define OMP_EVENT_PLAYBACK_STATUS_CHANGED "playback_status_change" 
     34#define OMP_EVENT_PLAYBACK_POSITION_CHANGED "playback_position_change" 
    3335 
    3436// Player states masking the gstreamer states so we can be more abstract 
    35 #define OMP_PLAYBACK_STATE_READY GST_STATE_READY 
    3637#define OMP_PLAYBACK_STATE_PAUSED GST_STATE_PAUSED 
    3738#define OMP_PLAYBACK_STATE_PLAYING GST_STATE_PLAYING 
    3839 
     40// The UI will be updated at this interval when a track is playing (in ms) 
     41#define PLAYBACK_UI_UPDATE_INTERVAL 1000 
    3942 
    4043void omp_playback_init(); 
     
    4447 
    4548void omp_playback_play(); 
     49void omp_playback_pause(); 
    4650gint omp_playback_get_state(); 
     51gulong omp_playback_get_track_position(); 
     52void omp_playback_set_track_position(glong position); 
     53gulong omp_playback_get_track_length(); 
    4754 
    4855static gboolean omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer data); 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c

    r2613 r2631  
    6363 
    6464        // Create the signals we emit: no params, no return value 
    65         g_signal_new(OMP_EVENT_PREV_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
    66         g_signal_new(OMP_EVENT_NEXT_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
     65        g_signal_new(OMP_EVENT_PLAYLIST_TRACK_CHANGED, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); 
    6766} 
    6867 
     
    9493omp_playlist_load(gchar *playlist_file) 
    9594{ 
     95        // Free the track history's memory by deleting the first element until the list is empty 
     96        while (omp_track_history) 
     97        { 
     98                g_free(omp_track_history->data); 
     99                omp_track_history = g_slist_delete_link(omp_track_history, omp_track_history); 
     100        } 
     101 
     102        // Let XSPF clean up, too 
    96103        if (omp_playlist) 
    97104        { 
     
    125132        gint track_num = 0; 
    126133 
    127         // DEBUG 
    128         g_printf("Setting current track to #%d\n", playlist_pos); 
     134        #ifdef DEBUG 
     135                g_printf("Setting current track to #%d\n", playlist_pos); 
     136        #endif 
    129137 
    130138        if (!omp_playlist) 
     
    147155        { 
    148156                omp_playlist_track_count = track_num; 
     157 
     158                // Emit signal to update UI and the like 
     159                g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED); 
    149160        } 
    150161 
     
    162173        struct omp_track_history_entry *history_entry; 
    163174        struct spiff_track *track; 
     175        gboolean was_playing; 
    164176        gboolean is_new_track = FALSE; 
    165177 
     
    168180                return; 
    169181        } 
     182 
     183        // If track playing time is >= 10 seconds we just jump back to the beginning of the track 
     184        if (omp_playback_get_track_position() >= 10) 
     185        { 
     186                omp_playback_set_track_position(0); 
     187                return TRUE; 
     188        } 
     189 
     190        // Get player state so we can continue playback if necessary 
     191        was_playing = (omp_playback_get_state() == OMP_PLAYBACK_STATE_PLAYING); 
     192 
     193try_again: 
     194 
     195        #ifdef DEBUG 
     196                if (omp_track_history) 
     197                { 
     198                        GSList *list; 
     199                        g_printf("--- Track History:\n"); 
     200                        list = omp_track_history; 
     201                        while (list) 
     202                        { 
     203                                history_entry = list->data; 
     204                                g_printf("- %s\n", history_entry->track->locations->value); 
     205                                list = g_slist_next(list); 
     206                        } 
     207                        g_printf("---\n"); 
     208                } 
     209        #endif 
    170210 
    171211        // Do we have tracks in the history to go back to? 
     
    198238                        if (track->next) 
    199239                        { 
    200                                 omp_playlist_current_track              = track; 
     240                                omp_playlist_current_track = track; 
    201241                                omp_playlist_current_track_id--; 
    202242                        } 
     
    207247        { 
    208248                // Emit signal to update UI and the like 
    209                 g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PREV_TRACK); 
     249                g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED); 
     250 
     251                // Load track and start playing if needed 
     252                if (omp_playlist_load_current_track()) 
     253                { 
     254                        if (was_playing) omp_playback_play(); 
     255 
     256                } else { 
     257 
     258                        // Uh-oh, track failed to load - let's find another one, shall we? 
     259                        is_new_track = FALSE; 
     260                        goto try_again; 
     261                } 
    210262        } 
    211263 
     
    238290        // Prepare the history entry - if we don't need it we'll just free it again 
    239291        history_entry = g_new(struct omp_track_history_entry, 1); 
    240         history_entry->track = omp_playlist_current_track; 
    241         history_entry->track_id = omp_playlist_current_track_id; 
     292        history_entry->track            = omp_playlist_current_track; 
     293        history_entry->track_id = omp_playlist_current_track_id; 
    242294 
    243295        // Do we have a track to play? 
     
    257309 
    258310                // Emit signal to update UI and the like 
    259                 g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_NEXT_TRACK); 
     311                g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED); 
    260312 
    261313                // Load track and start playing if needed 
  • trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h

    r2613 r2631  
    3030#include <spiff/spiff_c.h> 
    3131 
    32 #define OMP_EVENT_PREV_TRACK "prev_track" 
    33 #define OMP_EVENT_NEXT_TRACK "next_track" 
    34  
    35  
    36 extern struct _omp_playlist_events omp_playlist_events; 
    37  
     32#define OMP_EVENT_PLAYLIST_TRACK_CHANGED "playlist_track_changed" 
    3833 
    3934extern struct spiff_list *omp_playlist; 
Note: See TracChangeset for help on using the changeset viewer.