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
34char* 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 */
48char* 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 */
65char* 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
84MidiMessageQueue* 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
97void 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
110int 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
134int 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.
163MidiMessage* 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
177void 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
193void 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