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
24using namespace BPrivate;
25
26
27status_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
37BMidi::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
48BMidi::~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
62void
63BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
64{
65	// do nothing
66}
67
68
69void
70BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
71{
72	// do nothing
73}
74
75
76void
77BMidi::KeyPressure(
78	uchar channel, uchar note, uchar pressure, uint32 time)
79{
80	// do nothing
81}
82
83
84void
85BMidi::ControlChange(
86	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
87{
88	// do nothing
89}
90
91
92void
93BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
94{
95	// do nothing
96}
97
98
99void
100BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
101{
102	// do nothing
103}
104
105
106void
107BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
108{
109	// do nothing
110}
111
112
113void
114BMidi::SystemExclusive(void* data, size_t length, uint32 time)
115{
116	// do nothing
117}
118
119
120void
121BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
122{
123	// do nothing
124}
125
126
127void
128BMidi::SystemRealTime(uchar status, uint32 time)
129{
130	// do nothing
131}
132
133
134void
135BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
136{
137	// do nothing
138}
139
140
141void
142BMidi::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
156status_t
157BMidi::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
181void
182BMidi::Stop()
183{
184	AllNotesOff();
185	fThreadId = -1;
186}
187
188
189bool
190BMidi::IsRunning() const
191{
192	return fIsRunning;
193}
194
195
196void
197BMidi::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
207void
208BMidi::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
219bool
220BMidi::IsConnected(BMidi* toObject) const
221{
222	if (toObject != NULL)
223		return fProducer->IsConnected(toObject->fConsumer);
224
225	return false;
226}
227
228
229BList*
230BMidi::Connections() const
231{
232	return fConnections;
233}
234
235
236void
237BMidi::SnoozeUntil(uint32 time) const
238{
239	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
240}
241
242
243bool
244BMidi::KeepRunning()
245{
246	return (fThreadId != -1);
247}
248
249
250void BMidi::_ReservedMidi1() {}
251void BMidi::_ReservedMidi2() {}
252void BMidi::_ReservedMidi3() {}
253
254
255void
256BMidi::Run()
257{
258	// do nothing
259}
260
261
262void
263BMidi::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
271void
272BMidi::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
280void
281BMidi::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
289void
290BMidi::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
299void
300BMidi::SprayProgramChange(
301	uchar channel, uchar programNumber, uint32 time) const
302{
303	fProducer->SprayProgramChange(
304		channel - 1, programNumber, MAKE_BIGTIME(time));
305}
306
307
308void
309BMidi::SprayChannelPressure(
310	uchar channel, uchar pressure, uint32 time) const
311{
312	fProducer->SprayChannelPressure(
313		channel - 1, pressure, MAKE_BIGTIME(time));
314}
315
316
317void
318BMidi::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
325void
326BMidi::SpraySystemExclusive(
327	void* data, size_t length, uint32 time) const
328{
329	fProducer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
330}
331
332
333void
334BMidi::SpraySystemCommon(
335	uchar status, uchar data1, uchar data2, uint32 time) const
336{
337	fProducer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
338}
339
340
341void
342BMidi::SpraySystemRealTime(uchar status, uint32 time) const
343{
344	fProducer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
345}
346
347
348void
349BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
350{
351	fProducer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
352}
353
354