xref: /haiku/src/kits/midi/Midi.cpp (revision 81f5654c124bf46fba0fd251f208e2d88d81e1ce)
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 using namespace BPrivate;
34 
35 //------------------------------------------------------------------------------
36 
37 status_t _run_thread(void* data)
38 {
39 	BMidi* midi = (BMidi*) data;
40 	midi->Run();
41 	midi->isRunning = false;
42 	return 0;
43 }
44 
45 //------------------------------------------------------------------------------
46 
47 BMidi::BMidi()
48 {
49 	connections = new BList;
50 	threadId    = -1;
51 	isRunning   = false;
52 
53 	producer = new BMidiLocalProducer("MidiGlue(out)");
54 	consumer = new BMidiGlue(this, "MidiGlue(in)");
55 }
56 
57 //------------------------------------------------------------------------------
58 
59 BMidi::~BMidi()
60 {
61 	Stop();
62 
63 	status_t result;
64 	wait_for_thread(threadId, &result);
65 
66 	producer->Release();
67 	consumer->Release();
68 
69 	delete connections;
70 }
71 
72 //------------------------------------------------------------------------------
73 
74 void BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
75 {
76 	// do nothing
77 }
78 
79 //------------------------------------------------------------------------------
80 
81 void BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
82 {
83 	// do nothing
84 }
85 
86 //------------------------------------------------------------------------------
87 
88 void BMidi::KeyPressure(
89 	uchar channel, uchar note, uchar pressure, uint32 time)
90 {
91 	// do nothing
92 }
93 
94 //------------------------------------------------------------------------------
95 
96 void BMidi::ControlChange(
97 	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
98 {
99 	// do nothing
100 }
101 
102 //------------------------------------------------------------------------------
103 
104 void BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
105 {
106 	// do nothing
107 }
108 
109 //------------------------------------------------------------------------------
110 
111 void BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
112 {
113 	// do nothing
114 }
115 
116 //------------------------------------------------------------------------------
117 
118 void BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
119 {
120 	// do nothing
121 }
122 
123 //------------------------------------------------------------------------------
124 
125 void BMidi::SystemExclusive(void* data, size_t length, uint32 time)
126 {
127 	// do nothing
128 }
129 
130 //------------------------------------------------------------------------------
131 
132 void BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
133 {
134 	// do nothing
135 }
136 
137 //------------------------------------------------------------------------------
138 
139 void BMidi::SystemRealTime(uchar status, uint32 time)
140 {
141 	// do nothing
142 }
143 
144 //------------------------------------------------------------------------------
145 
146 void BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
147 {
148 	// do nothing
149 }
150 
151 //------------------------------------------------------------------------------
152 
153 void BMidi::AllNotesOff(bool justChannel, uint32 time)
154 {
155 	for (uchar channel = 1; channel <= 16; ++channel)
156 	{
157 		SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time);
158 
159 		if (!justChannel)
160 		{
161 			for (uchar note = 0; note <= 0x7F; ++note)
162 			{
163 				SprayNoteOff(channel, note, 0, time);
164 			}
165 		}
166 	}
167 }
168 
169 //------------------------------------------------------------------------------
170 
171 status_t BMidi::Start()
172 {
173 	if (isRunning) { return B_OK; }
174 
175 	status_t err = spawn_thread(
176 		_run_thread, "MidiRunThread", B_URGENT_PRIORITY, this);
177 
178 	if (err < B_OK) { return err; }
179 
180 	threadId  = err;
181 	isRunning = true;
182 
183 	err = resume_thread(threadId);
184 	if (err != B_OK)
185 	{
186 		threadId  = -1;
187 		isRunning = false;
188 	}
189 
190 	return err;
191 }
192 
193 //------------------------------------------------------------------------------
194 
195 void BMidi::Stop()
196 {
197 	threadId = -1;
198 }
199 
200 //------------------------------------------------------------------------------
201 
202 bool BMidi::IsRunning() const
203 {
204 	return isRunning;
205 }
206 
207 //------------------------------------------------------------------------------
208 
209 void BMidi::Connect(BMidi* toObject)
210 {
211 	if (toObject != NULL)
212 	{
213 		if (producer->Connect(toObject->consumer) == B_OK)
214 		{
215 			connections->AddItem(toObject);
216 		}
217 	}
218 }
219 
220 //------------------------------------------------------------------------------
221 
222 void BMidi::Disconnect(BMidi* fromObject)
223 {
224 	if (fromObject != NULL)
225 	{
226 		if (producer->Disconnect(fromObject->consumer) == B_OK)
227 		{
228 			connections->RemoveItem(fromObject);
229 		}
230 	}
231 }
232 
233 //------------------------------------------------------------------------------
234 
235 bool BMidi::IsConnected(BMidi* toObject) const
236 {
237 	if (toObject != NULL)
238 	{
239 		return producer->IsConnected(toObject->consumer);
240 	}
241 
242 	return false;
243 }
244 
245 //------------------------------------------------------------------------------
246 
247 BList* BMidi::Connections() const
248 {
249 	return connections;
250 }
251 
252 //------------------------------------------------------------------------------
253 
254 void BMidi::SnoozeUntil(uint32 time) const
255 {
256 	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
257 }
258 
259 //------------------------------------------------------------------------------
260 
261 bool BMidi::KeepRunning()
262 {
263 	return (threadId != -1);
264 }
265 
266 //------------------------------------------------------------------------------
267 
268 void BMidi::_ReservedMidi1() {}
269 void BMidi::_ReservedMidi2() {}
270 void BMidi::_ReservedMidi3() {}
271 
272 //------------------------------------------------------------------------------
273 
274 void BMidi::Run()
275 {
276 	// do nothing
277 }
278 
279 //------------------------------------------------------------------------------
280 
281 void BMidi::SprayNoteOff(
282 	uchar channel, uchar note, uchar velocity, uint32 time) const
283 {
284 	producer->SprayNoteOff(
285 		channel - 1, note, velocity, MAKE_BIGTIME(time));
286 }
287 
288 //------------------------------------------------------------------------------
289 
290 void BMidi::SprayNoteOn(
291 	uchar channel, uchar note, uchar velocity, uint32 time) const
292 {
293 	producer->SprayNoteOn(
294 		channel - 1, note, velocity, MAKE_BIGTIME(time));
295 }
296 
297 //------------------------------------------------------------------------------
298 
299 void BMidi::SprayKeyPressure(
300 	uchar channel, uchar note, uchar pressure, uint32 time) const
301 {
302 	producer->SprayKeyPressure(
303 		channel - 1, note, pressure, MAKE_BIGTIME(time));
304 }
305 
306 //------------------------------------------------------------------------------
307 
308 void BMidi::SprayControlChange(
309 	uchar channel, uchar controlNumber, uchar controlValue,
310 	uint32 time) const
311 {
312 	producer->SprayControlChange(
313 		channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time));
314 }
315 
316 //------------------------------------------------------------------------------
317 
318 void BMidi::SprayProgramChange(
319 	uchar channel, uchar programNumber, uint32 time) const
320 {
321 	producer->SprayProgramChange(
322 		channel - 1, programNumber, MAKE_BIGTIME(time));
323 }
324 
325 //------------------------------------------------------------------------------
326 
327 void BMidi::SprayChannelPressure(
328 	uchar channel, uchar pressure, uint32 time) const
329 {
330 	producer->SprayChannelPressure(
331 		channel - 1, pressure, MAKE_BIGTIME(time));
332 }
333 
334 //------------------------------------------------------------------------------
335 
336 void BMidi::SprayPitchBend(
337 	uchar channel, uchar lsb, uchar msb, uint32 time) const
338 {
339 	producer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time));
340 }
341 
342 //------------------------------------------------------------------------------
343 
344 void BMidi::SpraySystemExclusive(
345 	void* data, size_t length, uint32 time) const
346 {
347 	producer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
348 }
349 
350 //------------------------------------------------------------------------------
351 
352 void BMidi::SpraySystemCommon(
353 	uchar status, uchar data1, uchar data2, uint32 time) const
354 {
355 	producer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
356 }
357 
358 //------------------------------------------------------------------------------
359 
360 void BMidi::SpraySystemRealTime(uchar status, uint32 time) const
361 {
362 	producer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
363 }
364 
365 //------------------------------------------------------------------------------
366 
367 void BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
368 {
369 	producer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
370 }
371 
372 //------------------------------------------------------------------------------
373