r2771 - in trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2: images src

abraxa at sita.openmoko.org abraxa at sita.openmoko.org
Wed Aug 22 09:34:23 CEST 2007


Author: abraxa
Date: 2007-08-22 09:34:10 +0200 (Wed, 22 Aug 2007)
New Revision: 2771

Added:
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-all.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-current.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-off.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-once.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle-off.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle-on.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ind-music-eq-00.png
Removed:
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-list.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat.png
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle.png
Modified:
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/Makefile.am
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/editor_page.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main_page.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h
   trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist_page.c
Log:
Added shuffle/repeat modes
Added stereo balance UI, despite lack of gstreamer support for it
Various UI/backend improvements



Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/Makefile.am
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/Makefile.am	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/Makefile.am	2007-08-22 07:34:10 UTC (rev 2771)
@@ -6,10 +6,16 @@
 	btn-white-p.png \
 	ico-track.png \
 	ico-time.png \
-	ico-repeat.png \
-	ico-shuffle.png \
-	ico-list.png \
+	ico-repeat-off.png \
+	ico-repeat-once.png \
+	ico-repeat-current.png \
+	ico-repeat-all.png \
+	ico-shuffle-on.png \
+	ico-shuffle-off.png \
+	ico-balance-left.png \
+	ico-balance-right.png \
 	ico-tracktype-general.png \
+	ind-music-eq-00.png \
 	ind-music-eq-01.png \
 	ind-music-eq-02.png \
 	ind-music-eq-03.png \

Deleted: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-list.png
===================================================================
(Binary files differ)

Added: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-all.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-all.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-current.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-current.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Copied: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-off.png (from rev 2637, trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat.png)

Added: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-once.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat-once.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-repeat.png
===================================================================
(Binary files differ)

Copied: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle-off.png (from rev 2637, trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle.png)

Added: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle-on.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle-on.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ico-shuffle.png
===================================================================
(Binary files differ)

Added: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ind-music-eq-00.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/images/ind-music-eq-00.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/editor_page.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/editor_page.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/editor_page.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -231,7 +231,7 @@
 	main_vbox = gtk_vbox_new(FALSE, 0);
 
 	// Caption
-	alignment = create_label(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 5, 5, 5);
 	gtk_box_pack_start(GTK_BOX(main_vbox), GTK_WIDGET(alignment), FALSE, FALSE, 0);
 	omp_editor_title_label = label;
@@ -256,7 +256,7 @@
 	image = gtk_image_new_from_icon_name("gtk-file", BUTTON_PIXMAP_SIZE);
 	gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(image), TRUE, TRUE, 0);
 
-	alignment = create_label(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_label_set_text(GTK_LABEL(label), _("Add Tracks"));
 	gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -69,8 +69,8 @@
  * @param yscale Vertical expansion (0..1)
  * @note See gtk_alignment_new() for further info
  */
-GtkWidget*
-create_label(GtkWidget **label, gchar *font_info, gchar *color_desc,
+GtkWidget *
+label_create(GtkWidget **label, gchar *font_info, gchar *color_desc,
 	gfloat xalign, gfloat yalign, gfloat xscale, gfloat yscale,
 	gint max_char_count)
 {
@@ -100,6 +100,35 @@
 }
 
 /**
+ * Creates a button containing an image
+ * @param image_name Path and file name of the image to use
+ * @param image Destination for the image's handle (can be NULL)
+ * @param callback Callback to set
+ * @return The button
+ */
+GtkWidget *
+button_create_with_image(gchar *image_name, GtkWidget **image, GCallback callback)
+{
+	GtkWidget *btn_image, *button;
+	gchar *image_file_name;
+
+	button = gtk_button_new();
+	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(callback), NULL);
+	GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
+
+//	g_object_set(G_OBJECT(*button), "xalign", (gfloat)0.37, "yalign", (gfloat)0.37, NULL);
+
+	image_file_name = g_build_path("/", ui_image_path, image_name, NULL);
+	btn_image = gtk_image_new_from_file(image_file_name);
+	g_free(image_file_name);
+	gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(btn_image));
+
+	if (image) *image = btn_image;
+
+	return button;
+}
+
+/**
  * Loads an image from disk and adds it to a given container, returning a reference to the image as well
  */
 void
@@ -123,12 +152,11 @@
 	container_add_image_with_ref(container, image_name, &image);
 }
 
-
 /**
  * Adds a child to a GtkNotebook, filling the page handle with a stock icon
  */
 void
