marlin r1342 - in trunk: marlin src src/other



Author: iain
Date: Tue Dec 23 22:12:50 2008
New Revision: 1342
URL: http://svn.gnome.org/viewvc/marlin?rev=1342&view=rev

Log:
Make there be one Jack client that is shared throughout the whole process

Modified:
   trunk/marlin/marlin-jack-play.c
   trunk/marlin/marlin-jack-play.h
   trunk/marlin/marlin-jack-record.c
   trunk/marlin/marlin-jack-record.h
   trunk/marlin/marlin-jack.c
   trunk/marlin/marlin-jack.h
   trunk/marlin/marlin-load-pipeline.c
   trunk/marlin/marlin-program.c
   trunk/marlin/marlin-program.h
   trunk/src/marlin-record.c
   trunk/src/marlin-window.c
   trunk/src/other/gtkvumeter.c

Modified: trunk/marlin/marlin-jack-play.c
==============================================================================
--- trunk/marlin/marlin-jack-play.c	(original)
+++ trunk/marlin/marlin-jack-play.c	Tue Dec 23 22:12:50 2008
@@ -107,69 +107,14 @@
 static long process_more_frames (gpointer userdata, float **data);
 
 static void
-free_ports (MarlinJackPlay *jack)
-{
-	MarlinJackPlayPrivate *priv;
-	int i;
-
-	priv = jack->priv;
-
-	for (i = 0; i < priv->channels; i++) {
-		struct _port_data *pd = priv->port_data[i];
-
-		jack_port_unregister (priv->client, pd->playback);
-
-		if (pd->rb) {
-			jack_ringbuffer_free (pd->rb);
-		}
-		g_free (pd->rb_buffer);
-		g_free (pd->tmp_buffer);
-
-		if (pd->state) {
-			src_delete (pd->state);
-		}
-		g_free (pd);
-	}
-	g_free (priv->port_data);
-}
-
-static void
-setup_ports (MarlinJackPlay *jack)
-{
-	MarlinJackPlayPrivate *priv;
-	int i;
-
-	priv = jack->priv;
-
-	/* We always want to set up two ports, even for mono samples */
-	priv->port_data = g_new0 (struct _port_data *, 2);
-	for (i = 0; i < 2; i++) {
-		struct _port_data *pd;
-		char *name;
-
-		pd = g_new0 (struct _port_data, 1);
-
-		pd->jack = jack;
-		/* Create the ports */
-		name = g_strdup_printf ("playback%d", i + 1);
-		pd->playback = jack_port_register (priv->client, name,
-						   JACK_DEFAULT_AUDIO_TYPE,
-						   JackPortIsOutput, 0);
-                g_free (name);
-
-		priv->port_data[i] = pd;
-	}
-}
-
-static void
 finalize (GObject *object)
 {
 	MarlinJackPlayPrivate *priv;
 
 	priv = GET_PRIVATE (object);
 
-	free_ports ((MarlinJackPlay *) object);
-	jack_client_close (priv->client);
+	/* free_ports ((MarlinJackPlay *) object); */
+	/* jack_client_close (priv->client); */
 
 	((GObjectClass *) marlin_jack_play_parent_class)->finalize (object);
 }
@@ -237,13 +182,9 @@
 	}
 
 	if (strcmp (pspec->name, "channels") == 0) {
-		/* Channels have changed, so we need to tear down the ports
-		   and rebuild them */
-		free_ports (jack);
 		g_object_get (object,
 			      "channels", &priv->channels,
 			      NULL);
-		setup_ports (jack);
 		return;
 	}
 }
@@ -256,16 +197,32 @@
 
 	priv = GET_PRIVATE (jack);
 
+	/* Don't need to do anything if its the same sample */
+	if (priv->sample == sample) {
+		return;
+	}
+
 	if (priv->sample) {
-		/* Sample is changed, so tear down ports. They will be built
-		   up once we've setup the new sample */
-		free_ports ((MarlinJackPlay *) jack);
+		int i;
+
+		/* Sample is changed so we need to reset the SRC */
+		for (i = 0; i < priv->channels; i++) {
+			struct _port_data *pd = priv->port_data[i];
+
+			if (pd->state) {
+				src_reset (pd->state);
+			}
+		}
 
 		g_signal_handler_disconnect (priv->sample,
 					     priv->sample_notify_id);
 		g_object_unref (priv->sample);
 	}
 
+	if (sample == NULL) {
+		return;
+	}
+
 	priv->sample = g_object_ref (sample);
 	g_object_get (G_OBJECT (priv->sample),
 		      "channels", &priv->channels,
@@ -279,8 +236,6 @@
 
 	priv->src_ratio = calculate_rate_ratio (priv->sample_rate,
 						priv->jack_rate);
-
-	setup_ports ((MarlinJackPlay *) jack);
 }
 
 /**
@@ -397,7 +352,6 @@
 	return 0;
 }
 
-/* FIXME: Replace this with marlin_block_get_buffer */
 static long
 process_more_frames (gpointer userdata,
 		     float  **data)
@@ -412,6 +366,7 @@
 	if (frames_needed == 0 && priv->repeating == FALSE) {
 		/* This will tell the reader that we've finished writing */
 		pd->writer_finished = TRUE;
+
 		return 0;
 	}
 
@@ -431,7 +386,10 @@
 		pd->offset += copied;
 	}
 
-	pd->offset_in_block = pd->offset - pd->current_block->start;
+	/* If pd->current_block == NULL then we've finished */
+	if (pd->current_block) {
+		pd->offset_in_block = pd->offset - pd->current_block->start;
+	}
 	*data = pd->tmp_buffer;
 
 	return copied;
@@ -469,6 +427,8 @@
 
 		frames_needed = bytes_free / frame_size;
 		if (frames_needed == 0) {
+			gen_frames[i] = 0;
+			tmp_frames[i] = NULL;
 			continue;
 		}
 
@@ -478,6 +438,7 @@
 						   frames_needed,
 						   pd->rb_buffer);
 		if (gen_frames[i] == 0) {
+			tmp_frames[i] = NULL;
 			continue;
 		}
 
@@ -548,6 +509,12 @@
 		return FALSE;
 	}
 
