/* 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; }