-omp_notebook_add_page_with_icon(GtkWidget *notebook, GtkWidget *child, const gchar *icon_name, int padding)
+notebook_add_page_with_icon(GtkWidget *notebook, GtkWidget *child, const gchar *icon_name, int padding)
 {
 	GtkWidget *icon, *alignment;
 

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.h	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/guitools.h	2007-08-22 07:34:10 UTC (rev 2771)
@@ -34,12 +34,14 @@
 extern gchar *ui_image_path;
 
 GdkPixbuf *pixbuf_new_from_file(const gchar* file_name);
-GtkWidget *create_label(GtkWidget **label, gchar *font_info, gchar *color_desc, gfloat xalign, gfloat yalign, gfloat xscale, gfloat yscale, gint max_char_count);
+
+GtkWidget *label_create(GtkWidget **label, gchar *font_info, gchar *color_desc,
+	gfloat xalign, gfloat yalign, gfloat xscale, gfloat yscale, gint max_char_count);
+GtkWidget *button_create_with_image(gchar *image_name, GtkWidget **image, GCallback callback);
+
+void container_add_image_with_ref(GtkContainer *container, gchar *image_name, GtkWidget **image);
 void container_add_image(GtkContainer *container, gchar *image_name);
-void container_add_image_with_ref(GtkContainer *container, gchar *image_name, GtkWidget **image);
 
-// These are for the main window's notebook used to switch UI pages
-void omp_notebook_add_page_with_icon(GtkWidget *notebook, GtkWidget *child, const gchar *icon_name, int padding);
+void notebook_add_page_with_icon(GtkWidget *notebook, GtkWidget *child, const gchar *icon_name, int padding);
 
-
 #endif

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -62,7 +62,7 @@
 //define DEBUG_MEM_PROFILE
 
 // Forces the window to the native size of the Neo1973's screen area if enabled
-//define EMULATE_SIZE
+#define EMULATE_SIZE
 
 // The padding applied to the page handle's contents
 #define NOTEBOOK_PAGE_PADDING 6
@@ -248,24 +248,24 @@
 
 	// Add main page
 	page = omp_main_page_create();
-	omp_notebook_add_page_with_icon(omp_notebook, page,
+	notebook_add_page_with_icon(omp_notebook, page,
 		MOKO_STOCK_SPEAKER, NOTEBOOK_PAGE_PADDING);
 	omp_notebook_tab_ids->main = page_id++;
 	omp_notebook_tabs->main = page;
 
 	// Add playlist page
 	page = omp_playlist_page_create();
-	omp_notebook_add_page_with_icon(omp_notebook, page,
+	notebook_add_page_with_icon(omp_notebook, page,
 		MOKO_STOCK_VIEW, NOTEBOOK_PAGE_PADDING);
 	omp_notebook_tab_ids->playlists = page_id++;
 	omp_notebook_tabs->playlists = page;
 
 	// Add playlist editor page
-/*	page = omp_editor_page_create();
-	omp_notebook_add_page_with_icon(omp_notebook, page,
+	page = omp_editor_page_create();
+	notebook_add_page_with_icon(omp_notebook, page,
 		"gtk-index", NOTEBOOK_PAGE_PADDING);
 	omp_notebook_tab_ids->editor = page_id++;
-	omp_notebook_tabs->editor = page; */
+	omp_notebook_tabs->editor = page;
 }
 
 /**

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main_page.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main_page.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/main_page.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -38,6 +38,7 @@
 #include "guitools.h"
 #include "playlist.h"
 #include "playback.h"
+#include "persistent.h"
 
 /// Contains all main window widgets that need to be changeable
 struct _main_widgets
@@ -52,9 +53,8 @@
 	GtkWidget *volume_label;
 	GtkWidget *balance_image;
 	GtkWidget *play_pause_button_image;
-	GtkWidget *shuffle_button;
-	GtkWidget *repeat_button;
-	GtkWidget *playlist_button;
+	GtkWidget *shuffle_button_image;
+	GtkWidget *repeat_button_image;
 	GtkWidget *volume_hscale;
 } main_widgets;
 
@@ -65,6 +65,8 @@
 
 // Forward declarations for internal use
 void omp_main_update_track_change(gpointer instance, gpointer user_data);
+void omp_main_update_shuffle_state(gpointer instance, gboolean state, gpointer user_data);
+void omp_main_update_repeat_mode(gpointer instance, guint mode, gpointer user_data);
 void omp_main_update_status_change(gpointer instance, gpointer user_data);
 void omp_main_update_track_position(gpointer instance, gpointer user_data);
 void omp_main_update_volume(gpointer instance, gpointer user_data);
@@ -74,40 +76,43 @@
 
 
 /**
- * Updates the UI volume display
- * @param vol Volume to show, in percent
+ * Creates a button with a stock pixmap and returns it
+ * @param image_name The name of the image resource to use, not a file name
+ * @return The button
  */
-void
-omp_change_vol_img(gint vol)
+GtkWidget *
+omp_stock_button_create(gchar *image_name, GtkWidget **image, GCallback callback)
 {
-	// Sanity checks
-	if ( (vol < 0) || (vol > 100) )
-		g_printerr("Warning: volume passed to omp_change_vol_img() out of bounds\n");
+	GtkWidget *button;
 
-	if (vol < 0) vol = 0;
-	if (vol > 100) vol = 100;
+	button = gtk_button_new();
+	gtk_widget_set_size_request(GTK_WIDGET(button), 66, 66);
+	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(callback), NULL);
+	GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
 
-	gchar *image_file_name = g_strdup_printf("%s/ind-music-volume-%02d.png", ui_image_path, vol/10);
-	gtk_image_set_from_file(GTK_IMAGE(main_widgets.volume_image), image_file_name);
+	g_object_set(G_OBJECT(button), "xalign", (gfloat)0.37, "yalign", (gfloat)0.37, NULL);
 
-	g_free(image_file_name);
+	*image = gtk_image_new_from_icon_name(image_name, BUTTON_PIXMAP_SIZE);
+	gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(*image));
+
+	return button;
 }
 
 /**
  * Sets a desired EQ/visualization band to a new level
  * @param pos Band to change (0..11)
- * @param h Level to set (0..15, anything higher gets capped)
- * @note The switch is supposed to make the levels pseudo-logarithmic?
+ * @param level Level to set (0..15, anything higher gets capped)
  */
 void
