1 | /* |
2 | * Copyright (c) 2002, 2015, Oracle and/or its affiliates. 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. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | |
27 | #define USE_ERROR |
28 | #define USE_TRACE |
29 | |
30 | #include "PlatformMidi.h" |
31 | |
32 | #include <stdlib.h> |
33 | |
34 | char* GetInternalErrorStr(INT32 err) { |
35 | switch (err) { |
36 | case MIDI_SUCCESS: return "" ; |
37 | case MIDI_NOT_SUPPORTED: return "feature not supported" ; |
38 | case MIDI_INVALID_DEVICEID: return "invalid device ID" ; |
39 | case MIDI_INVALID_HANDLE: return "internal error: invalid handle" ; |
40 | case MIDI_OUT_OF_MEMORY: return "out of memory" ; |
41 | } |
42 | return NULL; |
43 | } |
44 | |
45 | /* |
46 | * internal implementation for getting error string |
47 | */ |
48 | char* MIDI_IN_InternalGetErrorString(INT32 err) { |
49 | char* result = GetInternalErrorStr(err); |
50 | |
51 | #if USE_PLATFORM_MIDI_IN == TRUE |
52 | if (!result) { |
53 | result = MIDI_IN_GetErrorStr(err); |
54 | } |
55 | #endif |
56 | if (!result) { |
57 | result = GetInternalErrorStr(MIDI_NOT_SUPPORTED); |
58 | } |
59 | return result; |
60 | } |
61 | |
62 | /* |
63 | * internal implementation for getting error string |
64 | */ |
65 | char* MIDI_OUT_InternalGetErrorString(INT32 err) { |
66 | char* result = GetInternalErrorStr(err); |
67 | |
68 | #if USE_PLATFORM_MIDI_OUT == TRUE |
69 | if (!result) { |
70 | result = MIDI_OUT_GetErrorStr(err); |
71 | } |
72 | #endif |
73 | if (!result) { |
74 | result = GetInternalErrorStr(MIDI_NOT_SUPPORTED); |
75 | } |
76 | return result; |
77 | } |
78 | |
79 | |
80 | #if USE_MIDI_QUEUE == TRUE |
81 | |
82 | // MessageQueue implementation |
83 | |
84 | MidiMessageQueue* MIDI_CreateQueue(int capacity) { |
85 | MidiMessageQueue* queue = (MidiMessageQueue*) malloc(sizeof(MidiMessageQueue) + ((capacity-1) * sizeof(MidiMessage))); |
86 | if (queue) { |
87 | TRACE0("MIDI_CreateQueue\n" ); |
88 | queue->lock = MIDI_CreateLock(); |
89 | queue->capacity = capacity; |
90 | queue->size = 0; |
91 | queue->readIndex = 0; |
92 | queue->writeIndex = 0; |
93 | } |
94 | return queue; |
95 | } |
96 | |
97 | void MIDI_DestroyQueue(MidiMessageQueue* queue) { |
98 | if (queue) { |
99 | void* lock = queue->lock; |
100 | MIDI_Lock(lock); |
101 | free(queue); |
102 | MIDI_Unlock(lock); |
103 | MIDI_DestroyLock(lock); |
104 | TRACE0("MIDI_DestroyQueue\n" ); |
105 | } |
106 | } |
107 | |
108 | // if overwrite is true, oldest messages will be overwritten when the queue is full |
109 | // returns true, if message has been added |
110 | int MIDI_QueueAddShort(MidiMessageQueue* queue, UINT32 packedMsg, INT64 timestamp, int overwrite) { |
111 | if (queue) { |
112 | MIDI_Lock(queue->lock); |
113 | if (queue->size == queue->capacity) { |
114 | TRACE0("MIDI_QueueAddShort: overflow\n" ); |
115 | if (!overwrite || queue->queue[queue->writeIndex].locked) { |
116 | return FALSE; // failed |
117 | } |
118 | // adjust overwritten readIndex |
119 | queue->readIndex = (queue->readIndex+1) % queue->capacity; |
120 | } else { |
121 | queue->size++; |
122 | } |
123 | TRACE2("MIDI_QueueAddShort. index=%d, size=%d\n" , queue->writeIndex, queue->size); |
124 | queue->queue[queue->writeIndex].type = SHORT_MESSAGE; |
125 | queue->queue[queue->writeIndex].data.s.packedMsg = packedMsg; |
126 | queue->queue[queue->writeIndex].timestamp = timestamp; |
127 | queue->writeIndex = (queue->writeIndex+1) % queue->capacity; |
128 | MIDI_Unlock(queue->lock); |
129 | return TRUE; |
130 | } |
131 | return FALSE; |
132 | } |
133 | |
134 | int MIDI_QueueAddLong(MidiMessageQueue* queue, UBYTE* data, UINT32 size, |
135 | INT32 sysexIndex, INT64 timestamp, int overwrite) { |
136 | if (queue) { |
137 | MIDI_Lock(queue->lock); |
138 | if (queue->size == queue->capacity) { |
139 | TRACE0("MIDI_QueueAddLong: overflow\n" ); |
140 | if (!overwrite || queue->queue[queue->writeIndex].locked) { |
141 | return FALSE; // failed |
142 | } |
143 | // adjust overwritten readIndex |
144 | queue->readIndex = (queue->readIndex+1) % queue->capacity; |
145 | } else { |
146 | queue->size++; |
147 | } |
148 | TRACE2("MIDI_QueueAddLong. index=%d, size=%d\n" , queue->writeIndex, queue->size); |
149 | //fprintf(stdout, "MIDI_QueueAddLong sysex-index %d\n", sysexIndex); fflush(stdout); |
150 | queue->queue[queue->writeIndex].type = LONG_MESSAGE; |
151 | queue->queue[queue->writeIndex].data.l.size = size; |
152 | queue->queue[queue->writeIndex].data.l.data = data; |
153 | queue->queue[queue->writeIndex].data.l.index = sysexIndex; |
154 | queue->queue[queue->writeIndex].timestamp = timestamp; |
155 | queue->writeIndex = (queue->writeIndex+1) % queue->capacity; |
156 | MIDI_Unlock(queue->lock); |
157 | return TRUE; |
158 | } |
159 | return FALSE; |
160 | } |
161 | |
162 | // returns NULL if no messages in queue. |
163 | MidiMessage* MIDI_QueueRead(MidiMessageQueue* queue) { |
164 | MidiMessage* msg = NULL; |
165 | if (queue) { |
166 | MIDI_Lock(queue->lock); |
167 | if (queue->size > 0) { |
168 | msg = &(queue->queue[queue->readIndex]); |
169 | TRACE2("MIDI_QueueRead. index=%d, size=%d\n" , queue->readIndex, queue->size); |
170 | msg->locked = TRUE; |
171 | } |
172 | MIDI_Unlock(queue->lock); |
173 | } |
174 | return msg; |
175 | } |
176 | |
177 | void MIDI_QueueRemove(MidiMessageQueue* queue, INT32 onlyLocked) { |
178 | if (queue) { |
179 | MIDI_Lock(queue->lock); |
180 | if (queue->size > 0) { |
181 | MidiMessage* msg = &(queue->queue[queue->readIndex]); |
182 | if (!onlyLocked || msg->locked) { |
183 | TRACE2("MIDI_QueueRemove. index=%d, size=%d\n" , queue->readIndex, queue->size); |
184 | queue->readIndex = (queue->readIndex+1) % queue->capacity; |
185 | queue->size--; |
186 | } |
187 | msg->locked = FALSE; |
188 | } |
189 | MIDI_Unlock(queue->lock); |
190 | } |
191 | } |
192 | |
193 | void MIDI_QueueClear(MidiMessageQueue* queue) { |
194 | if (queue) { |
195 | MIDI_Lock(queue->lock); |
196 | queue->size = 0; |
197 | queue->readIndex = 0; |
198 | queue->writeIndex = 0; |
199 | MIDI_Unlock(queue->lock); |
200 | } |
201 | } |
202 | |
203 | #endif |
204 | |