rhythmbox r5781 - in trunk: . shell widgets



Author: jmatthew
Date: Sat Jun 28 04:30:56 2008
New Revision: 5781
URL: http://svn.gnome.org/viewvc/rhythmbox?rev=5781&view=rev

Log:
2008-06-28  Jonathan Matthew  <jonathan d14n org>

	* shell/rb-shell-player.c: (rb_shell_player_constructor),
	(rb_shell_player_handle_eos_unlocked),
	(rb_shell_player_slider_dragging_cb),
	(rb_shell_player_set_playing_time), (tick_cb):
	If the seek slider is still being dragged when we reach EOS, wait
	until it's released; if a seek occurs before then, forget about it.
	Fixes #140020.

	* widgets/rb-header.c: (rb_header_class_init),
	(rb_header_set_playing_entry_internal), (rb_header_set_property),
	(rb_header_get_property), (rb_header_sync), (rb_header_sync_time),
	(slider_press_callback), (slider_moved_timeout),
	(slider_moved_callback), (apply_slider_position),
	(slider_release_callback), (slider_changed_callback):
	Add the 'slider-dragging' property used above.  Rearrange various
	bits of code to behave a little bit better, most importantly removing
	the idle handler that just screwed things up.  Set the upper bound on
	the slider unconditionally when the playing entry changes, fixing
	#496816.


Modified:
   trunk/ChangeLog
   trunk/shell/rb-shell-player.c
   trunk/widgets/rb-header.c

Modified: trunk/shell/rb-shell-player.c
==============================================================================
--- trunk/shell/rb-shell-player.c	(original)
+++ trunk/shell/rb-shell-player.c	Sat Jun 28 04:30:56 2008
@@ -202,6 +202,9 @@
 						  gboolean from_eos,
 						  gboolean allow_stop,
 						  GError **error);
+static void rb_shell_player_slider_dragging_cb (GObject *header,
+						GParamSpec *pspec,
+						RBShellPlayer *player);
 
 
 
@@ -639,6 +642,10 @@
 	player->priv->header_widget = rb_header_new (player, player->priv->db);
 	gtk_widget_show (GTK_WIDGET (player->priv->header_widget));
 	gtk_box_pack_start (GTK_BOX (player), GTK_WIDGET (player->priv->header_widget), TRUE, TRUE, 0);
+	g_signal_connect_object (player->priv->header_widget,
+				 "notify::slider-dragging",
+				 G_CALLBACK (rb_shell_player_slider_dragging_cb),
+				 player, 0);
 
 	gtk_action_group_add_actions (player->priv->actiongroup,
 				      rb_shell_player_actions,
@@ -785,6 +792,7 @@
 	RhythmDBEntry *playing_entry;
 	RBSource *source;
 	gboolean update_stats;
+	gboolean dragging;
 
 	source = player->priv->current_playing_source;
 
@@ -806,6 +814,14 @@
 		return;
 	}
 
+	/* defer EOS handling while the position slider is being dragged */
+	g_object_get (player->priv->header_widget, "slider-dragging", &dragging, NULL);
+	if (dragging) {
+		rb_debug ("slider is dragging, will handle EOS (if applicable) on release");
+		player->priv->playing_entry_eos = TRUE;
+		return;
+	}
+
 	update_stats = FALSE;
 	switch (rb_source_handle_eos (source)) {
 	case RB_SOURCE_EOF_ERROR:
@@ -891,6 +907,22 @@
 }
 
 static void
+rb_shell_player_slider_dragging_cb (GObject *header, GParamSpec *pspec, RBShellPlayer *player)
+{
+	gboolean drag;
+
+	g_object_get (player->priv->header_widget, "slider-dragging", &drag, NULL);
+	rb_debug ("slider dragging? %d", drag);
+
+	/* if an EOS occurred while dragging, process it now */
+	if (drag == FALSE && player->priv->playing_entry_eos) {
+		rb_debug ("processing EOS delayed due to slider dragging");
+		player->priv->playing_entry_eos = FALSE;
+		rb_shell_player_handle_eos_unlocked (player, rb_shell_player_get_playing_entry (player), FALSE);
+	}
+}
+
+static void
 rb_shell_player_handle_eos (RBPlayer *player,
 			    RhythmDBEntry *entry,
 			    RBShellPlayer *shell_player)