-omp_update_band(gint pos, gint level)
+omp_main_band_set(guint pos, guint level)
 {
+	gchar *image_file_name;
+
 	// Sanity checks
-	g_return_if_fail( (pos < 0) && (pos > 11) );
-	g_return_if_fail(level > -1);
+	g_return_if_fail(pos < 12);
 
 	// Pseudo-logarithmize the value
-	gint value = 0;
+	guint value = 0;
 
 	switch (level)
 	{
@@ -144,7 +149,6 @@
 	}
 
 	// Determine file name of the new image to use and apply it
-	gchar *image_file_name = NULL;
 	image_file_name = g_strdup_printf("%s/ind-music-eq-%02d.png", ui_image_path, value);
 
 	gtk_image_set_from_file(GTK_IMAGE(main_widgets.band_image[pos]), image_file_name);
@@ -153,36 +157,6 @@
 }
 
 /**
- * Set artist label [Mockup arrow #1 - upper line]
- */
-void
-omp_set_artist(const gchar *artist)
-{
-	if (!artist)
-	{
-		gtk_label_set_text(GTK_LABEL(main_widgets.artist_label), "Unknown Artist");
-		return;
-	}
-
-	gtk_label_set_text(GTK_LABEL(main_widgets.artist_label), artist);
-}
-
-/**
- * Set title label [Mockup arrow #1 - lower line]
- */
-void
-omp_set_title(const gchar *title)
-{
-	if (!title)
-	{
-		gtk_label_set_text(GTK_LABEL(main_widgets.title_label), "Unknown Title");
-		return;
-	}
-
-	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 at least once per second)
  */
 void
@@ -228,28 +202,58 @@
 }
 
 /**
- * Event handler for the Shuffle button
+ * Event handler for the "balance left" button
+ * @todo Figure out how to set balance with gstreamer
  */
 void
-omp_shuffle_button_callback(GtkWidget *widget, gpointer data)
+omp_main_balance_left_clicked(GtkWidget *widget, gpointer data)
 {
 	// ...
 }
 
 /**
- * Event handler for the Repeat button
+ * Event handler for the "balance right" button
+ * @todo Figure out how to set balance with gstreamer
  */
 void
-omp_repeat_button_callback(GtkWidget *widget, gpointer data)
+omp_main_balance_right_clicked(GtkWidget *widget, gpointer data)
 {
 	// ...
 }
 
 /**
+ * Event handler for the Shuffle button
+ */
+void
+omp_main_shuffle_clicked(GtkWidget *widget, gpointer data)
+{
+	omp_config_set_shuffle_state(!omp_config_get_shuffle_state());
+}
+
+/**
+ * Event handler for the Repeat button
+ */
+void
+omp_main_repeat_clicked(GtkWidget *widget, gpointer data)
+{
+	guint mode;
+
+	// Cycle through all available modes
+	mode = omp_config_get_repeat_mode()+1;
+
+	if (mode == OMP_REPEAT_COUNT)
+	{
+		mode = 0;
+	}
+
+	omp_config_set_repeat_mode(mode);
+}
+
+/**
  * Event handler for the Fast Forward button
  */
 void
-omp_main_button_fast_forward_callback(GtkWidget *widget, gpointer data)
+omp_main_fast_forward_clicked(GtkWidget *widget, gpointer data)
 {
 	// 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);
@@ -262,7 +266,7 @@
  * Event handler for the Rewind button
  */
 void
-omp_main_button_rewind_callback(GtkWidget *widget, gpointer data)
+omp_main_rewind_clicked(GtkWidget *widget, gpointer data)
 {
 	// 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);
@@ -275,7 +279,7 @@
  * Event handler for the Play/Pause button
  */
 void
-omp_main_button_play_pause_callback(GtkWidget *widget, gpointer data)
+omp_main_play_pause_clicked(GtkWidget *widget, gpointer data)
 {
 	if (omp_playback_get_state() != OMP_PLAYBACK_STATE_PLAYING)
 	{
@@ -320,59 +324,6 @@
 }
 
 /**
- * Creates a button framed by a GtkAlignment
- * @param image_name Path and file name of the image to use as pixmap
- * @return A GtkAlignment containing the button
- */
-GtkWidget *
-omp_button_create(gchar *image_name, gint pad_left, GCallback callback, GtkWidget **button)
-{
-	GtkWidget *image;
-	gchar *image_file_name;
-
-	GtkWidget *alignment = gtk_alignment_new(0, 0, 0, 0);
-	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, pad_left, 0);
-
-	*button = gtk_toggle_button_new();
-	gtk_widget_set_size_request(GTK_WIDGET(*button), 66, 66);
-	g_signal_connect(G_OBJECT(*button), "clicked", G_CALLBACK(callback), NULL);
-	GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(*button), GTK_CAN_FOCUS);
-	gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(*button));
-
-	g_object_set(G_OBJECT(*button), "xalign", (gfloat)0.37, "yalign", (gfloat)0.37, NULL);
-
-	image_file_name = g_build_path("/", ui_image_path, image_name, NULL);
-	image = gtk_image_new_from_file(image_file_name);
-	g_free(image_file_name);
-	gtk_container_add(GTK_CONTAINER(*button), GTK_WIDGET(image));
-
-	return alignment;
-}
-
-/**
- * Creates a button with a stock pixmap and returns it
- * @param image_name The name of the image resource to use, not a file name
- * @return The button
- */
-GtkWidget *
-omp_stock_button_create(gchar *image_name, GtkWidget **image, GCallback callback)
-{
-	GtkWidget *button;
-
-	button = gtk_button_new();
-	gtk_widget_set_size_request(GTK_WIDGET(button), 66, 66);
-	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(callback), NULL);
-	GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
-
-	g_object_set(G_OBJECT(button), "xalign", (gfloat)0.37, "yalign", (gfloat)0.37, NULL);
-
-	*image = gtk_image_new_from_icon_name(image_name, BUTTON_PIXMAP_SIZE);
-	gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(*image));
-
-	return button;
-}
-
-/**
  * Creates the main UI
  */
 void
