changeset 338:1802f99cd77f prerelease

Initial support for thread-safe libpd (stil missing updated libpd binary), untested
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 05 Jun 2016 21:46:44 +0100
parents 5e2780bfbfed
children 02e6f96466f8
files examples/basic_libpd/render.cpp examples/basic_libpd/ringbuffer.h examples/basic_libpd/z_queued.h
diffstat 3 files changed, 102 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/examples/basic_libpd/render.cpp	Sun Jun 05 20:28:43 2016 +0100
+++ b/examples/basic_libpd/render.cpp	Sun Jun 05 21:46:44 2016 +0100
@@ -12,6 +12,7 @@
 #include <PRU.h>
 #include <stdio.h>
 #include "z_libpd.h"
+#include "z_queued.h"
 #include <UdpServer.h>
 #include <Midi.h>
 
@@ -75,9 +76,9 @@
 		return false;
 	}
 	// init pd
-	libpd_set_printhook(Bela_printHook); // set this before calling libpd_init
-	libpd_set_noteonhook(pdnoteon);
-	libpd_init();
+	libpd_set_queued_printhook(Bela_printHook); // set this before calling libpd_init
+	libpd_set_queued_noteonhook(pdnoteon);
+	libpd_queued_init();
 	//TODO: analyse the ASCII of the patch file and find the in/outs to use
 	libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate);
 
@@ -220,6 +221,9 @@
 	// rt_printf("inW %d\n", inW);
 	if(inW == 0){ //if the buffer is full, process it
 		static int numberOfPdBlocksToProcess = gBufLength/gLibPdBlockSize;
+		// TODO: see if we can rewrite libpd_process_float so that it takes a buffer
+		// of interleaved channels of arbitrary length channels rather than a series of
+		// stacked buffers of size gLibPdBlockSize as it currently does.
 		libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf);
 		outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time
 	}
@@ -263,6 +267,7 @@
 
 void cleanup(BelaContext *context, void *userData)
 {
+	libpd_queued_release();
 	free(gInBuf);
 	free(gOutBuf);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/basic_libpd/ringbuffer.h	Sun Jun 05 21:46:44 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
+ *
+ *  For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ *  WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * See https://github.com/libpd/libpd/wiki for documentation
+ *
+ */
+
+#ifndef __OPENSL_RING_BUFFER_H__
+#define __OPENSL_RING_BUFFER_H__
+
+// Simple lock-free ring buffer implementation for one writer thread and one
+// consumer thread.
+typedef struct ring_buffer {
+    int size;
+    char *buf_ptr;
+    int write_idx;
+    int read_idx;
+} ring_buffer;
+
+// Creates a ring buffer (returns NULL on failure).
+ring_buffer *rb_create(int size);
+
+// Deletes a ring buffer.
+void rb_free(ring_buffer *buffer);
+
+// Returns the number of bytes that can currently be written; safe to be called
+// from any thread.
+int rb_available_to_write(ring_buffer *buffer);
+
+// Returns the number of bytes that can currently be read; safe to be called
+// from any thread.
+int rb_available_to_read(ring_buffer *buffer);
+
+// Writes bytes from n sources to the ring buffer (if the ring buffer has
+// enough space). The varargs are pairs of type (const char*, int) giving a
+// pointer to a buffer and the number of bytes to be copied. Only to be called
+// from a single writer thread.
+// Returns 0 on success.
+int rb_write_to_buffer(ring_buffer *buffer, int n, ...);
+
+// Reads the given number of bytes fromthe ring buffer to dest if the ring
+// buffer has enough data. Only to be called from a single reader thread.
+// Returns 0 on success.
+int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/basic_libpd/z_queued.h	Sun Jun 05 21:46:44 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Peter Brinkmann (peter.brinkmann@gmail.com)
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * See https://github.com/libpd/libpd/wiki for documentation
+ *
+ */
+
+#ifndef __Z_QUEUED_H__
+#define __Z_QUEUED_H__
+
+#include "z_libpd.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+EXTERN void libpd_set_queued_printhook(const t_libpd_printhook hook);
+EXTERN void libpd_set_queued_banghook(const t_libpd_banghook hook);
+EXTERN void libpd_set_queued_floathook(const t_libpd_floathook hook);
+EXTERN void libpd_set_queued_symbolhook(const t_libpd_symbolhook hook);
+EXTERN void libpd_set_queued_listhook(const t_libpd_listhook hook);
+EXTERN void libpd_set_queued_messagehook(const t_libpd_messagehook hook);
+
+EXTERN void libpd_set_queued_noteonhook(const t_libpd_noteonhook hook);
+EXTERN void libpd_set_queued_controlchangehook(const t_libpd_controlchangehook hook);
+EXTERN void libpd_set_queued_programchangehook(const t_libpd_programchangehook hook);
+EXTERN void libpd_set_queued_pitchbendhook(const t_libpd_pitchbendhook hook);
+EXTERN void libpd_set_queued_aftertouchhook(const t_libpd_aftertouchhook hook);
+EXTERN void libpd_set_queued_polyaftertouchhook(const t_libpd_polyaftertouchhook hook);
+EXTERN void libpd_set_queued_midibytehook(const t_libpd_midibytehook hook);
+
+int libpd_queued_init();
+void libpd_queued_release();
+void libpd_queued_receive_pd_messages();
+void libpd_queued_receive_midi_messages();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif