xref: /haiku/src/kits/midi/Midi.cpp (revision b2e8d9627a0ea786115cbe429d69362edc7c7986)
1 /*
2  * Copyright 2006, Haiku.
3  *
4  * Copyright (c) 2002-2003 Matthijs Hollemans
5  * Copyright (c) 2002 Michael Pfeiffer
6  * Copyright (c) 2002 Jerome Leveque
7  * Copyright (c) 2002 Paul Stadler
8  * Distributed under the terms of the MIT License.
9  *
10  * Authors:
11  *		Matthijs Hollemans
12  *		Michael Pfeiffer
13  *		Jérôme Leveque
14  *		Paul Stadler
15  */
16 
17 #include <List.h>
18 #include <Midi.h>
19 #include <MidiProducer.h>
20 
21 #include "MidiGlue.h"
22 #include "debug.h"
23 
24 using namespace BPrivate;
25 
26 
27 status_t
_run_thread(void * data)28 _run_thread(void* data)
29 {
30 	BMidi* midi = (BMidi*)data;
31 	midi->Run();
32 	midi->fIsRunning = false;
33 	return 0;
34 }
35 
36 
BMidi()37 BMidi::BMidi()
38 {
39 	fConnections = new BList;
40 	fThreadId    = -1;
41 	fIsRunning   = false;
42 
43 	fProducer = new BMidiLocalProducer("MidiGlue(out)");
44 	fConsumer = new BMidiGlue(this, "MidiGlue(in)");
45 }
46 
47 
~BMidi()48 BMidi::~BMidi()
49 {
50 	Stop();
51 
52 	status_t result;
53 	wait_for_thread(fThreadId, &result);
54 
55 	fProducer->Release();
56 	fConsumer->Release();
57 
58 	delete fConnections;
59 }
60 
61 
62 void
NoteOff(uchar channel,uchar note,uchar velocity,uint32 time)63 BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
64 {
65 	// do nothing
66 }
67 
68 
69 void
NoteOn(uchar channel,uchar note,uchar velocity,uint32 time)70 BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
71 {
72 	// do nothing
73 }
74 
75 
76 void
KeyPressure(uchar channel,uchar note,uchar pressure,uint32 time)77 BMidi::KeyPressure(
78 	uchar channel, uchar note, uchar pressure, uint32 time)
79 {
80 	// do nothing
81 }
82 
83 
84 void
ControlChange(uchar channel,uchar controlNumber,uchar controlValue,uint32 time)85 BMidi::ControlChange(
86 	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
87 {
88 	// do nothing
89 }
90 
91 
92 void
ProgramChange(uchar channel,uchar programNumber,uint32 time)93 BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
94 {
95 	// do nothing
96 }
97 
98 
99 void
ChannelPressure(uchar channel,uchar pressure,uint32 time)100 BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
101 {
102 	// do nothing
103 }
104 
105 
106 void
PitchBend(uchar channel,uchar lsb,uchar msb,uint32 time)107 BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
108 {
109 	// do nothing
110 }
111 
112 
113 void
SystemExclusive(void * data,size_t length,uint32 time)114 BMidi::SystemExclusive(void* data, size_t length, uint32 time)
115 {
116 	// do nothing
117 }
118 
119 
120 void
SystemCommon(uchar status,uchar data1,uchar data2,uint32 time)121 BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
122 {
123 	// do nothing
124 }
125 
126 
127 void
SystemRealTime(uchar status,uint32 time)128 BMidi::SystemRealTime(uchar status, uint32 time)
129 {
130 	// do nothing
131 }
132 
133 
134 void
TempoChange(int32 beatsPerMinute,uint32 time)135 BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
136 {
137 	// do nothing
138 }
139 
140 
141 void
AllNotesOff(bool justChannel,uint32 time)142 BMidi::AllNotesOff(bool justChannel, uint32 time)
143 {
144 	for (uchar channel = 1; channel <= 16; ++channel) {
145 		SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time);
146 
147 		if (!justChannel) {
148 			for (uchar note = 0; note <= 0x7F; ++note) {
149 				SprayNoteOff(channel, note, 0, time);
150 			}
151 		}
152 	}
153 }
154 
155 
156 status_t
Start()157 BMidi::Start()
158 {
159 	if (fIsRunning)
160 		return B_OK;
161 
162 	status_t err = spawn_thread(
163 		_run_thread, "MidiRunThread", B_URGENT_PRIORITY, this);
164 
165 	if (err < B_OK)
166 		return err;
167 
168 	fThreadId  = err;
169 	fIsRunning = true;
170 
171 	err = resume_thread(fThreadId);
172 	if (err != B_OK) {
173 		fThreadId  = -1;
174 		fIsRunning = false;
175 	}
176 
177 	return err;
178 }
179 
180 
181 void
Stop()182 BMidi::Stop()
183 {
184 	AllNotesOff();
185 	fThreadId = -1;
186 }
187 
188 
189 bool
IsRunning() const190 BMidi::IsRunning() const
191 {
192 	return fIsRunning;
193 }
194 
195 
196 void
Connect(BMidi * toObject)197 BMidi::Connect(BMidi* toObject)
198 {
199 	if (toObject != NULL) {
200 		if (fProducer->Connect(toObject->fConsumer) == B_OK) {
201 			fConnections->AddItem(toObject);
202 		}
203 	}
204 }
205 
206 
207 void
Disconnect(BMidi * fromObject)208 BMidi::Disconnect(BMidi* fromObject)
209 {
210 	if (fromObject == NULL)
211 		return;
212 
213 	if (fProducer->Disconnect(fromObject->fConsumer) == B_OK) {
214 		fConnections->RemoveItem(fromObject);
215 	}
216 }
217 
218 
219 bool
IsConnected(BMidi * toObject) const220 BMidi::IsConnected(BMidi* toObject) const
221 {
222 	if (toObject != NULL)
223 		return fProducer->IsConnected(toObject->fConsumer);
224 
225 	return false;
226 }
227 
228 
229 BList*
Connections() const230 BMidi::Connections() const
231 {
232 	return fConnections;
233 }
234 
235 
236 void
SnoozeUntil(uint32 time) const237 BMidi::SnoozeUntil(uint32 time) const
238 {
239 	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
240 }
241 
242 
243 bool
KeepRunning()244 BMidi::KeepRunning()
245 {
246 	return (fThreadId != -1);
247 }
248 
249 
_ReservedMidi1()250 void BMidi::_ReservedMidi1() {}
_ReservedMidi2()251 void BMidi::_ReservedMidi2() {}
_ReservedMidi3()252 void BMidi::_ReservedMidi3() {}
253 
254 
255 void
Run()256 BMidi::Run()
257 {
258 	// do nothing
259 }
260 
261 
262 void
SprayNoteOff(uchar channel,uchar note,uchar velocity,uint32 time) const263 BMidi::SprayNoteOff(
264 	uchar channel, uchar note, uchar velocity, uint32 time) const
265 {
266 	fProducer->SprayNoteOff(
267 		channel - 1, note, velocity, MAKE_BIGTIME(time));
268 }
269 
270 
271 void
SprayNoteOn(uchar channel,uchar note,uchar velocity,uint32 time) const272 BMidi::SprayNoteOn(
273 	uchar channel, uchar note, uchar velocity, uint32 time) const
274 {
275 	fProducer->SprayNoteOn(
276 		channel - 1, note, velocity, MAKE_BIGTIME(time));
277 }
278 
279 
280 void
SprayKeyPressure(uchar channel,uchar note,uchar pressure,uint32 time) const281 BMidi::SprayKeyPressure(
282 	uchar channel, uchar note, uchar pressure, uint32 time) const
283 {
284 	fProducer->SprayKeyPressure(
285 		channel - 1, note, pressure, MAKE_BIGTIME(time));
286 }
287 
288 
289 void
SprayControlChange(uchar channel,uchar controlNumber,uchar controlValue,uint32 time) const290 BMidi::SprayControlChange(
291 	uchar channel, uchar controlNumber, uchar controlValue,
292 	uint32 time) const
293 {
294 	fProducer->SprayControlChange(
295 		channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time));
296 }
297 
298 
299 void
SprayProgramChange(uchar channel,uchar programNumber,uint32 time) const300 BMidi::SprayProgramChange(
301 	uchar channel, uchar programNumber, uint32 time) const
302 {
303 	fProducer->SprayProgramChange(
304 		channel - 1, programNumber, MAKE_BIGTIME(time));
305 }
306 
307 
308 void
SprayChannelPressure(uchar channel,uchar pressure,uint32 time) const309 BMidi::SprayChannelPressure(
310 	uchar channel, uchar pressure, uint32 time) const
311 {
312 	fProducer->SprayChannelPressure(
313 		channel - 1, pressure, MAKE_BIGTIME(time));
314 }
315 
316 
317 void
SprayPitchBend(uchar channel,uchar lsb,uchar msb,uint32 time) const318 BMidi::SprayPitchBend(
319 	uchar channel, uchar lsb, uchar msb, uint32 time) const
320 {
321 	fProducer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time));
322 }
323 
324 
325 void
SpraySystemExclusive(void * data,size_t length,uint32 time) const326 BMidi::SpraySystemExclusive(
327 	void* data, size_t length, uint32 time) const
328 {
329 	fProducer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
330 }
331 
332 
333 void
SpraySystemCommon(uchar status,uchar data1,uchar data2,uint32 time) const334 BMidi::SpraySystemCommon(
335 	uchar status, uchar data1, uchar data2, uint32 time) const
336 {
337 	fProducer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
338 }
339 
340 
341 void
SpraySystemRealTime(uchar status,uint32 time) const342 BMidi::SpraySystemRealTime(uchar status, uint32 time) const
343 {
344 	fProducer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
345 }
346 
347 
348 void
SprayTempoChange(int32 beatsPerMinute,uint32 time) const349 BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
350 {
351 	fProducer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
352 }
353 
354