@@ -392,12 +343,12 @@
 	gtk_container_add(GTK_CONTAINER(destination), GTK_WIDGET(mainvbox));
 
 	// Title label
-	alignment = create_label(&main_widgets.title_label, "Bitstream Vera Sans 24", "black", 0, 0, 1, 0, 18);
+	alignment = label_create(&main_widgets.title_label, "Sans 24", "black", 0, 0, 1, 0, 18);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 18, 0, 35, 30);
 	gtk_box_pack_start(GTK_BOX(mainvbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 
 	// Artist label
-	alignment = create_label(&main_widgets.artist_label, "Bitstream Vera Sans 14", "black", 0, 0, 1, 0, 30);
+	alignment = label_create(&main_widgets.artist_label, "Sans 14", "black", 0, 0, 1, 0, 30);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 0, 35, 30);
 	gtk_box_pack_start(GTK_BOX(mainvbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 
@@ -407,6 +358,7 @@
 	alignment = gtk_alignment_new(0, 0, 0, 0);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 20, 0, 50, 30);
 	gtk_box_pack_start(GTK_BOX(mainvbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
+
 	upper_hbox = gtk_hbox_new(FALSE, 0);
 	gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(upper_hbox));
 
@@ -417,7 +369,7 @@
 	container_add_image(GTK_CONTAINER(alignment), "ico-track.png");
 
 	// Track number
-	alignment = create_label(&main_widgets.track_number_label, "Bitstream Vera Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&main_widgets.track_number_label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_box_pack_start(GTK_BOX(upper_hbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 
 	// Time icon
@@ -427,7 +379,7 @@
 	container_add_image(GTK_CONTAINER(alignment), "ico-time.png");
 
 	// Time
-	alignment = create_label(&main_widgets.time_label, "Bitstream Vera Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&main_widgets.time_label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_box_pack_start(GTK_BOX(upper_hbox), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 
 	// --- --- --- --- --- Slider --- --- --- --- ---
@@ -442,9 +394,14 @@
 	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);
-	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);
+
+	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 --- --- --- --- ---
@@ -458,7 +415,7 @@
 	gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(middle_hbox));
 
 	// EQ/Visualization bands
-	image_file_name = g_build_path("/", ui_image_path, "ind-music-eq-12.png", NULL);
+	image_file_name = g_build_path("/", ui_image_path, "ind-music-eq-06.png", NULL);
 
 	for (i=0; i<12; i++)
 	{
@@ -486,7 +443,7 @@
 	container_add_image_with_ref(GTK_CONTAINER(alignment), "ind-music-volume-00.png", &main_widgets.volume_image);
 
 	// Volume label
-	alignment = create_label(&main_widgets.volume_label, "Sans 14", "darkorange", 0, 0, 1, 0, 0);
+	alignment = label_create(&main_widgets.volume_label, "Sans 14", "darkorange", 0, 0, 1, 0, 0);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 6, 0, 10, 0);
 	gtk_box_pack_start(GTK_BOX(volume_box), GTK_WIDGET(alignment), TRUE, TRUE, 0);
 	caption = g_strdup_printf(OMP_WIDGET_CAPTION_VOLUME, 0);
@@ -501,24 +458,38 @@
 
 	// --- --- --- --- --- Lower hbox --- --- --- --- ---
 
-	// Add lower hbox containing the three rectangular buttons
-	alignment = gtk_alignment_new(0, 0, 0, 0);
-	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 25, 0, 0, 0);
+	// Add lower hbox containing the shuffle/repeat/balance buttons
+	alignment = gtk_alignment_new(0, 0, 1, 0);
+	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 25, 0, 25, 0);
 	gtk_box_pack_start(GTK_BOX(mainvbox), alignment, TRUE, TRUE, 0);
+
 	lower_hbox = gtk_hbutton_box_new();
+	gtk_button_box_set_layout(GTK_BUTTON_BOX(lower_hbox), GTK_BUTTONBOX_SPREAD);
 	gtk_container_add(GTK_CONTAINER(alignment), lower_hbox);
 
+	// "balance left" button
+	button = button_create_with_image("ico-balance-left.png", NULL,
+		G_CALLBACK(omp_main_balance_left_clicked));
+	gtk_box_pack_start(GTK_BOX(lower_hbox), button, TRUE, TRUE, 0);
+
 	// Shuffle toggle button