+	jack_set_process_callback (priv->client, process_reader, jack);
+	jack_set_buffer_size_callback (priv->client, bufsize_changed, jack);
+
+	jack_set_sample_rate_callback (priv->client, srate_changed, jack);
+	priv->jack_rate = jack_get_sample_rate (priv->client);
+
 	if (jack_activate (priv->client)) {
 		if (error && *error != NULL) {
 			*error = g_error_new (MARLIN_JACK_ERROR,
@@ -617,7 +584,7 @@
 	priv->mode = MARLIN_JACK_PLAY_MODE_PREROLLING;
 
 	/* Start the idle process to fill the ring buffer with data */
-	priv->writer_id = g_idle_add (process_writer, jack);
+	priv->writer_id = g_timeout_add (50, process_writer, jack);
 
 	return TRUE;
 }
@@ -651,7 +618,7 @@
 
 	priv = GET_PRIVATE (jack);
 
-	priv->mode = MARLIN_JACK_PLAY_MODE_STOPPED;
+	priv->mode = MARLIN_JACK_PLAY_MODE_NOTHING;
 
 	jack_deactivate (priv->client);
 
@@ -688,6 +655,15 @@
 	free (ports);
 }
 
+static gboolean
+is_busy (MarlinJack *jack)
+{
+	MarlinJackPlay *player = (MarlinJackPlay *) jack;
+	MarlinJackPlayPrivate *priv = player->priv;
+
+	return (priv->mode != MARLIN_JACK_PLAY_MODE_NOTHING);
+}
+
 static void
 marlin_jack_play_class_init (MarlinJackPlayClass *klass)
 {
@@ -702,6 +678,7 @@
 	j_class->stop = play_stop;
 	j_class->pause = play_pause;
 	j_class->cont = play_continue;
+	j_class->is_busy = is_busy;
 
 	g_type_class_add_private (klass, sizeof (MarlinJackPlayPrivate));
 
@@ -735,6 +712,34 @@
 }
 
 static void
+setup_ports (MarlinJackPlay *jack)
+{
+	MarlinJackPlayPrivate *priv;
+	int i;
+
+	priv = jack->priv;
+
+	/* We always want to set up two ports, even for mono samples */
+	priv->port_data = g_new0 (struct _port_data *, 2);
+	for (i = 0; i < 2; i++) {
+		struct _port_data *pd;
+		char *name;
+
+		pd = g_new0 (struct _port_data, 1);
+
+		pd->jack = jack;
+		/* Create the ports */
+		name = g_strdup_printf ("playback%d", i + 1);
+		pd->playback = jack_port_register (priv->client, name,
+						   JACK_DEFAULT_AUDIO_TYPE,
+						   JackPortIsOutput, 0);
+                g_free (name);
+
+		priv->port_data[i] = pd;
+	}
+}
+
+static void
 marlin_jack_play_init (MarlinJackPlay *jack)
 {
 	MarlinJackPlayPrivate *priv;
@@ -753,54 +758,25 @@
 
 /**
  * marlin_jack_play_new:
- * @client_name: Name of this client
- * @server_name: Name of the jack server to connect to (or NULL for default)
- * @error:
+ * @client:
  *
- * Creates a new #MarlinJackPlay structure that will be connected to @server_name
- * (or the default server if @server_name is NULL).
+ * Creates a new #MarlinJackPlay structure using @client.
  */
 MarlinJackPlay *
-marlin_jack_play_new (const char *client_name,
-		      const char *server_name,
-		      GError    **error)
+marlin_jack_play_new (jack_client_t *client)
 {
 	MarlinJackPlay *jack;
 	MarlinJackPlayPrivate *priv;
-	jack_options_t options = JackNullOption;
-	jack_status_t status;
 
 	jack = g_object_new (MARLIN_JACK_PLAY_TYPE, NULL);
 	priv = jack->priv;
 
-	if (server_name) {
-		options |= JackServerName;
-	}
+	priv->client = client;
+	setup_ports (jack);
 
-	priv->client = jack_client_open (client_name, options,
-					 &status, server_name);
-	if (priv->client == NULL) {
-		/* Make error */
-		if (error && *error != NULL) {
-			*error = g_error_new (MARLIN_JACK_ERROR,
-					      MARLIN_JACK_ERROR_NO_SERVER,
-					      "Unable to run JACK server - JACK status was %d", status);
-		} else {
-			g_warning ("Unable to run JACK server - JACK status was %d");
-		}
-
-		g_object_unref (jack);
-		return NULL;
-	}
-
-	jack_set_process_callback (priv->client, process_reader, jack);
-	jack_set_buffer_size_callback (priv->client, bufsize_changed, jack);
 	priv->bufsize = jack_get_buffer_size (priv->client);
-	priv->jack_buf = g_new0 (jack_default_audio_sample_t, priv->bufsize * 16);
-
-	jack_set_sample_rate_callback (priv->client, srate_changed, jack);
-	priv->jack_rate = jack_get_sample_rate (priv->client);
-
+	priv->jack_buf = g_new0 (jack_default_audio_sample_t,
+				 priv->bufsize * 16);
 	return jack;
 }
 

Modified: trunk/marlin/marlin-jack-play.h
==============================================================================
--- trunk/marlin/marlin-jack-play.h	(original)
+++ trunk/marlin/marlin-jack-play.h	Tue Dec 23 22:12:50 2008
@@ -55,9 +55,7 @@
 };
 
 GType marlin_jack_play_get_type (void);
-MarlinJackPlay *marlin_jack_play_new (const char *client_name,
-				      const char *server_name,
-				      GError **error);
+MarlinJackPlay *marlin_jack_play_new (jack_client_t *client);
 
 void marlin_jack_play_set_repeating (MarlinJackPlay *jack,
 				     gboolean        repeating);

Modified: trunk/marlin/marlin-jack-record.c
==============================================================================
--- trunk/marlin/marlin-jack-record.c	(original)
+++ trunk/marlin/marlin-jack-record.c	Tue Dec 23 22:12:50 2008
@@ -159,7 +159,7 @@
 	priv = GET_PRIVATE (object);
 
 	free_ports ((MarlinJackRecord *) object);
-	jack_client_close (priv->client);
+	/*jack_client_close (priv->client);*/
 
 	((GObjectClass *) marlin_jack_record_parent_class)->finalize (object);
 }
@@ -609,6 +609,12 @@
 	free (ports);
 }
 
+static gboolean
+is_busy (MarlinJack *jack)
+{
+	return FALSE;
+}
+
 static void
 marlin_jack_record_class_init (MarlinJackRecordClass *klass)
 {
@@ -623,6 +629,7 @@
 	j_class->stop = record_stop;
 	j_class->pause = record_pause;
 	j_class->cont = record_continue;
+	j_class->is_busy = is_busy;
 
 	g_type_class_add_private (klass, sizeof (MarlinJackRecordPrivate));
 }
@@ -639,46 +646,22 @@
 
 /**
  * marlin_jack_record_new:
- * @client_name: Name of this client
- * @server_name: Name of the jack server to connect to (or NULL for default)
- * @error: A pointer to a #GError
+ * @client:
  *
  * Creates a new #MarlinJackRecord object.
  *
  * Return value: A #MarlinJackRecord object
  */
 MarlinJackRecord *
-marlin_jack_record_new (const char *client_name,
-			const char *server_name,
-			GError    **error)
+marlin_jack_record_new (jack_client_t *client)
 {
 	MarlinJackRecord *jack;
 	MarlinJackRecordPrivate *priv;
-	jack_options_t options = JackNullOption;
-	jack_status_t status;
 
 	jack = g_object_new (MARLIN_JACK_RECORD_TYPE, NULL);
 	priv = jack->priv;
 
-	if (server_name) {
-		options |= JackServerName;
-	}
-
-	priv->client = jack_client_open (client_name, options,
-					 &status, server_name);
-	if (priv->client == NULL) {
-		/* Make error */
-		if (error && *error != NULL) {
-			*error = g_error_new (MARLIN_JACK_ERROR,
-					      MARLIN_JACK_ERROR_NO_SERVER,
-					      "Unable to run JACK server - JACK status was %d", status);
-		} else {
-			g_warning ("Unable to run JACK server - JACK status was %d");
-		}
-
-		g_object_unref (jack);
-		return NULL;
-	}
+	priv->client = client;
 
 	jack_set_process_callback (priv->client, process_writer, jack);
 	jack_set_buffer_size_callback (priv->client, bufsize_changed, jack);

Modified: trunk/marlin/marlin-jack-record.h
==============================================================================
--- trunk/marlin/marlin-jack-record.h	(original)
+++ trunk/marlin/marlin-jack-record.h	Tue Dec 23 22:12:50 2008
@@ -55,9 +55,7 @@
 };
 
 GType marlin_jack_record_get_type (void);
-MarlinJackRecord *marlin_jack_record_new (const char *client_name,
-					  const char *server_name,
-					  GError **error);
+MarlinJackRecord *marlin_jack_record_new (jack_client_t *client);
 
 G_END_DECLS
 

Modified: trunk/marlin/marlin-jack.c
==============================================================================
--- trunk/marlin/marlin-jack.c	(original)
+++ trunk/marlin/marlin-jack.c	Tue Dec 23 22:12:50 2008
@@ -277,6 +277,12 @@
 	long i;
 	double p = 0.0, total = 0.0;
 
+	if (n_frames == 0) {
+		*peak = 0.0;
+		*rms = 0.0;
+		return;
+	}
+
 	for (i = 0; i < n_frames; i++) {
 		double squared = pow ((double) (data[i]), 2);
 
@@ -302,10 +308,6 @@
 		return;
 	}
 
-	if (n_frames == 0) {
-		return;
-	}
-
 	calculate_peak_and_rms (data[0], n_frames[0], &p, &r);
 	peak[0] = p;
 	rms[0] = r;
@@ -319,3 +321,26 @@
 	g_signal_emit (jack, signals[LEVEL_CHANGED], 0,
 		       priv->channels, rms, peak);
 }
+
+/**
+ * marlin_jack_is_busy:
+ * @jack: #MarlinJack object
+ *
+ * Returns if @jack is busy (playing or recording)
+ *
+ * Return value: TRUE if @jack is busy, FALSE otherwise
+ */
+gboolean
+marlin_jack_is_busy (MarlinJack *jack)
+{
+	MarlinJackClass *j_class = MARLIN_JACK_GET_CLASS (jack);
+
+	if (j_class->is_busy) {
+		return j_class->is_busy (jack);
+	}
+
+	g_assert_not_reached ();
+
+	/* Only for compiler really */
+	return FALSE;
+}