@@ -3308,6 +3340,10 @@
 				  GError **error)
 {
 	if (rb_player_seekable (player->priv->mmplayer)) {
+		if (player->priv->playing_entry_eos) {
+			rb_debug ("forgetting that playing entry had EOS'd due to seek");
+			player->priv->playing_entry_eos = FALSE;
+		}
 		rb_player_set_time (player->priv->mmplayer, (long) time);
 		return TRUE;
 	} else {
@@ -3589,7 +3625,7 @@
 		  duration,
 		  duration_from_player);
 
-	if (rb_player_playing (mmplayer)) {
+	if (TRUE /* rb_player_playing (mmplayer)*/) {		/* why do we care whether it's playing or not? */
 		if (elapsed < 0)
 			elapsed = 0;
 

Modified: trunk/widgets/rb-header.c
==============================================================================
--- trunk/widgets/rb-header.c	(original)
+++ trunk/widgets/rb-header.c	Sat Jun 28 04:30:56 2008
@@ -74,6 +74,7 @@
 static void rb_header_set_show_timeline (RBHeader *header,
 			                 gboolean show);
 static void rb_header_update_elapsed (RBHeader *header);
+static void apply_slider_position (RBHeader *header);
 static gboolean slider_press_callback (GtkWidget *widget, GdkEventButton *event, RBHeader *header);
 static gboolean slider_moved_callback (GtkWidget *widget, GdkEventMotion *event, RBHeader *header);
 static gboolean slider_release_callback (GtkWidget *widget, GdkEventButton *event, RBHeader *header);
@@ -101,7 +102,6 @@
 	gboolean slider_locked;
 	guint slider_moved_timeout;
 	long latest_set_time;
-	guint value_changed_update_handler;
 	GtkWidget *elapsed;
 
 	guint elapsed_time;
@@ -116,6 +116,7 @@
 	PROP_SHELL_PLAYER,
 	PROP_ENTRY,
 	PROP_SEEKABLE,
+	PROP_SLIDER_DRAGGING
 };
 
 #define TITLE_MARKUP(xTITLE) g_markup_printf_escaped ("<big><b>%s</b></big>", xTITLE)
@@ -185,6 +186,19 @@
 							       TRUE,
 							       G_PARAM_READWRITE));
 
+	/**
+	 * RBHeader:slider-dragging:
+	 *
+	 * Whether the song position slider is currently being dragged.
+	 */
+	g_object_class_install_property (object_class,
+					 PROP_SLIDER_DRAGGING,
+					 g_param_spec_boolean ("slider-dragging",
+						 	       "slider dragging",
+							       "slider dragging",
+							       FALSE,
+							       G_PARAM_READABLE));
+
 	g_type_class_add_private (klass, sizeof (RBHeaderPrivate));
 }
 
@@ -277,6 +291,24 @@
 }
 
 static void
