2 * Copyright 2005-2006, Haiku.
4 * Copyright (c) 2002-2004 Matthijs Hollemans
5 * Distributed under the terms of the MIT License.
14 #include <MidiConsumer.h>
15 #include <MidiProducer.h>
16 #include <MidiRoster.h>
20 BMidiLocalProducer::BMidiLocalProducer(const char* name
)
23 TRACE(("BMidiLocalProducer::BMidiLocalProducer"))
28 BMidiRoster::MidiRoster()->CreateLocal(this);
32 BMidiLocalProducer::~BMidiLocalProducer()
34 TRACE(("BMidiLocalProducer::~BMidiLocalProducer"))
36 BMidiRoster::MidiRoster()->DeleteLocal(this);
41 BMidiLocalProducer::Connected(BMidiConsumer
* cons
)
44 TRACE(("Connected() %" B_PRId32
" to %" B_PRId32
"", ID(), cons
->ID()))
51 BMidiLocalProducer::Disconnected(BMidiConsumer
* cons
)
54 TRACE(("Disconnected() %" B_PRId32
" from %" B_PRId32
"", ID(), cons
->ID()))
61 BMidiLocalProducer::SprayData(void* data
, size_t length
,
62 bool atomic
, bigtime_t time
) const
64 SprayEvent(data
, length
, atomic
, time
);
69 BMidiLocalProducer::SprayNoteOff(uchar channel
, uchar note
,
70 uchar velocity
, bigtime_t time
) const
74 data
[0] = B_NOTE_OFF
+ channel
;
78 SprayEvent(&data
, 3, true, time
);
80 debugger("invalid MIDI channel");
86 BMidiLocalProducer::SprayNoteOn(uchar channel
, uchar note
,
87 uchar velocity
, bigtime_t time
) const
91 data
[0] = B_NOTE_ON
+ channel
;
95 SprayEvent(&data
, 3, true, time
);
97 debugger("invalid MIDI channel");
103 BMidiLocalProducer::SprayKeyPressure(uchar channel
, uchar note
,
104 uchar pressure
, bigtime_t time
) const
108 data
[0] = B_KEY_PRESSURE
+ channel
;
112 SprayEvent(&data
, 3, true, time
);
114 debugger("invalid MIDI channel");
120 BMidiLocalProducer::SprayControlChange(uchar channel
,
121 uchar controlNumber
, uchar controlValue
, bigtime_t time
) const
125 data
[0] = B_CONTROL_CHANGE
+ channel
;
126 data
[1] = controlNumber
;
127 data
[2] = controlValue
;
129 SprayEvent(&data
, 3, true, time
);
131 debugger("invalid MIDI channel");
137 BMidiLocalProducer::SprayProgramChange(uchar channel
,
138 uchar programNumber
, bigtime_t time
) const
142 data
[0] = B_PROGRAM_CHANGE
+ channel
;
143 data
[1] = programNumber
;
145 SprayEvent(&data
, 2, true, time
);
147 debugger("invalid MIDI channel");
153 BMidiLocalProducer::SprayChannelPressure(uchar channel
,
154 uchar pressure
, bigtime_t time
) const
158 data
[0] = B_CHANNEL_PRESSURE
+ channel
;
161 SprayEvent(&data
, 2, true, time
);
163 debugger("invalid MIDI channel");
169 BMidiLocalProducer::SprayPitchBend(uchar channel
,
170 uchar lsb
, uchar msb
, bigtime_t time
) const
174 data
[0] = B_PITCH_BEND
+ channel
;
178 SprayEvent(&data
, 3, true, time
);
180 debugger("invalid MIDI channel");
186 BMidiLocalProducer::SpraySystemExclusive(void* data
,
187 size_t length
, bigtime_t time
) const
189 SprayEvent(data
, length
, true, time
, true);
194 BMidiLocalProducer::SpraySystemCommon(uchar status
, uchar data1
,
195 uchar data2
, bigtime_t time
) const
209 case B_CABLE_MESSAGE
:
210 case B_MIDI_TIME_CODE
:
215 case B_SONG_POSITION
:
220 debugger("invalid system common status");
224 SprayEvent(&data
, len
, true, time
);
229 BMidiLocalProducer::SpraySystemRealTime(uchar status
,
230 bigtime_t time
) const
232 if (status
>= B_TIMING_CLOCK
)
233 SprayEvent(&status
, 1, true, time
);
235 debugger("invalid real time status");
240 BMidiLocalProducer::SprayTempoChange(int32 beatsPerMinute
,
241 bigtime_t time
) const
243 int32 tempo
= 60000000 / beatsPerMinute
;
249 data
[3] = tempo
>> 16;
250 data
[4] = tempo
>> 8;
253 SprayEvent(&data
, 6, true, time
);
256 //------------------------------------------------------------------------------
258 void BMidiLocalProducer::_Reserved1() { }
259 void BMidiLocalProducer::_Reserved2() { }
260 void BMidiLocalProducer::_Reserved3() { }
261 void BMidiLocalProducer::_Reserved4() { }
262 void BMidiLocalProducer::_Reserved5() { }
263 void BMidiLocalProducer::_Reserved6() { }
264 void BMidiLocalProducer::_Reserved7() { }
265 void BMidiLocalProducer::_Reserved8() { }
267 //------------------------------------------------------------------------------
270 BMidiLocalProducer::SprayEvent(const void* data
, size_t length
,
271 bool atomic
, bigtime_t time
, bool sysex
) const
273 if (LockProducer()) {
274 if (CountConsumers() > 0) {
275 // We don't just send the MIDI event data to all connected
276 // consumers, we also send a header. The header contains our
277 // ID (4 bytes), the consumer's ID (4 bytes), the performance
278 // time (8 bytes), whether the data is atomic (1 byte), and
279 // padding (3 bytes). The MIDI event data follows the header.
281 size_t buf_size
= 20 + length
;
283 // add 0xF0 and 0xF7 markers
287 uint8
* buffer
= (uint8
*)malloc(buf_size
);
288 if (buffer
!= NULL
) {
289 *((uint32
*) (buffer
+ 0)) = fId
;
290 *((bigtime_t
*) (buffer
+ 8)) = time
;
291 *((uint32
*) (buffer
+ 16)) = 0;
292 *((bool*) (buffer
+ 16)) = atomic
;
295 *((uint8
*) (buffer
+ 20)) = B_SYS_EX_START
;
297 memcpy(buffer
+ 21, data
, length
);
299 *((uint8
*) (buffer
+ buf_size
- 1)) = B_SYS_EX_END
;
300 } else if (data
!= NULL
) {
301 memcpy(buffer
+ 20, data
, length
);
304 for (int32 t
= 0; t
< CountConsumers(); ++t
) {
305 BMidiConsumer
* cons
= ConsumerAt(t
);
306 *((uint32
*) (buffer
+ 4)) = cons
->fId
;
309 printf("*** spraying: ");
310 for (uint32 t
= 0; t
< buf_size
; ++t
)
312 printf("%02X, ", buffer
[t
]);
317 write_port(cons
->fPort
, 0, buffer
, buf_size
);