Modified: trunk/marlin/marlin-jack.h
==============================================================================
--- trunk/marlin/marlin-jack.h	(original)
+++ trunk/marlin/marlin-jack.h	Tue Dec 23 22:12:50 2008
@@ -27,6 +27,8 @@
 
 #include <jack/jack.h>
 
+#include <marlin/marlin-sample.h>
+
 G_BEGIN_DECLS
 
 #define MARLIN_JACK_TYPE (marlin_jack_get_type ())
@@ -61,6 +63,7 @@
 	void (*cont) (MarlinJack *jack); /* This should be continue, but thats
 					    a reserved word...maybe it should
 					    just be merged with pause? FIXME */
+	gboolean (*is_busy) (MarlinJack *jack);
 
 	/* signals */
 	void (*level_changed) (MarlinJack *jack,
@@ -81,7 +84,7 @@
 void marlin_jack_emit_levels (MarlinJack *jack,
 			      float     **data,
 			      long       *n_frames);
-
+gboolean marlin_jack_is_busy (MarlinJack *jack);
 G_END_DECLS
 
 #endif

Modified: trunk/marlin/marlin-load-pipeline.c
==============================================================================
--- trunk/marlin/marlin-load-pipeline.c	(original)
+++ trunk/marlin/marlin-load-pipeline.c	Tue Dec 23 22:12:50 2008
@@ -384,9 +384,9 @@
 		gst_element_set_state (priv->audioconvert, GST_STATE_PLAYING);
 		gst_element_set_state (priv->splitter, GST_STATE_PLAYING);
 	}
-	
+
 	gst_caps_unref (caps);
-	
+
 	if (final && priv->audio_pad == NULL) {
 		g_print ("All pads created: No audio\n");
 	}
@@ -399,7 +399,7 @@
 	MarlinLoadPipelinePrivate *priv;
 	GstStructure *structure;
 	int channels, rate;
-	
+
 	priv = pipeline->priv;
 
 	structure = gst_caps_get_structure (caps, 0);
@@ -411,7 +411,7 @@
 		g_print ("No rate set in these caps\n%s", cap_string);
 		g_free (cap_string);
 		return FALSE;
-	} 
+	}
 
 	if (gst_structure_get_int (structure, "channels", &channels) == FALSE) {
 		char *cap_string;
@@ -420,7 +420,7 @@
 		g_print ("No channels set in these caps\n%s", cap_string);
 		g_free (cap_string);
 		return FALSE;
-	} 
+	}
 
 	/* Set the values on the sample */
 	if (priv->sample) {

Modified: trunk/marlin/marlin-program.c
==============================================================================
--- trunk/marlin/marlin-program.c	(original)
+++ trunk/marlin/marlin-program.c	Tue Dec 23 22:12:50 2008
@@ -2,7 +2,7 @@
 /*
  *  Authors: Iain Holmes <iain gnome org>
  *
- *  Copyright 2003 - 2006 Iain Holmes
+ *  Copyright 2003 - 2008 Iain Holmes
  *
  *  This file is free software; you can redistribute it and/or
  *  modify it under the terms of version 2 of the GNU Library General Public
@@ -126,8 +126,29 @@
 marlin_program_init (MarlinProgram *program)
 {
 	MarlinProgramPrivate *priv;
+	jack_options_t options = JackNullOption;
+	jack_status_t status;
 
 	priv = program->priv = GET_PRIVATE (program);
+
+	priv->client = jack_client_open ("marlin", options,
+					 &status, NULL);
+	if (priv->client == NULL) {
+		g_warning ("Could not start Jack server");
+	} else {
+		priv->player = marlin_jack_play_new (priv->client);
+		priv->recorder = marlin_jack_record_new (priv->client);
+
+		if (status & JackServerStarted) {
+			g_print ("Jack server started\n");
+		}
+
+		if (status & JackNameNotUnique) {
+			char *client_name = jack_get_client_name (priv->client);
+			g_print ("Unique name %s assigned\n", client_name);
+		}
+	}
+
 	priv->current_owner = MARLIN_PROGRAM_JACK_UNOWNED;
 	priv->owner_count = 0;
 }
@@ -220,7 +241,7 @@
 /**
  * marlin_program_get_clip_source:
  * @program:
- * 
+ *
  * Obtains the source of the clipboard.
  * FIXME: Should this be combined with get_clipboard?
  */
@@ -234,7 +255,7 @@
 /**
  * marlin_program_play_clipboard:
  * @program:
- * 
+ *
  * Starts the clipboard playing.
  */
 void
@@ -246,7 +267,7 @@
 #endif
 }
 
-/** 
+/**
  * marlin_program_stop_clipboard:
  * @program:
  *
@@ -265,7 +286,7 @@
  * marlin_program_request_new_view:
  * @program: A #MarlinProgram.
  * @sample: A #MarlinSample.
- * 
+ *
  * Requests that a new view be created for @sample.
  */
 void
@@ -286,6 +307,9 @@
 	return (++priv->owner_count);
 }
 
+/**
+ * marlin_program_acquire_jack
+ */
 void
 marlin_program_acquire_jack (MarlinProgram *program,
 			     guint          owner_id)
@@ -296,10 +320,19 @@
 		return;
 	}
 
+	if (marlin_jack_is_busy (priv->player) ||
+	    marlin_jack_is_busy (priv->recorder)) {
+		/* Jack is busy so cannot be acquired */
+		return;
+	}
+
 	priv->current_owner = owner_id;
 	g_signal_emit (program, signals[JACK_OWNER_CHANGED], 0, owner_id);
 }
 
+/**
+ * marlin_program_release_jack:
+ */
 void
 marlin_program_release_jack (MarlinProgram *program,
 			     guint          owner_id)
@@ -314,3 +347,45 @@
 	g_signal_emit (program, signals[JACK_OWNER_CHANGED], 0,
 		       MARLIN_PROGRAM_JACK_UNOWNED);
 }
+
+/**
+ * marlin_program_get_player:
+ */
+MarlinJack *
+marlin_program_get_player (MarlinProgram *program)
+{
+	MarlinProgramPrivate *priv = program->priv;
+
+	if (priv->player) {
+		return (MarlinJack *) g_object_ref (priv->player);
+	} else {
+		return NULL;
+	}
+}
+
+/**
+ * marlin_program_get_recorder:
+ */
+MarlinJack *
+marlin_program_get_recorder (MarlinProgram *program)
+{
+	MarlinProgramPrivate *priv = program->priv;
+
+	if (priv->recorder) {
+		return (MarlinJack *) g_object_ref (priv->recorder);
+	} else {
+		return NULL;
+	}
+}
+
+/**
+ * marlin_program_get_jack_owner:
+ * @program:
+ */
+guint
+marlin_program_get_jack_owner (MarlinProgram *program)
+{
+	MarlinProgramPrivate *priv = program->priv;
+
+	return priv->current_owner;
+}

Modified: trunk/marlin/marlin-program.h
==============================================================================
--- trunk/marlin/marlin-program.h	(original)
+++ trunk/marlin/marlin-program.h	Tue Dec 23 22:12:50 2008
@@ -25,6 +25,7 @@
 
 #include <glib-object.h>
 
+#include <marlin/marlin-jack.h>
 #include <marlin/marlin-sample.h>
 
 #define MARLIN_PROGRAM_TYPE (marlin_program_get_type ())
@@ -64,6 +65,15 @@
 void marlin_program_request_new_view (MarlinProgram *program,
 				      MarlinSample *sample);
 
-int marlin_program_get_jack_owner_id (MarlinProgram *program);
+guint marlin_program_request_jack_owner_id (MarlinProgram *program);
+void marlin_program_acquire_jack (MarlinProgram *program,
+				  guint          owner_id);
+void marlin_program_release_jack (MarlinProgram *program,
+				  guint          owner_id);
+
+guint marlin_program_get_jack_owner (MarlinProgram *program);
+
+MarlinJack *marlin_program_get_player (MarlinProgram *program);
+MarlinJack *marlin_program_get_recorder (MarlinProgram *program);
 
 #endif