+rb_header_set_playing_entry_internal (RBHeader *header, RhythmDBEntry *entry)
+{
+	if (header->priv->entry == entry)
+		return;
+
+	header->priv->entry = entry;
+	if (header->priv->entry) {
+		header->priv->duration = rhythmdb_entry_get_ulong (header->priv->entry,
+								   RHYTHMDB_PROP_DURATION);
+	} else {
+		header->priv->duration = 0;
+	}
+
+	header->priv->adjustment->upper = header->priv->duration;
+	gtk_adjustment_changed (header->priv->adjustment);
+}
+
+static void
 rb_header_set_property (GObject *object,
 			guint prop_id,
 			const GValue *value,
@@ -289,13 +321,7 @@
 		header->priv->db = g_value_get_object (value);
 		break;
 	case PROP_ENTRY:
-		header->priv->entry = g_value_get_boxed (value);
-		if (header->priv->entry) {
-			header->priv->duration = rhythmdb_entry_get_ulong (header->priv->entry,
-									   RHYTHMDB_PROP_DURATION);
-		} else {
-			header->priv->duration = 0;
-		}
+		rb_header_set_playing_entry_internal (header, g_value_get_boxed (value));
 		break;
 	case PROP_SHELL_PLAYER:
 		header->priv->shell_player = g_value_get_object (value);
@@ -334,6 +360,9 @@
 	case PROP_SEEKABLE:
 		g_value_set_boolean (value, header->priv->seekable);
 		break;
+	case PROP_SLIDER_DRAGGING:
+		g_value_set_boolean (value, header->priv->slider_dragging);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -415,8 +444,12 @@
 rb_header_sync (RBHeader *header)
 {
 	char *label_text;
+	const char *location = "<null>";
 
-	rb_debug ("syncing with entry = %p", header->priv->entry);
+	if (header->priv->entry != NULL) {
+		location = rhythmdb_entry_get_string (header->priv->entry, RHYTHMDB_PROP_LOCATION);
+	}
+	rb_debug ("syncing with entry = %s", location);
 
 	if (header->priv->entry != NULL) {
 		const char *title;
@@ -566,14 +599,7 @@
 	seconds = header->priv->elapsed_time;
 
 	if (header->priv->duration > 0) {
-		double progress = 0.0;
-
-		if (seconds > 0) {
-			progress = (double) seconds;
-		} else {
-			header->priv->adjustment->upper = header->priv->duration;
-			g_signal_emit_by_name (G_OBJECT (header->priv->adjustment), "changed");
-		}
+		double progress = (double) seconds;
 
 		header->priv->slider_locked = TRUE;
 		gtk_adjustment_set_value (header->priv->adjustment, progress);
@@ -596,24 +622,25 @@
 {
 	header->priv->slider_dragging = TRUE;
 	header->priv->latest_set_time = -1;
+	g_object_notify (G_OBJECT (header), "slider-dragging");
+
+	/* HACK: we want the behaviour you get with the middle button, so we
+	 * mangle the event.  clicking with other buttons moves the slider in
+	 * step increments, clicking with the middle button moves the slider to
+	 * the location of the click.
+	 */
+	event->button = 2;
+
+
 	return FALSE;
 }
 
 static gboolean
 slider_moved_timeout (RBHeader *header)
 {
-	double progress;
-	long new;
-
 	GDK_THREADS_ENTER ();
 
-	progress = gtk_adjustment_get_value (gtk_range_get_adjustment (GTK_RANGE (header->priv->scale)));
-	new = (long) (progress+0.5);
-
-	rb_debug ("setting time to %ld", new);
-	rb_shell_player_set_playing_time (header->priv->shell_player, new, NULL);
-
-	header->priv->latest_set_time = new;
+	apply_slider_position (header);
 	header->priv->slider_moved_timeout = 0;
 
 	GDK_THREADS_LEAVE ();
@@ -626,7 +653,6 @@
 		       GdkEventMotion *event,
 		       RBHeader *header)
 {
-	GtkAdjustment *adjustment;
 	double progress;
 
 	if (header->priv->slider_dragging == FALSE) {
@@ -634,9 +660,7 @@
 		return FALSE;
 	}
 
-	adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
-
-	progress = gtk_adjustment_get_value (adjustment);
+	progress = gtk_adjustment_get_value (header->priv->adjustment);
 	header->priv->elapsed_time = (guint) (progress+0.5);
 
 	rb_header_update_elapsed (header);
@@ -652,52 +676,43 @@
 	return FALSE;
 }
 
-static gboolean
-slider_release_callback (GtkWidget *widget,
-			 GdkEventButton *event,
-			 RBHeader *header)
+static void
+apply_slider_position (RBHeader *header)
 {
 	double progress;
 	long new;
-	GtkAdjustment *adjustment;
-
-	if (header->priv->slider_dragging == FALSE) {
-		rb_debug ("slider is not dragging");
-		return FALSE;
-	}
-
-	adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
 
-	progress = gtk_adjustment_get_value (adjustment);
+	progress = gtk_adjustment_get_value (header->priv->adjustment);
 	new = (long) (progress+0.5);
 
 	if (new != header->priv->latest_set_time) {
 		rb_debug ("setting time to %ld", new);
 		rb_shell_player_set_playing_time (header->priv->shell_player, new, NULL);
+		header->priv->latest_set_time = new;
 	}
-
-	header->priv->slider_dragging = FALSE;
-
-	if (header->priv->slider_moved_timeout != 0) {
-		g_source_remove (header->priv->slider_moved_timeout);
-		header->priv->slider_moved_timeout = 0;
-	}
-
-	return FALSE;
 }
 
 static gboolean
-changed_idle_callback (RBHeader *header)
+slider_release_callback (GtkWidget *widget,
+			 GdkEventButton *event,
+			 RBHeader *header)
 {
-	GDK_THREADS_ENTER ();
+	/* HACK: see slider_press_callback */
+	event->button = 2;
 
-	slider_release_callback (header->priv->scale, NULL, header);
-
-	header->priv->value_changed_update_handler = 0;
-	rb_debug ("in changed_idle_callback");
+	if (header->priv->slider_dragging == FALSE) {
+		rb_debug ("slider is not dragging");
+		return FALSE;
+	}
 
-	GDK_THREADS_LEAVE ();
+	if (header->priv->slider_moved_timeout != 0) {
+		g_source_remove (header->priv->slider_moved_timeout);
+		header->priv->slider_moved_timeout = 0;
+	}
 
+	apply_slider_position (header);
+	header->priv->slider_dragging = FALSE;
+	g_object_notify (G_OBJECT (header), "slider-dragging");
 	return FALSE;
 }
 
@@ -705,12 +720,13 @@
 slider_changed_callback (GtkWidget *widget,
 		         RBHeader *header)
 {
+	/* if the slider isn't being dragged, and nothing else is happening,
+	 * this indicates the position was adjusted with a keypress (page up/page down etc.),
+	 * so we should directly apply the change.
+	 */
 	if (header->priv->slider_dragging == FALSE &&
-	    header->priv->slider_locked == FALSE &&
-	    header->priv->value_changed_update_handler == 0) {
-		header->priv->slider_dragging = TRUE;
-		header->priv->value_changed_update_handler =
-			g_idle_add ((GSourceFunc) changed_idle_callback, header);
+	    header->priv->slider_locked == FALSE) {
+		apply_slider_position (header);
 	}
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]