marlin r1343 - in trunk: marlin src



Author: iain
Date: Wed Dec 24 15:01:19 2008
New Revision: 1343
URL: http://svn.gnome.org/viewvc/marlin?rev=1343&view=rev

Log:
Drain the buffer when we stop recording so that we get all the recorded data

When we stop recording, the buffer is drained asynchronously to add all the data
into the sample. Emit a signal to let the MarlinRecord dialog know when to open a new window and reset the recorder.

Modified:
   trunk/marlin/marlin-jack-play.c
   trunk/marlin/marlin-jack-record.c
   trunk/marlin/marlin-jack-record.h
   trunk/marlin/marlin-program.c
   trunk/src/marlin-record.c

Modified: trunk/marlin/marlin-jack-play.c
==============================================================================
--- trunk/marlin/marlin-jack-play.c	(original)
+++ trunk/marlin/marlin-jack-play.c	Wed Dec 24 15:01:19 2008
@@ -245,7 +245,7 @@
  * realtime safe. This includes the necessary things to access the frame
  * data, which is mmapped from disk and may require mmap calls and locking.
  *
- * When start_playing is called, an idle function is started that calls
+ * When start_playing is called, an timeout is started that calls
  * process_writer. This is run in thread A and is able to do all the mmapping
  * safely. Because it is run in the main thread, the frame data can be accessed
  * without locking. process_writer copies enough frame data to fill the ring
@@ -322,8 +322,7 @@
 
 		o_buf = jack_port_get_buffer (pd->playback, nframes);
 		/* Zero this so that there is silence */
-		memset (o_buf, 0,
-			nframes * frame_size);
+		memset (o_buf, 0, nframes * frame_size);
 	}
 }
 

Modified: trunk/marlin/marlin-jack-record.c
==============================================================================
--- trunk/marlin/marlin-jack-record.c	(original)
+++ trunk/marlin/marlin-jack-record.c	Wed Dec 24 15:01:19 2008
@@ -38,9 +38,7 @@
 #include <marlin/marlin-jack-record.h>
 
 enum {
-	EOS,
-	STATUS_CHANGED,
-	POSITION_CHANGED,
+	FINISHED,
 	LAST_SIGNAL
 };
 
@@ -50,7 +48,8 @@
 	MARLIN_JACK_RECORD_MODE_NOTHING,
 	MARLIN_JACK_RECORD_MODE_STOPPED,
 	MARLIN_JACK_RECORD_MODE_PREROLLING,
-	MARLIN_JACK_RECORD_MODE_RECORDING
+	MARLIN_JACK_RECORD_MODE_RECORDING,
+	MARLIN_JACK_RECORD_MODE_DRAINING,
 } MarlinJackRecordMode;
 
 #define DEFAULT_RB_SIZE 262144
@@ -71,6 +70,7 @@
 	SRC_STATE *state;
 
 	gboolean writer_finished;
+	gboolean eos; /* Is this port finished? */
 };
 
 struct _MarlinJackRecordPrivate {
@@ -94,6 +94,7 @@
 };
 
 G_DEFINE_TYPE (MarlinJackRecord, marlin_jack_record, MARLIN_JACK_TYPE);
+static guint32 signals[LAST_SIGNAL] = {0, };
 
 static long process_more_frames (gpointer userdata, float **data);
 
@@ -358,8 +359,6 @@
 
 	jack_ringbuffer_read (pd->rb, (char *) pd->tmp_buffer, bytes_avail);
 
-	fprintf (stderr, "Got more frames: %d [%p]\n", bytes_avail / sizeof (float), pd);
-
 	*data = pd->tmp_buffer;
 	return bytes_avail / sizeof (float);
 }
@@ -373,7 +372,8 @@
 	int i;
 
 	if (priv->mode != MARLIN_JACK_RECORD_MODE_RECORDING &&
-	    priv->mode != MARLIN_JACK_RECORD_MODE_PREROLLING) {
+	    priv->mode != MARLIN_JACK_RECORD_MODE_PREROLLING &&
+	    priv->mode != MARLIN_JACK_RECORD_MODE_DRAINING) {
 		return TRUE;
 	}
 
@@ -383,30 +383,52 @@
 		long frames_needed;
 		size_t bytes_avail;
 
