xref: /haiku/docs/user/midi2/MidiConsumer.dox (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1/*!
2	\file MidiConsumer.h
3	\ingroup midi2
4	\ingroup libbe
5	\brief Defines consumer classes for the MIDI Kit.
6*/
7
8
9/*!
10	\class BMidiConsumer MidiConsumer.h
11	\ingroup midi2
12	\ingroup libmidi2
13	\ingroup libbe
14	\brief Receives MIDI events from a producer
15
16	A consumer is an object that knows how to deal with incoming MIDI events. A
17	consumer can be connected to multiple producers at the same time. There is no
18	way to find out which producers are connected to this consumer just by looking
19	at the BMidiConsumer object; you will have to consult BMidiRoster for that.
20
21	A BMidiConsumer either represents a local consumer, i.e. a class extending from
22	BMidiLocalConsumer, or is a proxy for a remote object published by another app.
23*/
24
25
26/*!
27	\fn bigtime_t BMidiConsumer::Latency() const
28	\brief Returns the latency of this consumer
29
30	The latency is measured in microseconds. Producers should attempt to get MIDI
31	events to this consumer by <I>(when - latency)</I>. You do this by subtracting
32	the latency from the performance time when you spray the events (provided that
33	you spray these events ahead of time, of course).
34
35	You cannot <I>set</I> the latency on a BMidiConsumer, only on a
36	BMidiLocalConsumer.
37
38	The latency issue gets slightly more complicated when multiple endpoints are
39	chained together, as in the following picture:
40
41\verbatim
42+-------+     +-------------+     +-------+
43|       |     |             |     |       |
44| prodA |---->| consB prodB |---->| consC |
45|       |     |             |     |       |
46+-------+     +-------------+     +-------+
47  appA          appB (filter)       appC
48\endverbatim
49
50	Suppose consC has 200ms latency, and consB has 100ms latency. If consB simply
51	reports 100ms, then prodA will schedule its events for (t - 100), which is
52	really 200ms too late. (Of course, producers send out their events as soon as
53	possible, so depending on the load of the system, everything may work out just
54	fine.)
55
56	ConsB should report the latency of the consumer that is hooked up to its
57	output, consC, in addition to its own latency. In other words, the full
58	downstream latency. So, the reported latency in this case would be 300ms. This
59	also means that appB should change the latency of consB when prodB makes or
60	breaks a connection, and when consC reports a latency change. (If multiple
61	consumers are connected to prodB, you should take the slowest one.)
62	Unfortunately, the Midi Kit provides no easy mechanism for doing any of this,
63	so you are on your own here.
64*/
65
66/*!
67	\class BMidiLocalConsumer MidiConsumer.h
68	\ingroup midi2
69	\ingroup libmidi2
70	\ingroup libbe
71	\brief A consumer endpoint that is created by your own application.
72
73	If you want to create a consumer that reacts to MIDI events, you should
74	subclass BMidiLocalConsumer.
75
76	Each local consumer has its own thread that receives and dispatches the MIDI
77	events. Whenever MIDI data arrives, the Data() hook passes the MIDI event on to
78	a more specific hook function: NoteOn(), NoteOff(), SystemExclusive(), and so
79	on. Calls to these hook functions are serialized -- they will never have to be
80	re-entrant. They also should not be called from outside the thread that is
81	invoking them.
82
83	Your subclass can override any of the MIDI event hooks. BMidiLocalConsumer
84	doesn't provide default implementations for them, so you don't have to call a
85	hook's default implementation if you override it. For complete control, you can
86	also override Data().
87
88	Most hook functions take a channel argument. Even though MIDI channels are
89	really numbered 1 through 16, the hook functions work with channels 0 through
90	15. The performance time for the event is specified in microseconds relative to
91	the system time base. A performance time that is 0 (or really any time in the
92	past) means "play as soon as possible". See the \ref midi2time "introduction"
93	for more information about timing and consumers.
94
95	The thread driving the consumer's events is a very high priority real time
96	thread. Events should be handled as quickly as possible (not counting
97	snoozing). If non-time-critical computation is needed it may be wise to queue
98	events up for a lower priority thread to handle them external to the main event
99	thread.
100*/
101
102
103/*!
104	\fn BMidiLocalConsumer::BMidiLocalConsumer(const char *name = NULL)
105	\brief Creates a new local consumer endpoint
106
107	The new endpoint is not visible to other applications until you Register() it.
108
109	You can tell the constructor what the name of the new consumer will be. If you
110	pass NULL (or use the default argument), then the consumer's name will be an
111	empty string. It won't be NULL, since endpoint names cannot be NULL.
112
113	There is no guarantee that the endpoint will be successfully created. For
114	example, the Midi Server may not be running. Therefore, you should always call
115	IsValid() after creating a new endpoint to make sure that everything went okay.
116	If not, Release() the object to reclaim memory and abort gracefully.
117
118\code
119MyConsumer* cons = new MyConsumer(...);
120if (!cons->IsValid())
121{
122    cons->Release();
123    ...exit gracefully...
124}
125\endcode
126
127*/
128
129
130/*!
131	\fn void BMidiLocalConsumer::SetLatency(bigtime_t latency)
132	\brief Changes the published latency of the consumer.
133
134	\sa Latency()
135*/
136
137
138/*!
139	\fn int32 BMidiLocalConsumer::GetProducerID()
140	\brief Returns the ID of the producer that most recently sent a MIDI event to
141		   this consumer.
142
143	You can call this from one of the hooks to determine which producer the event
144	came from.
145*/
146
147
148/*!
149	\fn void BMidiLocalConsumer::SetTimeout(bigtime_t when, void* data)
150	\brief Requests that the Timeout() hook will be called at some point.
151
152	This method asks the consumer thread to call the Timeout() hook as soon as
153	possible after the timeout expires. For every call to SetTimeout(), the
154	Timeout() hook is only called once. Note: the term "timeout" may be a little
155	misleading; the hook will <I>always</I> be called, even if events are received
156	in the mean time. Apparently, this facility is handy for dealing with early
157	events.
158
159	Note that the event thread blocks on the consumer's port as long as no events
160	arrive. By default no timeout is set, and as a result the thread blocks
161	forever. Your call to SetTimeout() doesn't change this. The new timeout value
162	will go into effect the next time the thread tries to read from the port, i.e.
163	after the first event has been received. If no event ever comes in, the
164	Timeout() hook will never be called. This also means that you cannot cancel a
165	timeout once you have set it. To repeat, calling SetTimeout() only takes effect
166	after at least one new event has been received.
167
168	\param when An absolute time that's measured against the system clock.
169
170	\param data A pointer to a "cookie" that you can pass along to Timeout(). The
171	data is not copied, so you must ensure that the pointer remains valid until
172	Timeout() is called. You typically delete the data inside Timeout().
173*/
174
175
176/*!
177	\fn void BMidiLocalConsumer::Timeout(void* data)
178	\brief Hook function that is called per your own request.
179
180	\sa SetTimeout()
181*/
182
183/*!
184	\fn void BMidiLocalConsumer::Data(uchar* data, size_t length, bool atomic,
185		bigtime_t time)
186	\brief Invoked when raw MIDI is received.
187
188	What the default implementation of Data() does depends on the value of atomic.
189	If atomic is true, the data received comprises a single MIDI event; i.e. one
190	status byte followed by the appropriate number of data bytes and nothing else.
191	In this case, Data() calls the event-specific hook function that corresponds to
192	that status byte. This optimization is used by the Midi Kit to allow faster
193	dispatch of events generated by the specific Spray functions from
194	BMidiLocalProducer.
195
196	If atomic is false, Data() ignores the MIDI event. If you want a consumer to
197	handle non-atomic events, you have to override Data() and program this
198	yourself. In that case, you probably also want to call the default
199	implementation to handle the "normal" MIDI events.
200
201	Data() is rarely overridden, but you can override it if you want to. If you do,
202	remember that the data buffer is owned by the Midi Kit. Do not attempt to
203	modify or free it, lest you wish to be laughed at by other developers.
204
205	\param data the MIDI event data
206	\param length byte size of the data buffer
207	\param atomic whether the data buffer contains a single complete MIDI event
208	\param time the requested performance time of the event
209
210	\sa BMidiLocalProducer::SprayData()
211*/
212
213
214/*!
215	\fn void BMidiLocalConsumer::NoteOff(uchar channel, uchar note,
216		uchar velocity, bigtime_t time)
217	\brief Invoked when a Note Off event is received.
218
219	\sa BMidiLocalProducer::SprayNoteOff()
220*/
221
222
223/*!
224	\fn void BMidiLocalConsumer::NoteOn(uchar channel, uchar note,
225		uchar velocity, bigtime_t time)
226	\brief Invoked when a Note On event is received.
227
228	\sa BMidiLocalProducer::SprayNoteOn()
229*/
230
231
232/*!
233	\fn void BMidiLocalConsumer::KeyPressure(uchar channel, uchar note,
234		uchar pressure, bigtime_t time)
235	\brief Invoked when a Polyphonic Pressure (Aftertouch) event is received.
236
237	\sa BMidiLocalProducer::SprayKeyPressure()
238*/
239
240
241/*!
242	\fn void BMidiLocalConsumer::ControlChange(uchar channel,
243		uchar controlNumber, uchar controlValue, bigtime_t time)
244	\brief Invoked when a Controller Change event is received.
245
246	\sa BMidiLocalProducer::SprayControlChange()
247*/
248
249
250/*!
251	\fn void BMidiLocalConsumer::ProgramChange(uchar channel,
252		uchar programNumber, bigtime_t time)
253	\brief Invoked when a Program Change event is received.
254
255	\sa BMidiLocalProducer::SprayProgramChange()
256*/
257
258
259/*!
260	\fn void BMidiLocalConsumer::ChannelPressure(uchar channel,
261		uchar pressure, bigtime_t time)
262	\brief Invoked when a Channel Pressure event is received.
263
264	\sa BMidiLocalProducer::SprayChannelPressure()
265*/
266
267
268/*!
269	\fn void BMidiLocalConsumer::PitchBend(uchar channel, uchar lsb,
270		uchar msb, bigtime_t time)
271	\brief Invoked when a Pitch Bend event is received.
272
273	\sa BMidiLocalProducer::SprayPitchBend()
274*/
275
276
277/*!
278	\fn void BMidiLocalConsumer::SystemExclusive(void* data, size_t length,
279		bigtime_t time)
280	\brief Invoked when a System Exclusive event is received.
281
282	The data does not include the sysex start and end control bytes
283	(0xF0 and 0xF7), only the payload of the sysex message.
284
285	The data belongs to the Midi Kit and is only valid for the duration of
286	this event. You may not modify or free it.
287
288	\sa BMidiLocalProducer::SpraySystemExclusive()
289*/
290
291
292/*!
293	\fn void BMidiLocalConsumer::SystemCommon(uchar status, uchar data1,
294		uchar data2, bigtime_t time)
295	\brief Invoked when a System Common event is received.
296
297	Not all data bytes are used for all common events. Unused bytes are
298	set to 0.
299
300	\sa BMidiLocalProducer::SpraySystemCommon()
301*/
302
303
304/*!
305	\fn void BMidiLocalConsumer::SystemRealTime(uchar status, bigtime_t time)
306	\brief Invoked when a Real Time event is received.
307
308	\sa BMidiLocalProducer::SpraySystemRealTime()
309*/
310
311
312/*!
313	\fn void BMidiLocalConsumer::TempoChange(int32 beatsPerMinute, bigtime_t time)
314
315	\brief Invoked when a Tempo Change event is received
316	\sa BMidiLocalProducer::SprayTempoChange()
317*/
318
319
320/*!
321	\fn void BMidiLocalConsumer::AllNotesOff(bool justChannel, bigtime_t time)
322	\brief Not used.
323*/
324