xref: /haiku/src/kits/midi/Midi.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
1 /*
2  * Copyright (c) 2002-2003 Matthijs Hollemans
3  * Copyright (c) 2002 Michael Pfeiffer
4  * Copyright (c) 2002 Jerome Leveque
5  * Copyright (c) 2002 Paul Stadler
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include <List.h>
27 #include <MidiProducer.h>
28 
29 #include "Midi.h"
30 #include "MidiGlue.h"
31 #include "debug.h"
32 
33 //------------------------------------------------------------------------------
34 
35 status_t _run_thread(void* data)
36 {
37 	BMidi* midi = (BMidi*) data;
38 	midi->Run();
39 	midi->isRunning = false;
40 	return 0;
41 }
42 
43 //------------------------------------------------------------------------------
44 
45 BMidi::BMidi()
46 {
47 	connections = new BList;
48 	threadId    = -1;
49 	isRunning   = false;
50 
51 	producer = new BMidiLocalProducer("MidiGlue(out)");
52 	consumer = new BMidiGlue(this, "MidiGlue(in)");
53 }
54 
55 //------------------------------------------------------------------------------
56 
57 BMidi::~BMidi()
58 {
59 	Stop();
60 
61 	status_t result;
62 	wait_for_thread(threadId, &result);
63 
64 	producer->Release();
65 	consumer->Release();
66 
67 	delete connections;
68 }
69 
70 //------------------------------------------------------------------------------
71 
72 void BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
73 {
74 	// do nothing
75 }
76 
77 //------------------------------------------------------------------------------
78 
79 void BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
80 {
81 	// do nothing
82 }
83 
84 //------------------------------------------------------------------------------
85 
86 void BMidi::KeyPressure(
87 	uchar channel, uchar note, uchar pressure, uint32 time)
88 {
89 	// do nothing
90 }
91 
92 //------------------------------------------------------------------------------
93 
94 void BMidi::ControlChange(
95 	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
96 {
97 	// do nothing
98 }
99 
100 //------------------------------------------------------------------------------
101 
102 void BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
103 {
104 	// do nothing
105 }
106 
107 //------------------------------------------------------------------------------
108 
109 void BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
110 {
111 	// do nothing
112 }
113 
114 //------------------------------------------------------------------------------
115 
116 void BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
117 {
118 	// do nothing
119 }
120 
121 //------------------------------------------------------------------------------
122 
123 void BMidi::SystemExclusive(void* data, size_t length, uint32 time)
124 {
125 	// do nothing
126 }
127 
128 //------------------------------------------------------------------------------
129 
130 void BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
131 {
132 	// do nothing
133 }
134 
135 //------------------------------------------------------------------------------
136 
137 void BMidi::SystemRealTime(uchar status, uint32 time)
138 {
139 	// do nothing
140 }
141 
142 //------------------------------------------------------------------------------
143 
144 void BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
145 {
146 	// do nothing
147 }
148 
149 //------------------------------------------------------------------------------
150 
151 void BMidi::AllNotesOff(bool justChannel, uint32 time)
152 {
153 	for (uchar channel = 1; channel <= 16; ++channel)
154 	{
155 		SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time);
156 
157 		if (!justChannel)
158 		{
159 			for (uchar note = 0; note <= 0x7F; ++note)
160 			{
161 				SprayNoteOff(channel, note, 0, time);
162 			}
163 		}
164 	}
165 }
166 
167 //------------------------------------------------------------------------------
168 
169 status_t BMidi::Start()
170 {
171 	if (isRunning) { return B_OK; }
172 
173 	status_t err = spawn_thread(
174 		_run_thread, "MidiRunThread", B_URGENT_PRIORITY, this);
175 
176 	if (err < B_OK) { return err; }
177 
178 	threadId  = err;
179 	isRunning = true;
180 
181 	err = resume_thread(threadId);
182 	if (err != B_OK)
183 	{
184 		threadId  = -1;
185 		isRunning = false;
186 	}
187 
188 	return err;
189 }
190 
191 //------------------------------------------------------------------------------
192 
193 void BMidi::Stop()
194 {
195 	threadId = -1;
196 }
197 
198 //------------------------------------------------------------------------------
199 
200 bool BMidi::IsRunning() const
201 {
202 	return isRunning;
203 }
204 
205 //------------------------------------------------------------------------------
206 
207 void BMidi::Connect(BMidi* toObject)
208 {
209 	if (toObject != NULL)
210 	{
211 		if (producer->Connect(toObject->consumer) == B_OK)
212 		{
213 			connections->AddItem(toObject);
214 		}
215 	}
216 }
217 
218 //------------------------------------------------------------------------------
219 
220 void BMidi::Disconnect(BMidi* fromObject)
221 {
222 	if (fromObject != NULL)
223 	{
224 		if (producer->Disconnect(fromObject->consumer) == B_OK)
225 		{
226 			connections->RemoveItem(fromObject);
227 		}
228 	}
229 }
230 
231 //------------------------------------------------------------------------------
232 
233 bool BMidi::IsConnected(BMidi* toObject) const
234 {
235 	if (toObject != NULL)
236 	{
237 		return producer->IsConnected(toObject->consumer);
238 	}
239 
240 	return false;
241 }
242 
243 //------------------------------------------------------------------------------
244 
245 BList* BMidi::Connections() const
246 {
247 	return connections;
248 }
249 
250 //------------------------------------------------------------------------------
251 
252 void BMidi::SnoozeUntil(uint32 time) const
253 {
254 	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
255 }
256 
257 //------------------------------------------------------------------------------
258 
259 bool BMidi::KeepRunning()
260 {
261 	return (threadId != -1);
262 }
263 
264 //------------------------------------------------------------------------------
265 
266 void BMidi::_ReservedMidi1() {}
267 void BMidi::_ReservedMidi2() {}
268 void BMidi::_ReservedMidi3() {}
269 
270 //------------------------------------------------------------------------------
271 
272 void BMidi::Run()
273 {
274 	// do nothing
275 }
276 
277 //------------------------------------------------------------------------------
278 
279 void BMidi::SprayNoteOff(
280 	uchar channel, uchar note, uchar velocity, uint32 time) const
281 {
282 	producer->SprayNoteOff(
283 		channel - 1, note, velocity, MAKE_BIGTIME(time));
284 }
285 
286 //------------------------------------------------------------------------------
287 
288 void BMidi::SprayNoteOn(
289 	uchar channel, uchar note, uchar velocity, uint32 time) const
290 {
291 	producer->SprayNoteOn(
292 		channel - 1, note, velocity, MAKE_BIGTIME(time));
293 }
294 
295 //------------------------------------------------------------------------------
296 
297 void BMidi::SprayKeyPressure(
298 	uchar channel, uchar note, uchar pressure, uint32 time) const
299 {
300 	producer->SprayKeyPressure(
301 		channel - 1, note, pressure, MAKE_BIGTIME(time));
302 }
303 
304 //------------------------------------------------------------------------------
305 
306 void BMidi::SprayControlChange(
307 	uchar channel, uchar controlNumber, uchar controlValue,
308 	uint32 time) const
309 {
310 	producer->SprayControlChange(
311 		channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time));
312 }
313 
314 //------------------------------------------------------------------------------
315 
316 void BMidi::SprayProgramChange(
317 	uchar channel, uchar programNumber, uint32 time) const
318 {
319 	producer->SprayProgramChange(
320 		channel - 1, programNumber, MAKE_BIGTIME(time));
321 }
322 
323 //------------------------------------------------------------------------------
324 
325 void BMidi::SprayChannelPressure(
326 	uchar channel, uchar pressure, uint32 time) const
327 {
328 	producer->SprayChannelPressure(
329 		channel - 1, pressure, MAKE_BIGTIME(time));
330 }
331 
332 //------------------------------------------------------------------------------
333 
334 void BMidi::SprayPitchBend(
335 	uchar channel, uchar lsb, uchar msb, uint32 time) const
336 {
337 	producer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time));
338 }
339 
340 //------------------------------------------------------------------------------
341 
342 void BMidi::SpraySystemExclusive(
343 	void* data, size_t length, uint32 time) const
344 {
345 	producer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
346 }
347 
348 //------------------------------------------------------------------------------
349 
350 void BMidi::SpraySystemCommon(
351 	uchar status, uchar data1, uchar data2, uint32 time) const
352 {
353 	producer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
354 }
355 
356 //------------------------------------------------------------------------------
357 
358 void BMidi::SpraySystemRealTime(uchar status, uint32 time) const
359 {
360 	producer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
361 }
362 
363 //------------------------------------------------------------------------------
364 
365 void BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
366 {
367 	producer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
368 }
369 
370 //------------------------------------------------------------------------------
371