+		/* Do nothing if the port has finished */
+		if (pd->eos) {
+			continue;
+		}
+
 		bytes_avail = jack_ringbuffer_read_space (pd->rb);
-		/* Roll until we've got half the ringbuffer filled */
-		if (bytes_avail < DEFAULT_RB_SIZE / 2) {
-			g_print ("Got %d bytes, rolling\n", bytes_avail);
+		if (priv->mode == MARLIN_JACK_RECORD_MODE_DRAINING &&
+		    bytes_avail == 0) {
+			/* Store any extra data that might be there */
+			store_block (MARLIN_JACK_RECORD (jack), pd,
+				     pd->data, pd->frames_in_data);
+
+			/* Move the recorded data into the sample */
+			pd->channel->first = pd->block_list;
+			pd->channel->last = pd->bl_end;
+			pd->channel->frames = marlin_block_recalculate_ranges (pd->channel->first);
+
+			marlin_sample_frame_count_changed (priv->sample);
+
+			pd->channel = NULL;
+			pd->block_list = NULL;
+			pd->bl_end = NULL;
+
+			pd->eos = TRUE;
+			continue;
+		}
+
+		/* Roll until we've got half the ringbuffer filled
+		   unless we're draining the ring buffer on shutdown */
+		if (priv->mode != MARLIN_JACK_RECORD_MODE_DRAINING &&
+		    bytes_avail < DEFAULT_RB_SIZE / 2) {
 			return TRUE;
 		}
 
-		g_print ("Starting: %p\n", pd);
 		frames_needed = MIN (MARLIN_BLOCK_SIZE - pd->frames_in_data,
-				     (bytes_avail / sizeof (float)) / 8);
-		g_print ("Frames needed [%p] - %d (%d, %d)\n", pd, frames_needed, MARLIN_BLOCK_SIZE - pd->frames_in_data, (bytes_avail / sizeof (float)) / 8);
-
+				     bytes_avail / sizeof (float));
 		if (frames_needed == 0) {
 			continue;
 		}
 
 		frames = src_callback_read (pd->state, priv->src_ratio,
 					    frames_needed, pd->rb_buffer);
-		g_print ("Got %d frames\n", frames);
 		if (frames == 0) {
 			continue;
 		}
 
-		fprintf (stderr, "Bing got %d frames\n", frames);
 		/* The amount of frames available will be fill a block */
 		if (pd->frames_in_data + frames >= MARLIN_BLOCK_SIZE) {
 			guint32 needed, remain;
@@ -415,7 +437,6 @@
 			needed = MARLIN_BLOCK_SIZE - pd->frames_in_data;
 			remain = frames - needed;
 
-			fprintf (stderr, "Needed: %d - remains: %d\n", needed, remain);
 			/* Read from the ringbuffer into the next free space
 			   in the frame buffer */
 			fd = pd->data + pd->frames_in_data;
@@ -442,7 +463,23 @@
 		}
 	}
 
-	priv->mode = MARLIN_JACK_RECORD_MODE_RECORDING;
+	if (priv->mode == MARLIN_JACK_RECORD_MODE_DRAINING) {
+		/* Check if both of the channels are finished */
+		for (i = 0; i < 2; i++) {
+			struct _port_data *pd = priv->port_data[i];
+			if (pd->eos == FALSE) {
+				return TRUE;
+			}
+		}
+
+		/* If we've got here then we're finished */
+		priv->reader_id = 0;
+		g_signal_emit (jack, signals[FINISHED], 0);
+
+		return FALSE;
+	} else {
+		priv->mode = MARLIN_JACK_RECORD_MODE_RECORDING;
+	}
 
 	return TRUE;
 }
@@ -576,37 +613,32 @@
 
 	priv = GET_PRIVATE (jack);
 
-	priv->mode = MARLIN_JACK_RECORD_MODE_STOPPED;
+	priv->mode = MARLIN_JACK_RECORD_MODE_DRAINING;
 
 	jack_deactivate (priv->client);
 
+	/* Once the client is deactivated the ring buffer stops getting filled
+	   up, but we want the reader to keep spinning until the ring buffer is
+	   completely empty */
+
+#if 0
 	g_source_remove (priv->reader_id);
 	priv->reader_id = 0;
 