-	alignment = omp_button_create("ico-shuffle.png", 108, G_CALLBACK(omp_shuffle_button_callback), &main_widgets.shuffle_button);
-	gtk_box_pack_start(GTK_BOX(lower_hbox), alignment, TRUE, TRUE, 0);
+	button = button_create_with_image("ico-shuffle.png",
+		&main_widgets.shuffle_button_image, G_CALLBACK(omp_main_shuffle_clicked));
+	gtk_box_pack_start(GTK_BOX(lower_hbox), button, TRUE, TRUE, 0);
 
 	// Repeat toggle button
-	alignment = omp_button_create("ico-repeat.png", 10, G_CALLBACK(omp_repeat_button_callback), &main_widgets.repeat_button);
-	gtk_box_pack_start(GTK_BOX(lower_hbox), alignment, TRUE, TRUE, 0);
+	button = button_create_with_image("ico-repeat.png",
+		&main_widgets.repeat_button_image, G_CALLBACK(omp_main_repeat_clicked));
+	gtk_box_pack_start(GTK_BOX(lower_hbox), button, TRUE, TRUE, 0);
+
+	// "balance right" button
+	button = button_create_with_image("ico-balance-right.png", NULL,
+		G_CALLBACK(omp_main_balance_right_clicked));
+	gtk_box_pack_start(GTK_BOX(lower_hbox), button, TRUE, TRUE, 0);
 }
 
 /**
- * Creates the widgets that didn't originally belong to the main UI
+ * Creates the widgets below the UI background image
  */
 void
 omp_main_secondary_widgets_create(GtkContainer *destination)
@@ -531,11 +502,11 @@
 	// Add mainvbox to destination container
 	mainvbox = gtk_vbox_new(FALSE, 0);
 	gtk_container_add(GTK_CONTAINER(destination), GTK_WIDGET(mainvbox));
-	gtk_widget_set_size_request(GTK_WIDGET(mainvbox), 480, -1);
 
 	// --- --- --- --- --- Player controls --- --- --- --- --- ---
 
 	alignment = gtk_alignment_new(0, 0, 1, 0);
+	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 25, 0);
 	gtk_box_pack_start(GTK_BOX(mainvbox), alignment, TRUE, TRUE, 0);
 
 	hbox = gtk_hbutton_box_new();
@@ -549,17 +520,17 @@
 
 	// Rewind button
 	button = omp_stock_button_create("gtk-media-rewind-ltr", &image,
-		G_CALLBACK(omp_main_button_rewind_callback));
+		G_CALLBACK(omp_main_rewind_clicked));
 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
 
 	// Play/Pause button
 	button = omp_stock_button_create("gtk-media-play-ltr", &main_widgets.play_pause_button_image,
-		G_CALLBACK(omp_main_button_play_pause_callback));
+		G_CALLBACK(omp_main_play_pause_clicked));
 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
 
 	// Fast Forward button
 	button = omp_stock_button_create("gtk-media-forward-ltr", &image,
-		G_CALLBACK(omp_main_button_fast_forward_callback));
+		G_CALLBACK(omp_main_fast_forward_clicked));
 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
 
 	// Next Track button
@@ -610,13 +581,22 @@
 
 	omp_main_reset_ui(NULL, NULL);
 
-	// Set up signal handlers
+
+	// Set up playlist signal handlers
 	g_signal_connect(G_OBJECT(omp_window), OMP_EVENT_PLAYLIST_TRACK_CHANGED,
 		G_CALLBACK(omp_main_update_track_change), NULL);
 
 	g_signal_connect(G_OBJECT(omp_window), OMP_EVENT_PLAYLIST_TRACK_COUNT_CHANGED,
 		G_CALLBACK(omp_main_update_track_change), NULL);
 
+	// Set up configuration signal handlers
+	g_signal_connect(G_OBJECT(omp_window), OMP_EVENT_CONFIG_SHUFFLE_STATE_CHANGED,
+		G_CALLBACK(omp_main_update_shuffle_state), NULL);
+
+	g_signal_connect(G_OBJECT(omp_window), OMP_EVENT_CONFIG_REPEAT_MODE_CHANGED,
+		G_CALLBACK(omp_main_update_repeat_mode), NULL);
+
+	// Set up playback signal handlers
 	g_signal_connect(G_OBJECT(omp_window), OMP_EVENT_PLAYBACK_RESET,
 		G_CALLBACK(omp_main_reset_ui), NULL);
 
@@ -643,7 +623,8 @@
 
 /**
  * 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
+ * @note This function only checks elements that don't change too often
+ * @note For the rest we have specialized functions below
  */
 void
 omp_main_update_track_change(gpointer instance, gpointer user_data)
@@ -657,7 +638,10 @@
 	gint track_id;
 
 	// Track id/track count changed?
-	if ( (omp_playlist_track_count != old_track_count) || (omp_playlist_current_track_id != old_track_id) )
+	if (
+			(omp_playlist_track_count != old_track_count) ||
+			(omp_playlist_current_track_id != old_track_id)
+		 )
 	{
 		old_track_count = omp_playlist_track_count;
 		old_track_id = omp_playlist_current_track_id;
@@ -689,7 +673,8 @@
 
 		if (omp_main_time_slider_can_update)
 		{
-			// We don't want to set both min/max to 0 as this triggers a critial GTK warning, so we set 0/1 instead in that case
+			// We don't want to set both min/max to 0 as this triggers a
+			// critial GTK warning, so we set 0/1 instead in that case
 			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);
 		}
