aboutsummaryrefslogtreecommitdiff
path: root/pd/portmidi/pm_common/pmutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portmidi/pm_common/pmutil.c')
-rw-r--r--pd/portmidi/pm_common/pmutil.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/pd/portmidi/pm_common/pmutil.c b/pd/portmidi/pm_common/pmutil.c
new file mode 100644
index 00000000..1178b80b
--- /dev/null
+++ b/pd/portmidi/pm_common/pmutil.c
@@ -0,0 +1,132 @@
+/* pmutil.c -- some helpful utilities for building midi
+ applications that use PortMidi
+ */
+#include "stdlib.h"
+#include "memory.h"
+#include "portmidi.h"
+#include "pmutil.h"
+#include "pminternal.h"
+
+
+PmQueue *Pm_QueueCreate(long num_msgs, long bytes_per_msg)
+{
+ PmQueueRep *queue = (PmQueueRep *) pm_alloc(sizeof(PmQueueRep));
+
+ /* arg checking */
+ if (!queue)
+ return NULL;
+
+ queue->len = num_msgs * bytes_per_msg;
+ queue->buffer = pm_alloc(queue->len);
+ if (!queue->buffer) {
+ pm_free(queue);
+ return NULL;
+ }
+ queue->head = 0;
+ queue->tail = 0;
+ queue->msg_size = bytes_per_msg;
+ queue->overflow = FALSE;
+ return queue;
+}
+
+
+PmError Pm_QueueDestroy(PmQueue *q)
+{
+ PmQueueRep *queue = (PmQueueRep *) q;
+
+ /* arg checking */
+ if (!queue || !queue->buffer)
+ return pmBadPtr;
+
+ pm_free(queue->buffer);
+ pm_free(queue);
+ return pmNoError;
+}
+
+
+PmError Pm_Dequeue(PmQueue *q, void *msg)
+{
+ long head;
+ PmQueueRep *queue = (PmQueueRep *) q;
+
+ /* arg checking */
+ if(!queue)
+ return pmBadPtr;
+
+ if (queue->overflow) {
+ queue->overflow = FALSE;
+ return pmBufferOverflow;
+ }
+
+ head = queue->head; /* make sure this is written after access */
+ if (head == queue->tail) return 0;
+ memcpy(msg, queue->buffer + head, queue->msg_size);
+ head += queue->msg_size;
+ if (head == queue->len) head = 0;
+ queue->head = head;
+ return 1; /* success */
+}
+
+
+/* source should not enqueue data if overflow is set */
+/**/
+PmError Pm_Enqueue(PmQueue *q, void *msg)
+{
+ PmQueueRep *queue = (PmQueueRep *) q;
+ long tail;
+
+ /* arg checking */
+ if (!queue)
+ return pmBadPtr;
+
+ tail = queue->tail;
+ memcpy(queue->buffer + tail, msg, queue->msg_size);
+ tail += queue->msg_size;
+ if (tail == queue->len) tail = 0;
+ if (tail == queue->head) {
+ queue->overflow = TRUE;
+ /* do not update tail, so message is lost */
+ return pmBufferOverflow;
+ }
+ queue->tail = tail;
+ return pmNoError;
+}
+
+int Pm_QueueEmpty(PmQueue *q)
+{
+ PmQueueRep *queue = (PmQueueRep *) q;
+ if (!queue) return TRUE;
+ return (queue->head == queue->tail);
+}
+
+int Pm_QueueFull(PmQueue *q)
+{
+ PmQueueRep *queue = (PmQueueRep *) q;
+ long tail;
+
+ /* arg checking */
+ if(!queue)
+ return pmBadPtr;
+
+ tail = queue->tail;
+ tail += queue->msg_size;
+ if (tail == queue->len) {
+ tail = 0;
+ }
+ return (tail == queue->head);
+}
+
+void *Pm_QueuePeek(PmQueue *q)
+{
+ long head;
+ PmQueueRep *queue = (PmQueueRep *) q;
+
+ /* arg checking */
+ if(!queue)
+ return NULL;
+
+ head = queue->head; /* make sure this is written after access */
+ if (head == queue->tail) return NULL;
+ return queue->buffer + head;
+}
+