r2631 - trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src
abraxa at sita.openmoko.org
abraxa at sita.openmoko.org
Sat Aug 4 14:50:37 CEST 2007
Author: abraxa
Date: 2007-08-04 14:50:34 +0200 (Sat, 04 Aug 2007)
New Revision: 2631
Modified:
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c
trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h
Log:
Continued work on UI<->backend communication and gstreamer wrapping
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/Makefile.am 2007-08-04 12:50:34 UTC (rev 2631)
@@ -17,7 +17,8 @@
$(OPENMOKO_CFLAGS) \
$(OMP_DEFINES) \
-I$(top_srcdir) \
- -I$(top_srcdir)/intl
+ -I$(top_srcdir)/intl\
+ -g -DDEBUG
INCLUDES = $(openmoko_mediaplayer_CFLAGS)
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.c 2007-08-04 12:50:34 UTC (rev 2631)
@@ -140,6 +140,10 @@
void
omp_config_restore_state()
{
+ #ifdef DEBUG
+ g_print("Loading playlist and restoring playback state\n");
+ #endif
+
// This mustn't be called more than once
g_assert(omp_config == NULL);
@@ -158,10 +162,11 @@
// Check whether playlist_position is valid
if (!omp_playlist_set_current_track(omp_config->playlist_position))
{
- // Reset playlist state as it must have been modified since it was last loaded
+ // Reset playlist state as playlist must have been modified since it was last loaded
omp_config->playlist_position = 0;
omp_config->track_position = 0;
- }
+ omp_playlist_set_current_track(0);
+ }
// Feed the track entity to the playback engine to obtain track information
omp_playlist_load_current_track();
@@ -362,15 +367,12 @@
signal(SIGSEGV, handler_sigsegfault);
signal(SIGUSR1, handler_sigusr1);
- // Load config and restore playback state
- omp_config_restore_state();
-
// Initialize playback, playlist and UI handling
omp_main_window_create();
omp_playback_init();
omp_playlist_init();
omp_main_connect_signals();
- omp_main_update_track_info();
+ omp_config_restore_state();
omp_main_window_show();
gtk_main();
@@ -384,6 +386,7 @@
omp_playback_free();
omp_playlist_free();
gst_deinit();
+ g_free(ui_image_path);
#ifdef DEBUG_MEM_PROFILE
g_mem_profile();
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/main.h 2007-08-04 12:50:34 UTC (rev 2631)
@@ -52,7 +52,7 @@
// gchar *playlist_path; ///< Last path used for the playlist selection dialog
gchar playlist_file[256]; ///< Path and file name of current (=last used) playlist
gint playlist_position; ///< Position within the playlist
- gint track_position; ///< Position to resume playback from within the last played track
+ glong track_position; ///< Position to resume playback from within the last played track
};
extern struct _omp_config *omp_config;
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.c 2007-08-04 12:50:34 UTC (rev 2631)
@@ -59,6 +59,8 @@
GtkWidget *omp_main_window = NULL;
+gboolean omp_main_time_slider_can_update = TRUE;
+gboolean omp_main_time_slider_was_dragged = FALSE;
/**
@@ -67,9 +69,6 @@
void
omp_application_terminate()
{
- // Free resources
- g_free(ui_image_path);
-
// Tell GTK to leave the message loop
gtk_main_quit();
}
@@ -190,7 +189,52 @@
gtk_label_set_text(GTK_LABEL(main_widgets.title_label), title);
}
+/**
+ * Gets called when the time slider's value got changed (yes, that means it gets called every second, too)
+ */
void
+omp_main_time_slider_changed(GtkRange *range, gpointer data)
+{
+ if (omp_main_time_slider_was_dragged)
+ {
+ omp_main_time_slider_was_dragged = FALSE;
+
+ // Set new position and resume playback that was paused when dragging started
+ omp_playback_set_track_position(gtk_range_get_value(GTK_RANGE(range)));
+
+ // Update UI right away
+ gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position());
+ }
+}
+
+/**
+ * Gets called when the user starts dragging the time slider
+ */
+gboolean
+omp_main_time_slider_drag_start(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ while (gtk_events_pending()) gtk_main_iteration();
+
+ // Prevent UI callbacks from messing with the slider position
+ omp_main_time_slider_can_update = FALSE;
+}
+
+/**
+ * Gets called when the user stops dragging the time slider
+ */
+gboolean
+omp_main_time_slider_drag_stop(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ while (gtk_events_pending()) gtk_main_iteration();
+
+ // Allow UI callbacks to alter the the slider position again
+ omp_main_time_slider_can_update = TRUE;
+
+ // Notify the slider change callback that this time we indeed want to change position
+ omp_main_time_slider_was_dragged = TRUE;
+}
+
+void
omp_shuffle_button_callback(GtkWidget* widget, gpointer data)
{
/* if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
@@ -225,13 +269,46 @@
}
/**
+ * Event handler for the Fast Forward button
+ */
+void
+omp_main_button_fast_forward_callback()
+{
+ // Set new position and resume playback that was paused when dragging started
+ omp_playback_set_track_position(omp_playback_get_track_position()+BUTTON_SEEK_DISTANCE);
+
+ // Update UI right away
+ gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position());
+}
+
+/**
+ * Event handler for the Rewind button
+ */
+void
+omp_main_button_rewind_callback()
+{
+ // Set new position and resume playback that was paused when dragging started
+ omp_playback_set_track_position(omp_playback_get_track_position()-BUTTON_SEEK_DISTANCE);
+
+ // Update UI right away
+ gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), omp_playback_get_track_position());
+}
+
+/**
* Event handler for the Play/Pause button
- * @todo State change, etc
+ * @todo Pixmap change
*/
void
omp_main_button_play_pause_callback()
{
- omp_playback_play();
+ if (omp_playback_get_state() != OMP_PLAYBACK_STATE_PLAYING)
+ {
+ omp_playback_play();
+
+ } else {
+
+ omp_playback_pause();
+ }
}
/**
@@ -282,7 +359,6 @@
image = gtk_image_new_from_icon_name(image_name, 36);
gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(image));
- g_object_unref(image);
return button;
}
@@ -388,9 +464,11 @@
gtk_scale_set_draw_value(GTK_SCALE(main_widgets.time_hscale), FALSE);
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(main_widgets.time_hscale), GTK_CAN_FOCUS);
gtk_widget_set_size_request(GTK_WIDGET(main_widgets.time_hscale), 338, 35);
+ gtk_range_set_update_policy(GTK_RANGE(main_widgets.time_hscale), GTK_UPDATE_DISCONTINUOUS);
gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), 0.0);
-// g_signal_connect(G_OBJECT(time_hscale), "change_value",
-// G_CALLBACK(omp_main_set_time), NULL);
+ g_signal_connect(G_OBJECT(main_widgets.time_hscale), "value_changed", G_CALLBACK(omp_main_time_slider_changed), NULL);
+ g_signal_connect(G_OBJECT(main_widgets.time_hscale), "button-press-event", G_CALLBACK(omp_main_time_slider_drag_start), NULL);
+ g_signal_connect(G_OBJECT(main_widgets.time_hscale), "button-release-event", G_CALLBACK(omp_main_time_slider_drag_stop), NULL);
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(main_widgets.time_hscale));
// --- --- --- --- --- Middle hbox --- --- --- --- ---
@@ -483,7 +561,7 @@
gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START);
// Rewind button
- button = omp_button_create("gtk-media-rewind-ltr", NULL);
+ button = omp_button_create("gtk-media-rewind-ltr", G_CALLBACK(omp_main_button_rewind_callback));
gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START);
@@ -493,7 +571,7 @@
gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START);
// Fast Forward button
- button = omp_button_create("gtk-media-forward-ltr", NULL);
+ button = omp_button_create("gtk-media-forward-ltr", G_CALLBACK(omp_main_button_fast_forward_callback));
gtk_box_pack_start(GTK_BOX(controls_hbox), button, TRUE, TRUE, 0);
gtk_box_set_child_packing(GTK_BOX(controls_hbox), GTK_WIDGET(button), FALSE, FALSE, 0, GTK_PACK_START);
@@ -536,6 +614,7 @@
// Show everything but the window itself
gtk_widget_show_all(GTK_WIDGET(bg_muxer));
+
return;
}
@@ -547,20 +626,23 @@
void
omp_main_connect_signals()
{
- g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PREV_TRACK, G_CALLBACK(omp_main_update_track_info), NULL);
- g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_NEXT_TRACK, G_CALLBACK(omp_main_update_track_info), NULL);
+ g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED, G_CALLBACK(omp_main_update_track_change), NULL);
+ g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED, G_CALLBACK(omp_main_update_track_change), NULL);
+ g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED, G_CALLBACK(omp_main_update_track_position), NULL);
}
-
/**
* Evaluates current track information and updates the config/UI if necessary
+ * @note This function only checks elements that don't change too often - for the rest we have specialized functions below
*/
void
-omp_main_update_track_info()
+omp_main_update_track_change()
{
static gint old_track_count = 0;
static gint old_track_id = 0;
+ static gulong old_track_length = 0;
+ gulong track_length, track_position;
gchar *text;
// Track id/track count changed?
@@ -572,12 +654,68 @@
// Update config
omp_config_update();
- // Update UI
+ // Update label
text = g_strdup_printf(WIDGET_CAPTION_TRACK_NUM, omp_playlist_current_track_id+1, omp_playlist_track_count);
gtk_label_set_text(GTK_LABEL(main_widgets.track_number_label), text);
g_free(text);
}
+ // Got a track length change?
+ track_length = omp_playback_get_track_length();
+ if (track_length != old_track_length)
+ {
+ old_track_length = track_length;
+ track_position = omp_playback_get_track_position();
+
+ // Set new time slider increments
+ gtk_range_set_increments(GTK_RANGE(main_widgets.time_hscale), track_length/10, track_length/10);
+
+ // Update label and slider
+ text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME,
+ track_position / 60, track_position % 60,
+ track_length / 60, track_length % 60);
+ gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text);
+ g_free(text);
+
+ if (omp_main_time_slider_can_update)
+ {
+ gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? track_length : 1);
+ gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position);
+ }
+ }
}
+/**
+ * Updates the UI if the playback position changed
+ */
+void
+omp_main_update_track_position()
+{
+ static gulong old_track_position = 0;
+
+ gulong track_position, track_length;
+ gchar *text;
+
+ // Got a track length change?
+ track_position = omp_playback_get_track_position();
+ {
+ old_track_position = track_position;
+ track_length = omp_playback_get_track_length();
+
+ // Update UI
+ text = g_strdup_printf(WIDGET_CAPTION_TRACK_TIME,
+ track_position / 60, track_position % 60,
+ track_length / 60, track_length % 60);
+ gtk_label_set_text(GTK_LABEL(main_widgets.time_label), text);
+ g_free(text);
+
+ if (omp_main_time_slider_can_update)
+ {
+ gtk_range_set_range(GTK_RANGE(main_widgets.time_hscale), 0, track_length ? track_length : 1);
+ gtk_range_set_value(GTK_RANGE(main_widgets.time_hscale), track_position);
+ }
+ }
+
+}
+
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/mainwin.h 2007-08-04 12:50:34 UTC (rev 2631)
@@ -33,6 +33,9 @@
#define WIDGET_CAPTION_TRACK_NUM "%.3d / %.3d"
#define WIDGET_CAPTION_VOLUME "%d%%"
+// Determines how many seconds the engine will seek if the FFWD/REW buttons are clicked
+#define BUTTON_SEEK_DISTANCE 10
+
extern GtkWidget *omp_main_window;
void omp_application_terminate();
@@ -42,6 +45,7 @@
void omp_main_window_create();
void omp_main_connect_signals();
-void omp_main_update_track_info();
+void omp_main_update_track_change();
+void omp_main_update_track_position();
#endif
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.c 2007-08-04 12:50:34 UTC (rev 2631)
@@ -30,9 +30,9 @@
#include "mainwin.h"
GstElement *omp_gst_playbin = NULL;
+guint omp_playback_ui_timeout = 0;
+gboolean omp_playback_ui_timeout_halted;
-
-
/**
* Initializes gstreamer by setting up pipe, message hooks and bins
*/
@@ -48,7 +48,9 @@
}
// Create the signals we'll emit
- g_signal_new(OMP_EVENT_PLAYBACK_EOS, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+ g_signal_new(OMP_EVENT_PLAYBACK_EOS, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+ 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);
+ 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);
// Set up gstreamer pipe and bins
omp_gst_playbin = gst_element_factory_make("playbin", "play");
@@ -81,6 +83,7 @@
/**
* Attempts to load a track from an URI
+ * @return TRUE if successful, FALSE if failed
*/
gboolean
omp_playback_load_track_from_uri(gchar *uri)
@@ -91,59 +94,171 @@
omp_playback_init();
}
- // DEBUG
- g_printf("Loading %s\n", uri);
+ #ifdef DEBUG
+ g_printf("Loading track: %s\n", uri);
+ #endif
gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
g_object_set(G_OBJECT(omp_gst_playbin), "uri", uri, NULL);
gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED);
+
+ return (gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE);
}
/**
+ * This callback gets called at least once per second if a track is playing
+ */
+static gboolean
+omp_playback_ui_timeout_callback(gpointer data)
+{
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED);
+
+ if (omp_playback_ui_timeout_halted)
+ {
+ // Reset the timeout ID so we can prevent race conditions
+ omp_playback_ui_timeout = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* Starts playback of the current stream
*/
void
omp_playback_play()
{
- // DEBUG
- g_print("Starting playback\n");
+ #ifdef DEBUG
+ g_print("Starting playback\n");
+ #endif
+ // Set state
gst_element_set_state(omp_gst_playbin, GST_STATE_PLAYING);
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED);
+
+ // Add timer to update UI if necessary
+ // If the halt flag was set but the callback didn't run yet then we
+ // don't want to add another callback since we would have two then
+ omp_playback_ui_timeout_halted = FALSE;
+
+ if (!omp_playback_ui_timeout)
+ {
+ omp_playback_ui_timeout = g_timeout_add(PLAYBACK_UI_UPDATE_INTERVAL, omp_playback_ui_timeout_callback, NULL);
+ }
}
/**
+ * Suspends playback of the current stream
+ */
+void
+omp_playback_pause()
+{
+ #ifdef DEBUG
+ g_print("Suspending playback\n");
+ #endif
+
+ // Set state
+ gst_element_set_state(omp_gst_playbin, GST_STATE_PAUSED);
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_STATUS_CHANGED);
+
+ // Stop timer
+ omp_playback_ui_timeout_halted = TRUE;
+}
+
+/**
* Returns the current state the playback engine is in
+ * @todo Don't use system clock, might be out-of-sync with playbin clock?
*/
gint
omp_playback_get_state()
{
GstState state;
- GstSystemClock *system_clock;
+ GstClock *clock;
// Poll state with an immediate timeout
- system_clock = gst_system_clock_obtain();
- gst_element_get_state(GST_OBJECT(omp_gst_playbin), &state, NULL, gst_clock_get_time(system_clock));
- gst_object_unref(system_clock);
+ clock = gst_system_clock_obtain();
+ gst_element_get_state(GST_ELEMENT(omp_gst_playbin), &state, NULL, gst_clock_get_time(clock));
+ gst_object_unref(clock);
- // The NULL element state is no different from READY for more abstract layers
- if (state == GST_STATE_NULL)
+ // The NULL and READY element states are no different from PAUSED for more abstract layers
+ if ( (state == GST_STATE_NULL) || (state == GST_STATE_READY) )
{
- state = GST_STATE_READY;
+ state = GST_STATE_PAUSED;
}
return (gint)state;
}
/**
+ * Returns the number of seconds that the track has been playing so far
+ */
+gulong
+omp_playback_get_track_position()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position;
+
+ if (!omp_gst_playbin)
+ {
+ return 0;
+ }
+
+ // Return 0 if function returns FALSE, position otherwise
+ return (gst_element_query_position(omp_gst_playbin, &format, &position)) ? (position/GST_SECOND) : 0;
+}
+
+/**
+ * Sets the playback position of the currently loaded track
+ */
+void
+omp_playback_set_track_position(glong position)
+{
+ if (!omp_gst_playbin)
+ {
+ return;
+ }
+
+ gst_element_seek_simple(GST_ELEMENT(omp_gst_playbin),
+ GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
+ position*GST_SECOND);
+
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_POSITION_CHANGED);
+}
+
+/**
+ * Returns the current track's playing length
+ */
+gulong
+omp_playback_get_track_length()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 length;
+
+ if (!omp_gst_playbin)
+ {
+ return 0;
+ }
+
+ // Return 0 if function returns FALSE, track length otherwise
+ return (gst_element_query_duration(omp_gst_playbin, &format, &length)) ? (length/GST_SECOND) : 0;
+}
+
+/**
* Handles gstreamer's end-of-stream notification
*/
static gboolean
omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer data)
{
- // DEBUG
- g_printf("End of stream reached.\n");
+ #ifdef DEBUG
+ g_printf("End of stream reached.\n");
+ #endif
- gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
+ // Reset playback engine
+ gst_element_set_state(omp_gst_playbin, GST_STATE_READY);
+ omp_playback_set_track_position(0);
+
g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_EOS);
return TRUE;
@@ -157,9 +272,12 @@
{
GError *error;
- gst_message_parse_error(message, &error, NULL);
- g_printerr("gstreamer error: %s\n", error->message);
- g_error_free(error);
+ #ifdef DEBUG
+ gst_message_parse_error(message, &error, NULL);
+ g_printerr("gstreamer error: %s\n", error->message);
+ gst_message_unref(error);
+ g_error_free(error);
+ #endif
return TRUE;
}
@@ -172,10 +290,12 @@
{
GError *error;
- gst_message_parse_error(message, &error, NULL);
- g_printerr("gstreamer warning: %s\n", error->message);
- g_error_free(error);
+ #ifdef DEBUG
+ gst_message_parse_warning(message, &error, NULL);
+ g_printerr("gstreamer warning: %s\n", error->message);
+ gst_message_unref(error);
+ g_error_free(error);
+ #endif
return TRUE;
}
-
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playback.h 2007-08-04 12:50:34 UTC (rev 2631)
@@ -30,12 +30,15 @@
#include <gst/gst.h>
#define OMP_EVENT_PLAYBACK_EOS "playback_end_of_stream"
+#define OMP_EVENT_PLAYBACK_STATUS_CHANGED "playback_status_change"
+#define OMP_EVENT_PLAYBACK_POSITION_CHANGED "playback_position_change"
// Player states masking the gstreamer states so we can be more abstract
-#define OMP_PLAYBACK_STATE_READY GST_STATE_READY
#define OMP_PLAYBACK_STATE_PAUSED GST_STATE_PAUSED
#define OMP_PLAYBACK_STATE_PLAYING GST_STATE_PLAYING
+// The UI will be updated at this interval when a track is playing (in ms)
+#define PLAYBACK_UI_UPDATE_INTERVAL 1000
void omp_playback_init();
void omp_playback_free();
@@ -43,7 +46,11 @@
gboolean omp_playback_load_track_from_uri(gchar *uri);
void omp_playback_play();
+void omp_playback_pause();
gint omp_playback_get_state();
+gulong omp_playback_get_track_position();
+void omp_playback_set_track_position(glong position);
+gulong omp_playback_get_track_length();
static gboolean omp_gst_message_eos(GstBus *bus, GstMessage *message, gpointer data);
static gboolean omp_gst_message_error(GstBus *bus, GstMessage *message, gpointer data);
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.c 2007-08-04 12:50:34 UTC (rev 2631)
@@ -62,8 +62,7 @@
g_signal_connect(G_OBJECT(omp_main_window), OMP_EVENT_PLAYBACK_EOS, G_CALLBACK(omp_playlist_process_eos_event), NULL);
// Create the signals we emit: no params, no return value
- g_signal_new(OMP_EVENT_PREV_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
- g_signal_new(OMP_EVENT_NEXT_TRACK, G_TYPE_OBJECT, 0, 0, 0, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
+ 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);
}
/**
@@ -93,6 +92,14 @@
void
omp_playlist_load(gchar *playlist_file)
{
+ // Free the track history's memory by deleting the first element until the list is empty
+ while (omp_track_history)
+ {
+ g_free(omp_track_history->data);
+ omp_track_history = g_slist_delete_link(omp_track_history, omp_track_history);
+ }
+
+ // Let XSPF clean up, too
if (omp_playlist)
{
spiff_free(omp_playlist);
@@ -124,8 +131,9 @@
struct spiff_track *track;
gint track_num = 0;
- // DEBUG
- g_printf("Setting current track to #%d\n", playlist_pos);
+ #ifdef DEBUG
+ g_printf("Setting current track to #%d\n", playlist_pos);
+ #endif
if (!omp_playlist)
{
@@ -146,6 +154,9 @@
if (position_valid)
{
omp_playlist_track_count = track_num;
+
+ // Emit signal to update UI and the like
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED);
}
return position_valid;
@@ -161,6 +172,7 @@
{
struct omp_track_history_entry *history_entry;
struct spiff_track *track;
+ gboolean was_playing;
gboolean is_new_track = FALSE;
if (!omp_playlist_current_track)
@@ -168,6 +180,34 @@
return;
}
+ // If track playing time is >= 10 seconds we just jump back to the beginning of the track
+ if (omp_playback_get_track_position() >= 10)
+ {
+ omp_playback_set_track_position(0);
+ return TRUE;
+ }
+
+ // Get player state so we can continue playback if necessary
+ was_playing = (omp_playback_get_state() == OMP_PLAYBACK_STATE_PLAYING);
+
+try_again:
+
+ #ifdef DEBUG
+ if (omp_track_history)
+ {
+ GSList *list;
+ g_printf("--- Track History:\n");
+ list = omp_track_history;
+ while (list)
+ {
+ history_entry = list->data;
+ g_printf("- %s\n", history_entry->track->locations->value);
+ list = g_slist_next(list);
+ }
+ g_printf("---\n");
+ }
+ #endif
+
// Do we have tracks in the history to go back to?
if (omp_track_history)
{
@@ -197,7 +237,7 @@
// We only found the previous track if we're not at the end of the list
if (track->next)
{
- omp_playlist_current_track = track;
+ omp_playlist_current_track = track;
omp_playlist_current_track_id--;
}
}
@@ -206,7 +246,19 @@
if (is_new_track)
{
// Emit signal to update UI and the like
- g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PREV_TRACK);
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED);
+
+ // Load track and start playing if needed
+ if (omp_playlist_load_current_track())
+ {
+ if (was_playing) omp_playback_play();
+
+ } else {
+
+ // Uh-oh, track failed to load - let's find another one, shall we?
+ is_new_track = FALSE;
+ goto try_again;
+ }
}
return is_new_track;
@@ -237,8 +289,8 @@
// Prepare the history entry - if we don't need it we'll just free it again
history_entry = g_new(struct omp_track_history_entry, 1);
- history_entry->track = omp_playlist_current_track;
- history_entry->track_id = omp_playlist_current_track_id;
+ history_entry->track = omp_playlist_current_track;
+ history_entry->track_id = omp_playlist_current_track_id;
// Do we have a track to play?
if (omp_playlist_current_track->next)
@@ -256,7 +308,7 @@
omp_track_history = g_slist_prepend(omp_track_history, (gpointer)history_entry);
// Emit signal to update UI and the like
- g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_NEXT_TRACK);
+ g_signal_emit_by_name(G_OBJECT(omp_main_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED);
// Load track and start playing if needed
if (omp_playlist_load_current_track())
Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h 2007-08-04 10:36:33 UTC (rev 2630)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer/src/playlist.h 2007-08-04 12:50:34 UTC (rev 2631)
@@ -29,13 +29,8 @@
#include <spiff/spiff_c.h>
-#define OMP_EVENT_PREV_TRACK "prev_track"
-#define OMP_EVENT_NEXT_TRACK "next_track"
+#define OMP_EVENT_PLAYLIST_TRACK_CHANGED "playlist_track_changed"
-
-extern struct _omp_playlist_events omp_playlist_events;
-
-
extern struct spiff_list *omp_playlist;
extern guint omp_playlist_track_count;
More information about the commitlog
mailing list