Modified: trunk/src/marlin-record.c
==============================================================================
--- trunk/src/marlin-record.c	(original)
+++ trunk/src/marlin-record.c	Tue Dec 23 22:12:50 2008
@@ -35,7 +35,7 @@
 #include <marlin/marlin-time-line.h>
 #include <marlin/marlin-stock.h>
 #include <marlin/marlin-jack-record.h>
-
+#include <marlin/marlin-program.h>
 #include <marlin/marlin-position-spinner.h>
 #include <marlin/marlin-utils.h>
 #include <marlin/marlin-types.h>
@@ -53,7 +53,7 @@
 
 typedef struct _RecordData {
 	GtkWidget *dialog;
-	
+
 	GtkWindow *parent_window;
 	MarlinSample *sample;
 	MarlinJack *recorder;
@@ -87,7 +87,7 @@
 		 RecordData *rd)
 {
 	int display;
-	
+
 	switch (response_id) {
 	case GTK_RESPONSE_HELP:
 		marlin_display_help ("marlin-record-dialog");
@@ -485,7 +485,7 @@
 		return;
 	}
 	rd->state = GR_PLAYING;
-#if 0		
+#if 0
 	marlin_pipeline_set_state (MARLIN_PIPELINE (rd->play_pipeline),
 				   GST_STATE_PLAYING);
 #endif
@@ -542,7 +542,7 @@
 	}
 	rd->state = GR_NOTHING;
 	gtk_label_set_text (GTK_LABEL (rd->status), _("Ready"));
-	
+
 	gtk_widget_set_sensitive (rd->stop, FALSE);
 
 	gtk_widget_set_sensitive (rd->record, TRUE);
@@ -561,9 +561,9 @@
 		  RecordData *rd)
 {
 	gtk_label_set_text (GTK_LABEL (rd->status), _("Ready"));
-	
+
 	rd->state = GR_NOTHING;
-	
+
 	gtk_widget_set_sensitive (rd->stop, FALSE);
 
 	gtk_widget_set_sensitive (rd->record, TRUE);
@@ -624,10 +624,12 @@
 	gtk_vumeter_set_levels (GTK_VUMETER (vumeter), rms, peak);
 }
 #endif
+
 GtkWidget *
 marlin_record_new (GtkWindow *parent_window)
 {
 	RecordData *rd = NULL;
+	MarlinProgram *program;
 	MarlinSample *window_sample;
 	GtkWidget *vbox, *hbox, *main_vb, *inner_vb, *inner_hb, *spacer, *label;
 	GtkWidget *iivb, *iihb, *position_hb;
@@ -652,7 +654,8 @@
 		      "channels", channels,
 		      NULL);
 
-	rd->recorder = (MarlinJack *) marlin_jack_record_new ("marlin-record", NULL, NULL);
+	program = marlin_program_get_default ();
+	rd->recorder = (MarlinJack *) marlin_program_get_recorder (program);
 	if (rd->recorder) {
 		g_object_set (G_OBJECT (rd->recorder),
 			      "sample", rd->sample,

Modified: trunk/src/marlin-window.c
==============================================================================
--- trunk/src/marlin-window.c	(original)
+++ trunk/src/marlin-window.c	Tue Dec 23 22:12:50 2008
@@ -160,6 +160,8 @@
 	GObject *ui_merge;
 
 	MarlinJackPlay *jack;
+	guint jack_owner_id;
+	guint32 owner_changed_id;
 
 	MarlinState state;
 	guint64 initial; /* The initial position of the cursor when play
@@ -195,27 +197,29 @@
 };
 
 static void set_path_sensitive (GtkActionGroup *ag,
-				const char *name,
-				gboolean sensitive);
+				const char     *name,
+				gboolean        sensitive);
 static void set_marker_popup_sensitive (MarlinWindow *window,
-					gboolean sensitive);
+					gboolean      sensitive);
 
 void marlin_window_set_file_sensitive (MarlinWindow *window,
-				       gboolean sensitive);
+				       gboolean      sensitive);
+void marlin_window_set_jack_sensitive (MarlinWindow *window,
+				       gboolean      sensitive);
 void marlin_window_set_media_bar_sensitive (MarlinWindow *window,
-					    gboolean sensitive);
+					    gboolean      sensitive);
 void marlin_window_set_tools_sensitive (MarlinWindow *window,
-					gboolean sensitive);
+					gboolean      sensitive);
 void marlin_window_set_view_sensitive (MarlinWindow *window,
-				       gboolean sensitive);
+				       gboolean      sensitive);
 void marlin_window_set_edit_sensitive (MarlinWindow *window,
-				       gboolean sensitive);
+				       gboolean      sensitive);
 void marlin_window_set_selection_sensitive (MarlinWindow *window,
-					    gboolean sensitive);
+					    gboolean      sensitive);
 void marlin_window_set_process_sensitive (MarlinWindow *window,
-					  gboolean sensitive);
+					  gboolean      sensitive);
 void marlin_window_set_plugins_sensitive (MarlinWindow *window,
-					  gboolean sensitive);
+					  gboolean      sensitive);
 void marlin_window_set_process_name (MarlinWindow *window);
 void marlin_window_set_edit_name (MarlinWindow *window);
 void marlin_window_pause_sample (MarlinWindow *window);
@@ -300,6 +304,14 @@
 	}
 
 	if (priv->jack != NULL) {
+		MarlinProgram *program;
+
+		program = marlin_program_get_default ();
+		g_signal_handler_disconnect (program, priv->owner_changed_id);
+
+		/* Give up our jack ownership */
+		marlin_program_release_jack (program, priv->jack_owner_id);
+
 		g_object_unref (priv->jack);
 		priv->jack = NULL;
 	}
@@ -385,36 +397,36 @@
 		guint64 fpm, fpb;
 		guint rate, bpm;
 		guint64 ms;
-		
+
 		switch (window->priv->position_display) {
 		case MARLIN_DISPLAY_FRAMES:
 			s_display = g_strdup_printf ("%llu", sel_start);
 			e_display = g_strdup_printf ("%llu", sel_finish);
 			break;
-			
+
 		case MARLIN_DISPLAY_TIME_LONG:
 			g_object_get (G_OBJECT (window->priv->sample),
 				      "sample_rate", &rate,
 				      NULL);
-			
+
 			ms = marlin_frames_to_ms (sel_start, rate);
 			s_display = marlin_ms_to_time_string (ms);
-			
+
 			ms = marlin_frames_to_ms (sel_finish, rate);
 			e_display = marlin_ms_to_time_string (ms);
 			break;
-			
+
 		case MARLIN_DISPLAY_SECONDS:
 			g_object_get (G_OBJECT (window->priv->sample),
 				      "sample_rate", &rate,
 				      NULL);
-			
+
 			ms = marlin_frames_to_ms (sel_start, rate);
 			s_display = g_strdup_printf ("%.3f", (double)ms / 1000.0);
 			ms = marlin_frames_to_ms (sel_finish, rate);
 			e_display = g_strdup_printf ("%.3f", (double)ms / 1000.0);
 			break;
-			
+
 		case MARLIN_DISPLAY_TIME_FRAMES:
 			g_object_get (G_OBJECT (window->priv->sample),
 				      "sample_rate", &rate,
@@ -435,7 +447,7 @@
 
 			fpm = rate * 60;
 			fpb = fpm / bpm;
-			
+
 			s_display = g_strdup_printf ("%llu", sel_start / fpb);
 			e_display = g_strdup_printf ("%llu", sel_finish / fpb);
 
@@ -444,16 +456,16 @@
 			e_display = NULL;
 			break;
 		}
-		
+
 		gtk_statusbar_pop (GTK_STATUSBAR (window->priv->sel_start_status), 0);
 		gtk_statusbar_pop (GTK_STATUSBAR (window->priv->sel_end_status), 0);
 		gtk_statusbar_push (GTK_STATUSBAR (window->priv->sel_start_status), 0, s_display);
 		gtk_statusbar_push (GTK_STATUSBAR (window->priv->sel_end_status), 0, e_display);
-		
+
 		g_free (s_display);
 		g_free (e_display);
 	}
-	
+
 	/* Edit works out what needs to be sensitive... */
 	marlin_window_set_edit_sensitive (window, TRUE);
 	marlin_window_set_selection_sensitive (window, TRUE);
@@ -466,8 +478,8 @@
 
 static void
 marker_added (MarlinMarkerModel *model,
-	      MarlinMarker *marker,
-	      MarlinWindow *window)
+	      MarlinMarker      *marker,
+	      MarlinWindow      *window)
 {
 	marlin_window_set_file_sensitive (window, TRUE);
 	marlin_window_set_process_sensitive (window, TRUE);
@@ -476,8 +488,8 @@
 
 static void
 marker_removed (MarlinMarkerModel *model,
-		MarlinMarker *marker,
-		MarlinWindow *window)
+		MarlinMarker      *marker,
+		MarlinWindow      *window)
 {
 	marlin_window_set_file_sensitive (window, TRUE);
 	marlin_window_set_process_sensitive (window, TRUE);
@@ -486,7 +498,7 @@
 
 static void
 undo_changed (MarlinUndoManager *manager,
-	      MarlinWindow *window)
+	      MarlinWindow      *window)
 {
 	marlin_window_set_edit_sensitive (window, TRUE);
 	marlin_window_set_plugins_sensitive (window, TRUE);
@@ -494,10 +506,10 @@
 }
 
 static void
