blob: 11d840ed68c39b16a40e7aae80f854059c681e57 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27#define USE_ERROR
28#define USE_TRACE
29
30#include "PlatformMidi.h"
31
32char* GetInternalErrorStr(INT32 err) {
33 switch (err) {
34 case MIDI_SUCCESS: return "";
35 case MIDI_NOT_SUPPORTED: return "feature not supported";
36 case MIDI_INVALID_DEVICEID: return "invalid device ID";
37 case MIDI_INVALID_HANDLE: return "internal error: invalid handle";
38 case MIDI_OUT_OF_MEMORY: return "out of memory";
39 }
40 return NULL;
41}
42
43/*
44 * internal implementation for getting error string
45 */
46char* MIDI_IN_InternalGetErrorString(INT32 err) {
47 char* result = GetInternalErrorStr(err);
48
49#if USE_PLATFORM_MIDI_IN == TRUE
50 if (!result) {
51 result = MIDI_IN_GetErrorStr(err);
52 }
53#endif
54 if (!result) {
55 result = GetInternalErrorStr(MIDI_NOT_SUPPORTED);
56 }
57 return result;
58}
59
60/*
61 * internal implementation for getting error string
62 */
63char* MIDI_OUT_InternalGetErrorString(INT32 err) {
64 char* result = GetInternalErrorStr(err);
65
66#if USE_PLATFORM_MIDI_OUT == TRUE
67 if (!result) {
68 result = MIDI_OUT_GetErrorStr(err);
69 }
70#endif
71 if (!result) {
72 result = GetInternalErrorStr(MIDI_NOT_SUPPORTED);
73 }
74 return result;
75}
76
77
78#if USE_MIDI_QUEUE == TRUE
79
80// MessageQueue implementation
81
82MidiMessageQueue* MIDI_CreateQueue(int capacity) {
83 MidiMessageQueue* queue = (MidiMessageQueue*) malloc(sizeof(MidiMessageQueue) + ((capacity-1) * sizeof(MidiMessage)));
84 if (queue) {
85 TRACE0("MIDI_CreateQueue\n");
86 queue->lock = MIDI_CreateLock();
87 queue->capacity = capacity;
88 queue->size = 0;
89 queue->readIndex = 0;
90 queue->writeIndex = 0;
91 }
92 return queue;
93}
94
95void MIDI_DestroyQueue(MidiMessageQueue* queue) {
96 if (queue) {
97 void* lock = queue->lock;
98 MIDI_Lock(lock);
99 free(queue);
100 MIDI_Unlock(lock);
101 MIDI_DestroyLock(lock);
102 TRACE0("MIDI_DestroyQueue\n");
103 }
104}
105
106// if overwrite is true, oldest messages will be overwritten when the queue is full
107// returns true, if message has been added
108int MIDI_QueueAddShort(MidiMessageQueue* queue, UINT32 packedMsg, INT64 timestamp, int overwrite) {
109 if (queue) {
110 MIDI_Lock(queue->lock);
111 if (queue->size == queue->capacity) {
112 TRACE0("MIDI_QueueAddShort: overflow\n");
113 if (!overwrite || queue->queue[queue->writeIndex].locked) {
114 return FALSE; // failed
115 }
116 // adjust overwritten readIndex
117 queue->readIndex = (queue->readIndex+1) % queue->capacity;
118 } else {
119 queue->size++;
120 }
121 TRACE2("MIDI_QueueAddShort. index=%d, size=%d\n", queue->writeIndex, queue->size);
122 queue->queue[queue->writeIndex].type = SHORT_MESSAGE;
123 queue->queue[queue->writeIndex].data.s.packedMsg = packedMsg;
124 queue->queue[queue->writeIndex].timestamp = timestamp;
125 queue->writeIndex = (queue->writeIndex+1) % queue->capacity;
126 MIDI_Unlock(queue->lock);
127 return TRUE;
128 }
129 return FALSE;
130}
131
132int MIDI_QueueAddLong(MidiMessageQueue* queue, UBYTE* data, UINT32 size,
133 INT32 sysexIndex, INT64 timestamp, int overwrite) {
134 if (queue) {
135 MIDI_Lock(queue->lock);
136 if (queue->size == queue->capacity) {
137 TRACE0("MIDI_QueueAddLong: overflow\n");
138 if (!overwrite || queue->queue[queue->writeIndex].locked) {
139 return FALSE; // failed
140 }
141 // adjust overwritten readIndex
142 queue->readIndex = (queue->readIndex+1) % queue->capacity;
143 } else {
144 queue->size++;
145 }
146 TRACE2("MIDI_QueueAddLong. index=%d, size=%d\n", queue->writeIndex, queue->size);
147 //fprintf(stdout, "MIDI_QueueAddLong sysex-index %d\n", sysexIndex); fflush(stdout);
148 queue->queue[queue->writeIndex].type = LONG_MESSAGE;
149 queue->queue[queue->writeIndex].data.l.size = size;
150 queue->queue[queue->writeIndex].data.l.data = data;
151 queue->queue[queue->writeIndex].data.l.index = sysexIndex;
152 queue->queue[queue->writeIndex].timestamp = timestamp;
153 queue->writeIndex = (queue->writeIndex+1) % queue->capacity;
154 MIDI_Unlock(queue->lock);
155 return TRUE;
156 }
157 return FALSE;
158}
159
160// returns NULL if no messages in queue.
161MidiMessage* MIDI_QueueRead(MidiMessageQueue* queue) {
162 MidiMessage* msg = NULL;
163 if (queue) {
164 MIDI_Lock(queue->lock);
165 if (queue->size > 0) {
166 msg = &(queue->queue[queue->readIndex]);
167 TRACE2("MIDI_QueueRead. index=%d, size=%d\n", queue->readIndex, queue->size);
168 msg->locked = TRUE;
169 }
170 MIDI_Unlock(queue->lock);
171 }
172 return msg;
173}
174
175void MIDI_QueueRemove(MidiMessageQueue* queue, INT32 onlyLocked) {
176 if (queue) {
177 MIDI_Lock(queue->lock);
178 if (queue->size > 0) {
179 MidiMessage* msg = &(queue->queue[queue->readIndex]);
180 if (!onlyLocked || msg->locked) {
181 TRACE2("MIDI_QueueRemove. index=%d, size=%d\n", queue->readIndex, queue->size);
182 queue->readIndex = (queue->readIndex+1) % queue->capacity;
183 queue->size--;
184 }
185 msg->locked = FALSE;
186 }
187 MIDI_Unlock(queue->lock);
188 }
189}
190
191void MIDI_QueueClear(MidiMessageQueue* queue) {
192 if (queue) {
193 MIDI_Lock(queue->lock);
194 queue->size = 0;
195 queue->readIndex = 0;
196 queue->writeIndex = 0;
197 MIDI_Unlock(queue->lock);
198 }
199}
200
201#endif