@@ -697,9 +682,58 @@
 }
 
 /**
- * Updates the UI if playback engine switched between paused and playing modes
+ * Updates the UI after a change to the shuffle flag
  */
 void
+omp_main_update_shuffle_state(gpointer instance, gboolean state, gpointer user_data)
+{
+	gchar *image_file_name;
+
+	if (state)
+	{
+		image_file_name = g_build_filename(ui_image_path, "ico-shuffle-on.png", NULL);
+	} else {
+		image_file_name = g_build_filename(ui_image_path, "ico-shuffle-off.png", NULL);
+	}
+
+	gtk_image_set_from_file(GTK_IMAGE(main_widgets.shuffle_button_image), image_file_name);
+	g_free(image_file_name);
+}
+
+/**
+ * Updates the UI after the repeat mode changed
+ */
+void
+omp_main_update_repeat_mode(gpointer instance, guint mode, gpointer user_data)
+{
+	gchar *image_file_name;
+
+	switch (mode)
+	{
+		case OMP_REPEAT_OFF:
+			image_file_name = g_build_filename(ui_image_path, "ico-repeat-off.png", NULL);
+			break;
+
+		case OMP_REPEAT_ONCE:
+			image_file_name = g_build_filename(ui_image_path, "ico-repeat-once.png", NULL);
+			break;
+
+		case OMP_REPEAT_CURRENT:
+			image_file_name = g_build_filename(ui_image_path, "ico-repeat-current.png", NULL);
+			break;
+
+		case OMP_REPEAT_ALL:
+			image_file_name = g_build_filename(ui_image_path, "ico-repeat-all.png", NULL);
+	}
+
+	gtk_image_set_from_file(GTK_IMAGE(main_widgets.repeat_button_image), image_file_name);
+	g_free(image_file_name);
+}
+
+/**
+ * Updates the UI after a switch between "paused" and "playing" modes
+ */
+void
 omp_main_update_status_change(gpointer instance, gpointer user_data)
 {
 	// Update Play/Pause button pixmap
@@ -726,8 +760,10 @@
 	gulong track_position, track_length;
 	gchar *text;
 
-	// Got a track length change?
+	// Got a track position change?
 	track_position = omp_playback_get_track_position();
+
+	if (track_position != old_track_position)
 	{
 		old_track_position = track_position;
 		track_length = omp_playback_get_track_length();
@@ -741,7 +777,8 @@
 
 		if (omp_main_time_slider_can_update)
 		{
-			// We don't want to set both min/max to 0 as this triggers a critial GTK warning, so we set 0/1 instead in that case
+			// We don't want to set both min/max to 0 as this triggers a
+			// critial GTK warning, so we set 0/1 instead in that case
 			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);
 		}
@@ -750,16 +787,20 @@
 }
 
 /**
- * Updates the UI if the playback volume changed
+ * Updates the UI due to a change in playback volume
  */
 void
 omp_main_update_volume(gpointer instance, gpointer user_data)
 {
-	gchar *text;
+	gchar *text, *image_file_name;
 	guint volume;
 
 	volume = omp_playback_get_volume();
 
+	image_file_name = g_strdup_printf("%s/ind-music-volume-%02d.png", ui_image_path, volume/10);
+	gtk_image_set_from_file(GTK_IMAGE(main_widgets.volume_image), image_file_name);
+	g_free(image_file_name);
+
 	text = g_strdup_printf(OMP_WIDGET_CAPTION_VOLUME, volume);
 	gtk_label_set_text(GTK_LABEL(main_widgets.volume_label), text);
 	g_free(text);
@@ -768,7 +809,7 @@
 }
 
 /**
- * Updates the UI if the track's artist changed
+ * Updates the UI's track artist label
  */
 void
 omp_main_update_tag_artist(gpointer instance, const gchar *artist, gpointer user_data)
@@ -777,11 +818,10 @@
 }
 
 /**
- * Updates the UI if the track's title changed
+ * Updates the UI's track title label
  */
 void
 omp_main_update_tag_title(gpointer instance, const gchar *title, gpointer user_data)
 {
 	gtk_label_set_text(GTK_LABEL(main_widgets.title_label), title);
 }
-

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -32,13 +32,14 @@
 #include <fcntl.h>
 
 #include "persistent.h"
