xref: /haiku/src/kits/midi/Midi.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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
28 _run_thread(void* data)
29 {
30 	BMidi* midi = (BMidi*)data;
31 	midi->Run();
32 	midi->fIsRunning = false;
33 	return 0;
34 }
35 
36 
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 
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
63 BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
64 {
65 	// do nothing
66 }
67 
68 
69 void
70 BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
71 {
72 	// do nothing
73 }
74 
75 
76 void
77 BMidi::KeyPressure(
78 	uchar channel, uchar note, uchar pressure, uint32 time)
79 {
80 	// do nothing
81 }
82 
83 
84 void
85 BMidi::ControlChange(
86 	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
87 {
88 	// do nothing
89 }
90 
91 
92 void
93 BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
94 {
95 	// do nothing
96 }
97 
98 
99 void
100 BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
101 {
102 	// do nothing
103 }
104 
105 
106 void
107 BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
108 {
109 	// do nothing
110 }
111 
112 
113 void
114 BMidi::SystemExclusive(void* data, size_t length, uint32 time)
115 {
116 	// do nothing
117 }
118 
119 
120 void
121 BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
122 {
123 	// do nothing
124 }
125 
126 
127 void
128 BMidi::SystemRealTime(uchar status, uint32 time)
129 {
130 	// do nothing
131 }
132 
133 
134 void
135 BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
136 {
137 	// do nothing
138 }
139 
140 
141 void
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
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
182 BMidi::Stop()
183 {
184 	AllNotesOff();
185 	fThreadId = -1;
186 }
187 
188 
189 bool
190 BMidi::IsRunning() const
191 {
192 	return fIsRunning;
193 }
194 
195 
196 void
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
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
220 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*
230 BMidi::Connections() const
231 {
232 	return fConnections;
233 }
234 
235 
236 void
237 BMidi::SnoozeUntil(uint32 time) const
238 {
239 	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
240 }
241 
242 
243 bool
244 BMidi::KeepRunning()
245 {
246 	return (fThreadId != -1);
247 }
248 
249 
250 void BMidi::_ReservedMidi1() {}
251 void BMidi::_ReservedMidi2() {}
252 void BMidi::_ReservedMidi3() {}
253 
254 
255 void
256 BMidi::Run()
257 {
258 	// do nothing
259 }
260 
261 
262 void
263 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
272 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
281 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
290 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
300 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
309 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
318 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
326 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
334 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
342 BMidi::SpraySystemRealTime(uchar status, uint32 time) const
343 {
344 	fProducer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
345 }
346 
347 
348 void
349 BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
350 {
351 	fProducer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
352 }
353 
354