+/*
 	ports = jack_get_ports (priv->client, NULL, NULL,
 				JackPortIsPhysical | JackPortIsOutput);
+*/
 	for (i = 0; i < 2; i++) {
 		struct _port_data *pd = priv->port_data[i];
+/*
 		jack_disconnect (priv->client,
 				 jack_port_name (pd->record), ports[i]);
-
-		/* Store any extra data that might be there */
-		store_block (MARLIN_JACK_RECORD (jack), pd,
-			     pd->data, pd->frames_in_data);
-
-		/* Move the recorded data into the sample */
-		pd->channel->first = pd->block_list;
-		pd->channel->last = pd->bl_end;
-		pd->channel->frames = marlin_block_recalculate_ranges (pd->channel->first);
-
-		marlin_sample_frame_count_changed (priv->sample);
-
-		pd->channel = NULL;
-		pd->block_list = NULL;
-		pd->bl_end = NULL;
+*/
 	}
 
-	free (ports);
+	/* free (ports); */
+#endif
 }
 
 static gboolean
@@ -632,6 +664,14 @@
 	j_class->is_busy = is_busy;
 
 	g_type_class_add_private (klass, sizeof (MarlinJackRecordPrivate));
+
+	signals[FINISHED] = g_signal_new ("record-finished",
+					  G_TYPE_FROM_CLASS (klass),
+					  G_SIGNAL_RUN_LAST,
+					  G_STRUCT_OFFSET (MarlinJackRecordClass, record_finished),
+					  NULL, NULL,
+					  g_cclosure_marshal_VOID__VOID,
+					  G_TYPE_NONE, 0);
 }
 
 static void

Modified: trunk/marlin/marlin-jack-record.h
==============================================================================
--- trunk/marlin/marlin-jack-record.h	(original)
+++ trunk/marlin/marlin-jack-record.h	Wed Dec 24 15:01:19 2008
@@ -47,11 +47,7 @@
 	MarlinJackClass parent_class;
 
 	/* Signals */
-	void (*eos) (MarlinJack *jack);
-	void (*status_changed) (MarlinJack *jack,
-				int status);
-	void (*position_changed) (MarlinJack *jack,
-				  guint64 position);
+	void (*record_finished) (MarlinJack *jack);
 };
 
 GType marlin_jack_record_get_type (void);

Modified: trunk/marlin/marlin-program.c
==============================================================================
--- trunk/marlin/marlin-program.c	(original)
+++ trunk/marlin/marlin-program.c	Wed Dec 24 15:01:19 2008
@@ -320,8 +320,8 @@
 		return;
 	}
 
-	if (marlin_jack_is_busy (priv->player) ||
-	    marlin_jack_is_busy (priv->recorder)) {
+	if (marlin_jack_is_busy ((MarlinJack *) priv->player) ||
+	    marlin_jack_is_busy ((MarlinJack *) priv->recorder)) {
 		/* Jack is busy so cannot be acquired */
 		return;
 	}

Modified: trunk/src/marlin-record.c
==============================================================================
--- trunk/src/marlin-record.c	(original)
+++ trunk/src/marlin-record.c	Wed Dec 24 15:01:19 2008
@@ -56,7 +56,9 @@
 
 	GtkWindow *parent_window;
 	MarlinSample *sample;
+
 	MarlinJack *recorder;
+	guint jack_owner_id;
 
 	GtkWidget *left_vu, *right_vu;
 
@@ -116,6 +118,10 @@
 		g_object_unref (G_OBJECT (rd->sample));
 	}
 
+	/* Release jack */
+	marlin_program_release_jack (marlin_program_get_default (),
+				     rd->jack_owner_id);
+
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 	g_free (rd);
 }
@@ -126,7 +132,7 @@
 {
 	gboolean on;
 
-	/* Set the controls on of off depending on how 
+	/* Set the controls on of off depending on how
 	   many frames there are. If there's none, then
 	   we can't play the sample. */
 
@@ -183,7 +189,7 @@
 	GtkTreeIter iter;
 	GtkListStore *store;
 	int i;
-	
+
 	cellview = gtk_cell_view_new ();
 
 	store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
@@ -265,7 +271,7 @@
 			      "max-frames", frames,
 			      "rate", rate,
 			      NULL);