+#include "main.h"
 
 /// The default configuration
 struct _omp_config omp_default_config =
 {
 	FALSE,
+	OMP_REPEAT_OFF,
 	TRUE,
-	OMP_REPEAT_OFF,
 //	FALSE,
 	FALSE,
 	"%f",
@@ -63,13 +64,22 @@
 	#endif
 
 	// This mustn't be called more than once
-	g_assert(omp_config == NULL);
+	g_assert(!omp_config);
 
 	// Set default config
 	omp_config = g_new(struct _omp_config, 1);
 	g_memmove(omp_config, &omp_default_config, sizeof(struct _omp_config));
 
-	/// @todo GConf
+	// Create the signals we emit
+	g_signal_new(OMP_EVENT_CONFIG_SHUFFLE_STATE_CHANGED,
+		G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST, 0, 0, NULL,
+		g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+	g_signal_new(OMP_EVENT_CONFIG_REPEAT_MODE_CHANGED,
+		G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST, 0, 0, NULL,
+		g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	/// @todo GConf implementation
 }
 
 /**
@@ -82,7 +92,7 @@
 }
 
 /**
- * Saves the current application configuration data to persistent storate
+ * Saves the current application configuration data to persistent storage
  */
 void
 omp_config_save()
@@ -90,6 +100,52 @@
 }
 
 /**
+ * Sets state of shuffle flag
+ */
+void
+omp_config_set_shuffle_state(gboolean state)
+{
+	omp_config->shuffle = state;
+	omp_config_save();
+
+	// Submit new state to the UI
+	g_signal_emit_by_name(G_OBJECT(omp_window), OMP_EVENT_CONFIG_SHUFFLE_STATE_CHANGED,
+		state);
+}
+
+/**
+ * Returns state of shuffle flag
+ */
+gboolean
+omp_config_get_shuffle_state()
+{
+	return omp_config->shuffle;
+}
+
+/**
+ * Sets repeat mode in config data
+ */
+void
+omp_config_set_repeat_mode(guint mode)
+{
+	omp_config->repeat_mode = mode;
+	omp_config_save();
+
+	// Submit new state to the UI
+	g_signal_emit_by_name(G_OBJECT(omp_window), OMP_EVENT_CONFIG_REPEAT_MODE_CHANGED,
+		mode);
+}
+
+/**
+ * Returns repeat mode
+ */
+guint
+omp_config_get_repeat_mode()
+{
+	return omp_config->repeat_mode;
+}
+
+/**
  * Fills the session data with sane default values
  */
 void
@@ -140,7 +196,7 @@
 	// Try to load the track, set the playback position and resume playback if needed
 	if (omp_playlist_load_current_track())
 	{
-		if (omp_session->was_playing)
+		if (omp_session->was_playing && omp_config->resume_playback)
 		{
 			omp_playback_fade_volume();
 			omp_playback_play();

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/persistent.h	2007-08-22 07:34:10 UTC (rev 2771)
@@ -30,12 +30,17 @@
 #include "playlist.h"
 #include "main.h"
 
+#define OMP_EVENT_CONFIG_SHUFFLE_STATE_CHANGED "config_shuffle_state_changed"
+#define OMP_EVENT_CONFIG_REPEAT_MODE_CHANGED "config_repeat_mode_changed"
+
 /// Application configuration data
+/// @note Default values are taken from omp_default_config
+/// @note Update that struct as well if you make changes here!
 struct _omp_config
 {
 	gboolean shuffle;									///< Shuffle on/off
+	guint repeat_mode;								///< Repeat mode @see omp_repeat_modes
 	gboolean resume_playback;					///< Resume playback on startup where it left off?
-	gint repeat_mode;									///< Repeat mode @see omp_repeat_modes
 //	gboolean auto_scroll;						///< Scroll title if it's too long?
 	gboolean convert_underscore;			///< Convert '_' to ' '?
 	gchar title_format[32];						///< Format string used for title display
@@ -64,6 +69,12 @@
 void omp_config_free();
 void omp_config_save();
 
+void omp_config_set_shuffle_state(gboolean state);
+gboolean omp_config_get_shuffle_state();
+
+void omp_config_set_repeat_mode(guint mode);
+guint omp_config_get_repeat_mode();
+
 void omp_session_restore_state();
 void omp_session_free();
 void omp_session_save();

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playback.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -140,7 +140,7 @@
 void
 omp_playback_reset()
 {
-	gst_element_set_state(omp_gst_playbin, GST_STATE_READY);
+	gst_element_set_state(omp_gst_playbin, GST_STATE_NULL);
 
 	g_signal_emit_by_name(G_OBJECT(omp_window), OMP_EVENT_PLAYBACK_RESET);
 }

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -62,6 +62,9 @@
 	guint track_id;
 };
 
+/// Flag that indicates whether the current track has already been repeated once or not
+gboolean omp_playlist_track_repeated_once = FALSE;
+
 // Forward declarations for internal use
 void omp_playlist_process_eos_event(gpointer instance, gpointer user_data);
 void omp_playlist_process_tag_artist_change(gpointer instance, gchar *artist, gpointer user_data);
@@ -305,7 +308,7 @@
 	struct omp_track_history_entry *history_entry;
 	struct spiff_track *track;
 	gboolean was_playing;
-	gboolean is_new_track = FALSE;
+	gboolean track_determined = FALSE;
 
 	if (!omp_playlist_current_track)
 	{
@@ -351,7 +354,7 @@
 		g_free(history_entry);
 		omp_track_history = g_slist_delete_link(omp_track_history, omp_track_history);
 
-		is_new_track = TRUE;
+		track_determined = TRUE;
 
 	} else {
 
@@ -371,12 +374,12 @@
 			{
 				omp_playlist_current_track = track;
 				omp_playlist_current_track_id--;
-				is_new_track = TRUE;
+				track_determined = TRUE;
 			}
 		}
 	}
 
-	if (is_new_track)
+	if (track_determined)
 	{
 		// Update session
 		omp_session_set_track_id(omp_playlist_current_track_id);
@@ -392,12 +395,12 @@
 		} else {
 
 			// Uh-oh, track failed to load - let's find another one, shall we?
-			is_new_track = FALSE;
+			track_determined = FALSE;
 			goto try_again;
 		}
 	}
 
-	return is_new_track;
+	return track_determined;
 }
 
 /**
@@ -411,7 +414,9 @@
 {
 	struct omp_track_history_entry *history_entry;
 	gboolean was_playing;
-	gboolean is_new_track = FALSE;
+	guint repeat_mode;
+	gboolean track_determined = FALSE;
+	guint i, n;
 
 	if (!omp_playlist_current_track)
 	{
@@ -421,6 +426,23 @@
 	// Get player state so we can continue playback if necessary
 	was_playing = (omp_playback_get_state() == OMP_PLAYBACK_STATE_PLAYING);
 
+	repeat_mode = omp_config_get_repeat_mode();
+
+	// Repeat once
+	if (repeat_mode == OMP_REPEAT_ONCE)
+	{
+		// Play same track again and turn repeat off
+		omp_config_set_repeat_mode(OMP_REPEAT_OFF);
+		track_determined = TRUE;
+	}
+
+	// Repeat current
+	if (repeat_mode == OMP_REPEAT_CURRENT)
+	{
+		// Play same track again
+		track_determined = TRUE;
+	}
+
 try_again:
 
 	// Prepare the history entry - if we don't need it we'll just free it again
@@ -428,17 +450,42 @@
 	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)
+	// Repeat all: we forward 1 track
+	// Shuffle on: we forward 0 < n < omp_playlist_track_count tracks
+	if ( (repeat_mode == OMP_REPEAT_ALL) || (omp_config_get_shuffle_state()) )
 	{
+		n = (omp_config_get_shuffle_state()) ?
+			g_random_int_range(1, omp_playlist_track_count) :
+			1;
+
+		for (i=0; i<n; i++)
+		{
+			if (omp_playlist_current_track->next)
+			{
+				omp_playlist_current_track = omp_playlist_current_track->next;
+				omp_playlist_current_track_id++;
+			} else {
+				omp_playlist_current_track = omp_playlist->tracks;
+				omp_playlist_current_track_id = 0;
+			}
+		}
+
+		track_determined = TRUE;
+	}
+
+	// Repeat off and shuffle off: Do we have a track to play?
+	if ( (repeat_mode == OMP_REPEAT_OFF) &&
+		   (!omp_config_get_shuffle_state()) &&
+		   omp_playlist_current_track->next
+		 )
+	{
 		omp_playlist_current_track = omp_playlist_current_track->next;
 		omp_playlist_current_track_id++;
 
-		// Yes, we were able to find a new track to play
-		is_new_track = TRUE;
+		track_determined = TRUE;
 	}
 
-	if (is_new_track)
+	if (track_determined)
 	{
 		// Add track to track history
 		omp_track_history = g_slist_prepend(omp_track_history, (gpointer)history_entry);
@@ -457,17 +504,17 @@
 		} else {
 
 			// Uh-oh, track failed to load - let's find another one, shall we?
-			is_new_track = FALSE;
+			track_determined = FALSE;
 			goto try_again;
 		}
 
 	} else {
 
-		// We're not making use of the history entry as the track didn't change
+		// We're not making use of the history entry as we didn't find a new track to play
 		g_free(history_entry);
 	}
 
-	return is_new_track;
+	return track_determined;
 }
 
 /**

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist.h	2007-08-22 07:34:10 UTC (rev 2771)
@@ -40,10 +40,11 @@
 /// Modes available for repetitive track playback
 enum omp_repeat_modes
 {
-	OMP_REPEAT_OFF,									///< Repeat off
-	OMP_REPEAT_CURRENT_ONCE,				///< Repeat current track once, then proceed with next track
+	OMP_REPEAT_OFF = 0,							///< Repeat off
+	OMP_REPEAT_ONCE,								///< Repeat current track once, then proceed with next track
 	OMP_REPEAT_CURRENT,							///< Repeat current track forever
-	OMP_REPEAT_PLAYLIST							///< Repeat entire playlist
+	OMP_REPEAT_ALL,									///< Repeat entire playlist
+	OMP_REPEAT_COUNT								///< End-of-list marker for mode iteration
 };
 
 extern struct spiff_list *omp_playlist;

Modified: trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist_page.c
===================================================================
--- trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist_page.c	2007-08-21 19:20:40 UTC (rev 2770)
+++ trunk/src/target/OM-2007.2/applications/openmoko-mediaplayer2/src/playlist_page.c	2007-08-22 07:34:10 UTC (rev 2771)
@@ -319,7 +319,7 @@
 	main_vbox = gtk_vbox_new(FALSE, 0);
 
 	// Caption #1
-	alignment = create_label(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 5, 5, 5);
 	gtk_box_pack_start(GTK_BOX(main_vbox), GTK_WIDGET(alignment), FALSE, FALSE, 0);
 	gtk_label_set_text(GTK_LABEL(label), _("Select Playlist to load:"));
@@ -332,7 +332,7 @@
 	omp_playlist_page_list_create(GTK_CONTAINER(scroll_box));
 
 	// Caption #2
-	alignment = create_label(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
+	alignment = label_create(&label, "Sans 14", "black", 0, 0, 0, 0, 0);
 	gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 5, 5, 5);
 	gtk_box_pack_start(GTK_BOX(main_vbox), GTK_WIDGET(alignment), FALSE, FALSE, 0);
 	gtk_label_set_text(GTK_LABEL(label), _("Enter name to create a new playlist:"));





More information about the commitlog mailing list