-set_property (GObject *object,
-	      guint prop_id,
+set_property (GObject      *object,
+	      guint         prop_id,
 	      const GValue *value,
-	      GParamSpec *pspec)
+	      GParamSpec   *pspec)
 {
 	MarlinWindow *window;
 	MarlinWindowPrivate *priv;
@@ -573,7 +585,7 @@
 						       "changed",
 						       G_CALLBACK (selection_changed),
 						       window);
-		
+
 		marlin_window_set_title (window, priv->sample);
 
 		/* If we have frames, then we have a sample that contains
@@ -590,7 +602,7 @@
 
 		marlin_window_set_process_name (window);
 		marlin_window_set_edit_name (window);
-		
+
 		break;
 
 	default:
@@ -599,9 +611,9 @@
 }
 
 static void
-get_property (GObject *object,
-	      guint prop_id,
-	      GValue *value,
+get_property (GObject    *object,
+	      guint       prop_id,
+	      GValue     *value,
 	      GParamSpec *pspec)
 {
 	MarlinWindow *window;
@@ -618,18 +630,45 @@
 	}
 }
 
+static gboolean
+focus_in_event (GtkWidget     *widget,
+		GdkEventFocus *event)
+{
+	MarlinWindow *window = (MarlinWindow *) widget;
+	MarlinWindowPrivate *priv = window->priv;
+	MarlinProgram *program = marlin_program_get_default ();
+
+	/* Will emit jack-owner-changed signal if window is allowed to
+	   own jack */
+	marlin_program_acquire_jack (program, priv->jack_owner_id);
+
+	return FALSE;
+}
+
+static gboolean
+focus_out_event (GtkWidget     *widget,
+		 GdkEventFocus *event)
+{
+	return FALSE;
+}
+
 static void
 marlin_window_class_init (MarlinWindowClass *klass)
 {
 	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
 
-	object_class = G_OBJECT_CLASS (klass);
+	object_class = (GObjectClass *) klass;
+	widget_class = (GtkWidgetClass *) klass;
 
 	object_class->finalize = finalize;
 	object_class->dispose = dispose;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 
+	widget_class->focus_in_event = focus_in_event;
+	widget_class->focus_out_event = focus_out_event;
+
 	g_type_class_add_private (object_class, sizeof (MarlinWindowPrivate));
 	g_object_class_install_property (object_class,
 					 PROP_SAMPLE,
@@ -640,7 +679,7 @@
 
 static void
 add_widget (GtkUIManager *merge,
-	    GtkWidget *widget,
+	    GtkWidget    *widget,
 	    MarlinWindow *window)
 {
 	if (GTK_IS_MENU_SHELL (widget)) {
@@ -658,7 +697,7 @@
 }
 
 static void
-menu_item_select_cb (GtkMenuItem *proxy,
+menu_item_select_cb (GtkMenuItem  *proxy,
 		     MarlinWindow *window)
 {
 	GtkAction *action;
@@ -678,7 +717,7 @@
 }
 
 static void
-menu_item_deselect_cb (GtkMenuItem *proxy,
+menu_item_deselect_cb (GtkMenuItem  *proxy,
 		       MarlinWindow *window)
 {
 	if (window->priv->message_status) {
@@ -689,8 +728,8 @@
 
 static void
 connect_proxy_cb (GtkUIManager *manager,
-		  GtkAction *action,
-		  GtkWidget *proxy,
+		  GtkAction    *action,
+		  GtkWidget    *proxy,
 		  MarlinWindow *window)
 {
 	if (GTK_IS_MENU_ITEM (proxy)) {
@@ -703,8 +742,8 @@
 
 static void
 disconnect_proxy_cb (GtkUIManager *manager,
-		     GtkAction *action,
-		     GtkWidget *proxy,
+		     GtkAction    *action,
+		     GtkWidget    *proxy,
 		     MarlinWindow *window)
 {
 	if (GTK_IS_MENU_ITEM (proxy)) {
@@ -826,7 +865,7 @@
 
 static void
 set_position (MarlinBaseWindow *window,
-	      guint64 position)
+	      guint64           position)
 {
 	g_object_set (G_OBJECT (MARLIN_WINDOW (window)->priv->view),
 		      "cursor_position", position,
@@ -863,15 +902,15 @@
 }
 
 static void
-statusbar_set_frames (GtkWidget *statusbar,
+statusbar_set_frames (GtkWidget    *statusbar,
 		      MarlinWindow *window,
-		      guint64 frames)
+		      guint64       frames)
 {
 	MarlinWindowPrivate *priv = window->priv;
 	guint rate, bpm;
 	guint64 ms, fpb, fpm;
 	char *display = NULL;
-	
+
 	if (priv->sample) {
 		g_object_get (G_OBJECT (priv->sample),
 			      "sample_rate", &rate,
@@ -921,8 +960,8 @@
 
 static void
 marlin_window_change_overview_bar_fpp (MarlinSampleView *view,
-				       guint frames_per_pixel,
-				       MarlinWindow *window)
+				       guint             frames_per_pixel,
+				       MarlinWindow     *window)
 {
 	g_object_set (G_OBJECT (window->priv->overview_bar),
 		      "frames_per_page", (guint64) frames_per_pixel * GTK_WIDGET (view)->allocation.width,
@@ -931,16 +970,16 @@
 	g_object_set (G_OBJECT (window->priv->marker_view),
 		      "frames_per_pixel", frames_per_pixel,
 		      NULL);
-	
+
 	marlin_window_set_view_sensitive (window, TRUE);
 	marlin_window_set_plugins_sensitive (window, TRUE);
 }
 
 static void
 view_vzoom_changed (MarlinSampleView *view,
-		    float vmax,
-		    float vmin,
-		    MarlinWindow *window)
+		    float             vmax,
+		    float             vmin,
+		    MarlinWindow     *window)
 {
 	marlin_window_set_view_sensitive (window, TRUE);
 	marlin_window_set_plugins_sensitive (window, TRUE);
@@ -950,8 +989,8 @@
 
 static void
 marlin_window_page_start_changed (MarlinSampleView *view,
-				  guint64 start_frame,
-				  MarlinWindow *window)
+				  guint64           start_frame,
+				  MarlinWindow     *window)
 {
 	guint frames_per_pixel;
 
@@ -966,15 +1005,15 @@
 
 static void
 marlin_window_view_size_allocate (MarlinSampleView *view,
-				  GtkAllocation *allocation,
-				  MarlinWindow *window)
+				  GtkAllocation    *allocation,
+				  MarlinWindow     *window)
 {
 	guint frames_per_pixel;
-	
+
 	g_object_get (G_OBJECT (view),
-		      "frames_per_pixel", &frames_per_pixel,		      
+		      "frames_per_pixel", &frames_per_pixel,
 		      NULL);
-	
+
 	g_object_set (G_OBJECT (window->priv->overview_bar),
 		      "frames_per_page", (guint64) frames_per_pixel * allocation->width,
 		      NULL);
@@ -982,8 +1021,8 @@
 
 static void
 marlin_window_overview_bar_start_changed (MarlinOverviewBar *overview_bar,
-					  guint64 start,
-					  MarlinWindow *window)
+					  guint64            start,
+					  MarlinWindow      *window)
 {
 	marlin_sample_view_scroll_to (window->priv->view, start);
 }
@@ -991,14 +1030,14 @@
 /* Grr, annoyingly ugly prototype */
 static void
 marlin_window_view_move_cursor (MarlinSampleView *view,
-				GtkMovementStep step,
-				int count,
-				gboolean extend_selection,
-				MarlinWindow *window);
+				GtkMovementStep   step,
+				int               count,
+				gboolean          extend_selection,
+				MarlinWindow     *window);
 static void
 marlin_window_overview_bar_cursor_changed (MarlinOverviewBar *overview_bar,
-				       guint64 position,
-				       MarlinWindow *window)
+					   guint64            position,
+					   MarlinWindow      *window)
 {
 	/* We need to turn off this signal, otherwise we get into
 	   a loop of the overview_bar emitting the signal and setting the
@@ -1020,10 +1059,10 @@
 
 static void
 marlin_window_view_move_cursor (MarlinSampleView *view,
-				GtkMovementStep step,
-				int count,
-				gboolean extend_selection,
-				MarlinWindow *window)
+				GtkMovementStep   step,
+				int               count,
+				gboolean          extend_selection,
+				MarlinWindow     *window)
 {
 	guint64 view_pos;
 
@@ -1034,7 +1073,7 @@
 	/* Change the position in the status bar */
 	statusbar_set_frames (window->priv->position_status,
 			      window, (guint64) view_pos);
-	
+
 	/* We need to turn off this signal, otherwise we get into
 	   a loop of the overview_bar emitting the signal and setting the
 	   view's cursor, which then gets back in here, and goes on */
@@ -1042,7 +1081,7 @@
 					 G_SIGNAL_MATCH_FUNC,
 					 0, 0, NULL,
 					 G_CALLBACK (marlin_window_overview_bar_cursor_changed), NULL);
-	
+
 	g_object_set (G_OBJECT (window->priv->overview_bar),
 		      "cursor_position", (guint64) view_pos,
 		      NULL);
@@ -1058,28 +1097,20 @@
 {
 	g_print ("play eos\n");
 	window->priv->state = MARLIN_STATE_STOPPED;
-	
-	g_object_set (G_OBJECT (window->priv->view), 
+
+	g_object_set (G_OBJECT (window->priv->view),
 		      "show_play_cursor", FALSE,
 		      NULL);
 
 	marlin_window_move_cursor_to (window, window->priv->initial);
 
-	/* -96.0 is the MIN_DB in src/other/gtkvumeter.c 
-	   Should be a public constant */
 	gtk_vumeter_set_levels (GTK_VUMETER (window->priv->left_vu), 0.0, 0.0);
 	gtk_vumeter_set_levels (GTK_VUMETER (window->priv->right_vu), 0.0, 0.0);
-
-#if 0
-	if (window->priv->repeating) {
-		marlin_play_pipeline_set_repeat (pipeline, FALSE);
-	}
-#endif
 }
 
 static void
-position_changed (MarlinJack *jack,
-		  guint64 position,
+position_changed (MarlinJack   *jack,
+		  guint64       position,
 		  MarlinWindow *window)
 {
 /* 	marlin_window_move_cursor_to (window, position); */
@@ -1090,7 +1121,7 @@
 
 static void
 change_position_display (GtkCheckMenuItem *item,
-			 MarlinWindow *window)
+			 MarlinWindow     *window)
 {
 	MarlinWindowPrivate *priv = window->priv;
 	GConfClient *client;
@@ -1133,7 +1164,7 @@
 
 static void
 attach_popup_menu (MarlinWindow *window,
-		   GtkWidget *widget)
+		   GtkWidget    *widget)
 {
 	static GtkWidget *menu = NULL;
 	MarlinDisplay pd;
@@ -1167,8 +1198,8 @@
 
 static gboolean
 view_key_press (MarlinSampleView *view,
-		GdkEventKey *event,
-		MarlinWindow *window)
+		GdkEventKey      *event,
+		MarlinWindow     *window)
 {
 	MarlinWindowPrivate *priv = window->priv;
 	MarlinUndoContext *ctxt;
@@ -1223,14 +1254,14 @@
 }
 
 static void
-drag_data_received (GObject *object,
-		    GdkDragContext *context,
-		    int x,
-		    int y,
+drag_data_received (GObject          *object,
+		    GdkDragContext   *context,
+		    int               x,
+		    int               y,
 		    GtkSelectionData *selection,
-		    guint info,
-		    guint time,
-		    gpointer data)
+		    guint             info,
+		    guint             time,
+		    gpointer          data)
 {
 	MarlinWindow *window;
 	char *tmp, *filename, **filenames;
@@ -1265,7 +1296,7 @@
 
 static void
 clip_changed (MarlinProgram *program,
-	      MarlinWindow *window)
+	      MarlinWindow  *window)
 {
 	if (marlin_program_get_clipboard (program) == NULL) {
 		marlin_window_set_edit_sensitive (window, FALSE);
@@ -1278,10 +1309,11 @@
 	}
 }
 
+/* Attach a popup menu from the UI xml to a widget */
 static void
 attach_menu (MarlinWindow *window,
-	     GtkWidget *widget,
-	     const char *menu_name)
+	     GtkWidget    *widget,
+	     const char   *menu_name)
 {
 	GtkWidget *menu;
 
@@ -1310,16 +1342,16 @@
 
 static void
 marker_view_move_cursor (MarlinMarkerView *view,
-			 guint64 position,
-			 MarlinWindow *window)
+			 guint64           position,
+			 MarlinWindow     *window)
 {
 	marlin_window_move_cursor_to (window, position);
 }
 
 static void
 overview_bar_play_request (MarlinOverviewBar *bar,
-			   guint64 start,
-			   MarlinWindow *window)
+			   guint64            start,
+			   MarlinWindow      *window)
 {
 	guint64 end;
 
@@ -1331,10 +1363,10 @@
 }
 
 static void
-level_cb (MarlinJack *jack,
-	  int         channels,
-	  double     *rms,
-	  double     *peak,
+level_cb (MarlinJack   *jack,
+	  int           channels,
+	  double       *rms,
+	  double       *peak,
 	  MarlinWindow *window)
 {
 	GtkWidget *vumeter;
@@ -1351,7 +1383,7 @@
 
 void
 marlin_window_set_icon (MarlinWindow *window,
-			GdkPixbuf *icon)
+			GdkPixbuf    *icon)
 {
 	if (window_icon == NULL) {
 		char *filename;
@@ -1370,8 +1402,8 @@
 
 static void
 baseline_changed (MarlinLevelRuler *ruler,
-		  int base_offset,
-		  MarlinWindow *window)
+		  int               base_offset,
+		  MarlinWindow     *window)
 {
 	g_object_set (G_OBJECT (window->priv->view),
 		      "base_offset", base_offset,
@@ -1380,8 +1412,8 @@
 
 static void
 marker_view_enter_marker (MarlinMarkerView *marker_view,
-			  MarlinMarker *marker,
-			  MarlinWindow *window)
+			  MarlinMarker     *marker,
+			  MarlinWindow     *window)
 {
 	window->priv->mv_in_marker = TRUE;
 	window->priv->current_marker = marker;
@@ -1420,6 +1452,19 @@
 	gtk_widget_destroy (dialog);
 }
 
+static void
+jack_owner_changed_cb (MarlinProgram *program,
+		       guint          jack_owner,
+		       MarlinWindow  *window)
+{
+	MarlinWindowPrivate *priv = window->priv;
+
+	/* If we are the jack owner then turn on the
+	   play/pause/record actions */
+	marlin_window_set_jack_sensitive (window,
+					  priv->jack_owner_id == jack_owner);
+}
+
 MarlinWindow *
 marlin_window_new (void)
 {
@@ -1432,11 +1477,11 @@
 	GConfClient *client = marlin_gconf_get_default ();
 	gboolean snap;
 	MarlinScale scale;
-	
+
 	window = g_object_new (MARLIN_WINDOW_TYPE, NULL);
 	priv = window->priv;
 
-	gtk_window_set_default_size (GTK_WINDOW (window), 
+	gtk_window_set_default_size (GTK_WINDOW (window),
 				     DEFAULT_WIDTH, DEFAULT_HEIGHT);
 
 	/* DND support */
@@ -1465,7 +1510,7 @@
 			  window);
 	g_signal_connect (G_OBJECT (priv->overview_bar), "play-request",
 			  G_CALLBACK (overview_bar_play_request), window);
-	
+
 	gtk_box_pack_start (GTK_BOX (priv->main_vbox),
 			    GTK_WIDGET (priv->overview_bar),
 			    FALSE, FALSE, 0);
@@ -1475,7 +1520,7 @@
 	   vertical ruler | sample view      | VU
 	                  | Scrollbar.       | ^^
 	*/
-	   
+
 	table = gtk_table_new (3, 3, FALSE);
 	gtk_box_pack_start (GTK_BOX (priv->main_vbox), table, TRUE, TRUE, 0);
 
@@ -1514,7 +1559,7 @@
 	/* Create the scrollbar here so we can use it's adjustment for
 	   the scrolled window */
 	priv->hscrollbar = gtk_hscrollbar_new (NULL);
-	
+
 	sw = gtk_scrolled_window_new (GTK_RANGE (priv->hscrollbar)->adjustment, NULL);
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 					GTK_POLICY_NEVER,
@@ -1529,7 +1574,7 @@
 				   "frames_per_pixel", 4096,
 				   "undo_manager", priv->undo,
 				   NULL);
-	
+
 	g_signal_connect (G_OBJECT (priv->view), "key-press-event",
 			  G_CALLBACK (view_key_press), window);
 	gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (priv->view));
@@ -1539,7 +1584,7 @@
 			  GTK_FILL | GTK_EXPAND,
 			  GTK_FILL | GTK_EXPAND,
 			  0, 0);
-	
+
 	g_signal_connect (G_OBJECT (priv->view), "frames-per-pixel-changed",
 			  G_CALLBACK (marlin_window_change_overview_bar_fpp),
 			  window);
@@ -1554,20 +1599,20 @@
 			  window);
 	g_signal_connect (G_OBJECT (priv->view), "vzoom-changed",
 			  G_CALLBACK (view_vzoom_changed), window);
-	
+
 	gtk_table_attach (GTK_TABLE (table), priv->hscrollbar,
 			  1, 2, 2, 3,
 			  GTK_FILL | GTK_EXPAND,
 			  GTK_FILL,
 			  0, 0);
-	
+
 	priv->meters_event = gtk_event_box_new ();
 	gtk_table_attach (GTK_TABLE (table), priv->meters_event,
 			  2, 3, 0, 3,
 			  GTK_FILL,
 			  GTK_FILL,
 			  0, 0);
-	
+
 	vu = gtk_hbox_new (TRUE, 6);
 	gtk_container_add (GTK_CONTAINER (priv->meters_event), vu);
 
@@ -1592,7 +1637,7 @@
 	statusbar = gtk_hbox_new (FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (priv->main_vbox), statusbar, FALSE, FALSE, 0);
 	gtk_widget_show (statusbar);
-	
+
 	/* The status bars */
 	/* Message bar */
 	priv->message_status = gtk_statusbar_new ();
@@ -1615,7 +1660,7 @@
 	gtk_widget_show_all (ev);
 
 	gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (priv->position_status), FALSE);
-	
+
 	gtk_box_pack_start (GTK_BOX (statusbar), ev, FALSE, FALSE, 0);
 
 	/* Selection start */
@@ -1630,7 +1675,7 @@
 	gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (priv->sel_start_status), FALSE);
 
 	gtk_box_pack_start (GTK_BOX (statusbar), ev, FALSE, FALSE, 0);
-	
+
 	priv->sel_end_status = gtk_statusbar_new ();
 	gtk_widget_set_size_request (priv->sel_end_status, 100, -1);
 
@@ -1662,8 +1707,18 @@
 
 	gtk_widget_show (priv->main_vbox);
 
-	priv->jack = marlin_jack_play_new ("marlin-window", NULL, NULL);
+	priv->jack = (MarlinJackPlay *) marlin_program_get_player (program);
+
 	if (priv->jack) {
+		/* If we have jack, then we want to have an owner ID
+		   and listen for when we gain or lose ownership */
+		priv->jack_owner_id =
+			marlin_program_request_jack_owner_id (program);
+		priv->owner_changed_id =
+			g_signal_connect (program, "jack-owner-changed",
+					  G_CALLBACK (jack_owner_changed_cb),
+					  window);
+
 		g_signal_connect (priv->jack, "eos",
 				  G_CALLBACK (play_eos), window);
 
@@ -1676,7 +1731,6 @@
 
 		g_signal_connect (priv->jack, "position-changed",
 				  G_CALLBACK (position_changed), window);
-		set_path_sensitive (priv->ui_action, "MediaRecord", TRUE);
 	} else {
 		display_no_jack_window (GTK_WIDGET (window));
 		set_path_sensitive (priv->ui_action, "MediaRecord", FALSE);
@@ -1707,14 +1761,14 @@
 	MarlinWindow *window;
 	GConfClient *client;
 	int x, y, width, height, cursor_position;
-	
+
 	window = marlin_window_new ();
 	g_object_set (G_OBJECT (window),
 		      "sample", sample,
 		      NULL);
 
 	client = gconf_client_get_default ();
-	
+
 	/* Restore state */
 	x = get_int (client, uuid, "x");
 	y = get_int (client, uuid, "y");
@@ -1730,7 +1784,7 @@
 		      NULL);
 
 	g_object_unref (G_OBJECT (client));
-	
+
 	return window;
 }
 
@@ -1746,7 +1800,7 @@
 		      "dirty", &dirty,
 		      "writable", &writable,
 		      NULL);
-	
+
 	if (filename == NULL) {
 		title = g_strdup (_("Marlin Sample Editor"));
 	} else {
@@ -1792,7 +1846,7 @@
 time_to_str (time_t length)
 {
 	int mins;
-	
+
 	if (length < 60) {
 		return g_strdup_printf (ngettext ("If you close without saving, changes from the last second will be discarded.",
 						  "If you close without saving, changes from the last %d seconds will be discarded.", length), length);
@@ -1812,14 +1866,14 @@
 	char *basename, *time_str;
 	char *bold;
 	time_t now;
-	
+
 	g_object_get (G_OBJECT (window->priv->sample),
 		      "filename", &filename,
 		      NULL);
 
 	now = time (NULL);
 	time_str = time_to_str (now - window->priv->last_save);
-	
+
 	basename = g_path_get_basename (filename);
 
 	bold = g_strdup_printf (_("Save changes made to \"%s\" before closing?"),
@@ -1849,10 +1903,10 @@
 	gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (mess)->label), TRUE);
 	gtk_label_set_line_wrap (GTK_LABEL (GTK_MESSAGE_DIALOG (mess)->label), FALSE);
 	gtk_label_set_justify (GTK_LABEL (GTK_MESSAGE_DIALOG (mess)->label), GTK_JUSTIFY_LEFT);
-	
+
 	gtk_widget_show (mess);
 }
-		
+
 gboolean
 marlin_window_can_close (MarlinWindow *window)
 {
@@ -1861,13 +1915,6 @@
 
 	priv = window->priv;
 
-#if 0
-	if (priv->play_pipeline) {
-		gst_element_set_state (GST_ELEMENT (priv->play_pipeline), 
-				       GST_STATE_READY);
-	}
-#endif
-
 	g_object_get (G_OBJECT (priv->sample),
 		      "dirty", &dirty,
 		      NULL);
@@ -1875,7 +1922,7 @@
 	if (dirty) {
 		maybe_save_quit (window);
 	}
-	
+
 	return dirty;
 }
 
@@ -1888,12 +1935,7 @@
 
 	priv = window->priv;
 
-#if 0
-	if (priv->play_pipeline) {
-		gst_element_set_state (GST_ELEMENT (priv->play_pipeline), 
-				       GST_STATE_READY);
-	}
-#endif
+	/* FIXME: Should stop playing here */
 
 	if (marlin_window_can_close (window) == FALSE) {
 		gtk_widget_destroy (GTK_WIDGET (window));
@@ -2003,30 +2045,41 @@
 	}
 
 	ag = priv->ui_action;
-	
+
 	set_path_sensitive (ag, "FileSave", dirty && writable);
 	set_path_sensitive (ag, "FileSaveAs", sensitive);
  	set_path_sensitive (ag, "FileProperties", sensitive);
 }
 
 void
-marlin_window_set_media_bar_sensitive (MarlinWindow *window,
-				       gboolean sensitive)
+marlin_window_set_jack_sensitive (MarlinWindow *window,
+				  gboolean      sensitive)
 {
-	MarlinWindowPrivate *priv;
+	MarlinWindowPrivate *priv = window->priv;
 	GtkActionGroup *ag;
+	guint64 total_frames;
 
-	priv = window->priv;
 	ag = priv->ui_action;
 
-	if (priv->jack == NULL) {
+	/* MediaRecord only depends on jack being present */
+	if (priv->jack == FALSE) {
 		sensitive = FALSE;
 	}
 
-	set_path_sensitive (ag, "MediaPrevious", sensitive);
-	set_path_sensitive (ag, "MediaNext", sensitive);
-	set_path_sensitive (ag, "MediaForward", sensitive);
-	set_path_sensitive (ag, "MediaRewind", sensitive);
+	set_path_sensitive (priv->ui_action, "MediaRecord", sensitive);
+
+	if (priv->sample) {
+		g_object_get (priv->sample,
+			      "total-frames", &total_frames,
+			      NULL);
+	} else {
+		total_frames = 0;
+	}
+
+	/* The playback depends on how many frames there are */
+	if (total_frames == 0) {
+		sensitive = FALSE;
+	}
 
 	set_path_sensitive (ag, "MediaPlay", sensitive);
 	set_path_sensitive (ag, "MediaRepeat", sensitive);
@@ -2035,6 +2088,23 @@
 }
 
 void
+marlin_window_set_media_bar_sensitive (MarlinWindow *window,
+				       gboolean      sensitive)
+{
+	MarlinWindowPrivate *priv = window->priv;
+	GtkActionGroup *ag;
+
+	ag = priv->ui_action;
+
+	marlin_window_set_jack_sensitive (window, sensitive);
+
+	set_path_sensitive (ag, "MediaPrevious", sensitive);
+	set_path_sensitive (ag, "MediaNext", sensitive);
+	set_path_sensitive (ag, "MediaForward", sensitive);
+	set_path_sensitive (ag, "MediaRewind", sensitive);
+}
+
+void
 marlin_window_set_view_sensitive (MarlinWindow *window,
 				  gboolean sensitive)
 {
@@ -2042,7 +2112,7 @@
 	MarlinProgram *program = marlin_program_get_default ();
 	MarlinCoverage coverage;
 	GtkActionGroup *ag;
-	
+
 	ag = priv->ui_action;
 
 	if (sensitive == FALSE) {
@@ -2070,7 +2140,7 @@
 		set_path_sensitive (ag, "ShowAll", sensitive);
 		set_path_sensitive (ag, "ViewCentre", sensitive);
 
-		marlin_sample_selection_get (priv->selection, 
+		marlin_sample_selection_get (priv->selection,
 					     &coverage,
 					     NULL, NULL);
 	}
@@ -2097,9 +2167,9 @@
 	GtkActionGroup *ag;
 	gboolean can_remove;
 	MarlinCoverage coverage;
-       		
+
 	ag = priv->ui_action;
-	
+
 	if (priv->selection == NULL) {
 		set_path_sensitive (ag, "EditMoveCursor", FALSE);
 		set_path_sensitive (ag, "ZeroMovePrev", FALSE);
@@ -2112,7 +2182,7 @@
 		set_path_sensitive (ag, "ZeroMoveNext", sensitive);
 
 		marlin_sample_selection_get (priv->selection,
-					     &coverage, NULL, NULL);	
+					     &coverage, NULL, NULL);
 	}
 
 	if (coverage == MARLIN_COVERAGE_NONE) {
@@ -2127,7 +2197,7 @@
 		set_path_sensitive (ag, "EditCut", can_remove);
 		set_path_sensitive (ag, "EditCrop", can_remove);
 	}
-	
+
 	if (marlin_program_get_clipboard (program) == NULL) {
 		set_path_sensitive (ag, "EditPasteNew", FALSE);
 		set_path_sensitive (ag, "EditPaste", FALSE);
@@ -2148,7 +2218,7 @@
 		} else {
 			set_path_sensitive (ag, "EditUndo", FALSE);
 		}
-		
+
 		if (marlin_undo_manager_can_redo (priv->undo)) {
 			set_path_sensitive (ag, "EditRedo", sensitive);
 		} else {
@@ -2174,11 +2244,11 @@
 	} else {
 		set_path_sensitive (ag, "SelectAll", sensitive);
 		set_path_sensitive (ag, "SelectRegion", sensitive);
-		marlin_sample_selection_get (priv->selection, 
+		marlin_sample_selection_get (priv->selection,
 					     &coverage,
 					     NULL, NULL);
 	}
-	
+
 	if (coverage == MARLIN_COVERAGE_NONE) {
 		set_path_sensitive (ag, "SelectNone", FALSE);
 		set_path_sensitive (ag, "SelectHalve", FALSE);
@@ -2203,6 +2273,7 @@
 	GtkActionGroup *ag;
 
 	ag = window->priv->ui_action;
+	/* FIXME ? */
 }
 
 void
@@ -2214,7 +2285,7 @@
 	guint channels;
 	MarlinMarkerModel *model;
 	GList *markers;
-	
+
 	ag = priv->ui_action;
 
 	if (window->priv->selection == NULL) {
@@ -2234,7 +2305,7 @@
 			      "channels", &channels,
 			      "markers", &model,
 			      NULL);
-	
+
 		g_object_get (G_OBJECT (model),
 			      "markers", &markers,
 			      NULL);
@@ -2452,10 +2523,16 @@
 			  gboolean      repeating)
 {
 	MarlinWindowPrivate *priv;
+	MarlinProgram *program = marlin_program_get_default ();
 
 	g_return_if_fail (IS_MARLIN_WINDOW (window));
 	priv = window->priv;
 
+	if (priv->jack_owner_id != marlin_program_get_jack_owner (program)) {
+		g_print ("Not jack owner\n");
+		return;
+	}
+
 	/* Turn off processing */
 	set_path_sensitive (priv->ui_action, "Process", FALSE);
 
@@ -2470,6 +2547,9 @@
 		      "show_play_cursor", TRUE,
 		      NULL);
 
+	g_object_set (priv->jack,
+		      "sample", priv->sample,
+		      NULL);
 	marlin_jack_play_set_repeating (priv->jack, repeating);
 	marlin_jack_play_set_range (priv->jack, start, finish);
 	marlin_jack_start (MARLIN_JACK (priv->jack), NULL);
@@ -3679,14 +3759,18 @@
 {
 	MarlinWindow *window = fd->window;
 	MarlinWindowPrivate *priv = fd->window->priv;
-	char *name;
+	char *name, *uri;
 	char *dirname, *d;
 	guint64 n_frames;
 
 	switch (response_id) {
 	case GTK_RESPONSE_OK:
 		name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filesel));
+		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (filesel));
+
 		d = g_path_get_dirname (name);
+		g_free (name);
+
 		/* Add a trailing / so that the file selector will cd into it */
 		dirname = g_strdup_printf ("%s/", d);
 
@@ -3698,16 +3782,12 @@
 			      "total-frames", &n_frames,
 			      NULL);
 		if (n_frames == 0) {
-			char *uri;
-
-			uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (filesel));
 			/* Open the file in this window */
 			marlin_window_load_file (window, uri);
-			g_free (uri);
 		} else {
-			marlin_open_window (name, NULL, NULL, NULL);
+			marlin_open_window (uri, NULL, NULL, NULL);
 		}
-		g_free (name);
+		g_free (uri);
 		break;
 
 	case GTK_RESPONSE_CANCEL:

Modified: trunk/src/other/gtkvumeter.c
==============================================================================
--- trunk/src/other/gtkvumeter.c	(original)
+++ trunk/src/other/gtkvumeter.c	Tue Dec 23 22:12:50 2008
@@ -419,8 +419,8 @@
 
 void
 gtk_vumeter_set_levels (GtkVUMeter *vumeter,
-			double rms,
-			double peak)
+			double      rms,
+			double      peak)
 {
 	g_return_if_fail (vumeter != NULL);
 	g_return_if_fail (GTK_IS_VUMETER (vumeter));
@@ -433,7 +433,7 @@
 
 /* Should be set as a property */
 void
-gtk_vumeter_set_peaks_falloff (GtkVUMeter *vumeter,
+gtk_vumeter_set_peaks_falloff (GtkVUMeter       *vumeter,
 			       GtkVUMeterFallOff falloff)
 {
 	g_return_if_fail (GTK_IS_VUMETER (vumeter));



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