-		
+
 		set_media_controls (rd, frames);
 		g_object_set (G_OBJECT (rd->play_pipeline),
 			      "sample", sample,
@@ -311,9 +317,9 @@
 		MarlinSample *sample;
 		struct _destroy_id *did;
 		char *filename;
-		
+
 #warning FIXME: Make this work.
-		
+
 #if 0
 		did = g_new (struct _destroy_id, 1);
 		did->window = window;
@@ -321,7 +327,7 @@
 		g_object_get (G_OBJECT (window),
 			      "sample", &sample,
 			      NULL);
-		g_object_get (G_OBJECT (sample), 
+		g_object_get (G_OBJECT (sample),
 			      "filename", &filename,
 			      NULL);
 
@@ -363,7 +369,7 @@
 	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 	gtk_label_set_selectable (GTK_LABEL (label), TRUE);
 	gtk_label_set_line_wrap (GTK_LABEL (label), GTK_WRAP_WORD);
-	
+
 	return label;
 }
 
@@ -378,7 +384,7 @@
 			  GTK_FILL, GTK_FILL, 0, 0);
 }
 
-/* Callbacks */	
+/* Callbacks */
 static void
 new_radio_toggled (GtkToggleButton *tb,
 		   RecordData *rd)
@@ -502,7 +508,8 @@
 }
 
 static void
-reset_record (RecordData *rd)
+recorder_finished_cb (MarlinJackRecord *jack,
+		      RecordData       *rd)
 {
 	int rate, channels;
 
@@ -537,7 +544,6 @@
 
 	case GR_RECORDING:
 		marlin_jack_stop (MARLIN_JACK (rd->recorder));
-		reset_record (rd);
 		break;
 	}
 	rd->state = GR_NOTHING;
@@ -656,7 +662,14 @@
 
 	program = marlin_program_get_default ();
 	rd->recorder = (MarlinJack *) marlin_program_get_recorder (program);
+	rd->jack_owner_id = marlin_program_request_jack_owner_id (program);
+
+	/* Should lock owner somehow */
+	marlin_program_acquire_jack (program, rd->jack_owner_id);
+
 	if (rd->recorder) {
+		g_signal_connect (rd->recorder, "record-finished",
+				  G_CALLBACK (recorder_finished_cb), rd);
 		g_object_set (G_OBJECT (rd->recorder),
 			      "sample", rd->sample,
 			      NULL);
@@ -764,11 +777,11 @@
 					"text", 1,
 					NULL);
 	gtk_combo_box_set_active (GTK_COMBO_BOX (rd->profile_menu), 0);
-	
+
 	rd->settings = gtk_button_new_with_mnemonic (_("_Settings"));
 	gtk_widget_set_sensitive (rd->settings, FALSE);
 	gtk_box_pack_start (GTK_BOX (extra_hb), rd->settings, FALSE, FALSE, 0);
-#endif	
+#endif
 	inner_hb = gtk_hbox_new (FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (inner_vb), inner_hb, FALSE, FALSE, 0);
 
@@ -874,7 +887,7 @@
 	gtk_box_pack_start (GTK_BOX (rd->exist_box), position_hb, TRUE, TRUE, 0);
 
 	rd->ins_combo = gtk_combo_box_new_text ();
- 	gtk_box_pack_start (GTK_BOX (position_hb), rd->ins_combo, FALSE, FALSE, 0); 
+ 	gtk_box_pack_start (GTK_BOX (position_hb), rd->ins_combo, FALSE, FALSE, 0);
 	gtk_widget_show (rd->ins_combo);
 
 	gtk_combo_box_append_text (GTK_COMBO_BOX (rd->ins_combo), _("Insert"));
@@ -913,7 +926,7 @@
 
 	gtk_box_pack_start (GTK_BOX (hbox), rd->left_vu, FALSE, FALSE, 0);
 	gtk_box_pack_start (GTK_BOX (hbox), rd->right_vu, FALSE, FALSE, 0);
-	
+
 	gtk_widget_show_all (rd->dialog);
 	return rd->dialog;
 }



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