1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @addtogroup Midi
18  * @{
19  */
20 
21 /**
22  * @file AMidi.h
23  */
24 
25 #ifndef ANDROID_MEDIA_AMIDI_H_
26 #define ANDROID_MEDIA_AMIDI_H_
27 
28 #include <stdarg.h>
29 #include <stdint.h>
30 #include <sys/types.h>
31 
32 #include <jni.h>
33 
34 #include <media/NdkMediaError.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #define AMIDI_API __attribute__((visibility("default")))
41 
42 typedef struct AMidiDevice AMidiDevice;
43 typedef struct AMidiInputPort AMidiInputPort;
44 typedef struct AMidiOutputPort AMidiOutputPort;
45 
46 /*
47  * Message Op Codes. Used to parse MIDI data packets
48  */
49 enum {
50     AMIDI_OPCODE_DATA = 1,      /* The MIDI packet contains normal MIDI data */
51     AMIDI_OPCODE_FLUSH = 2,     /* The MIDI packet contains just a MIDI FLUSH command. */
52                                 /* Forces the send of any pending MIDI data. */
53 };
54 
55 /*
56  * Type IDs for various MIDI devices.
57  */
58 enum {
59     AMIDI_DEVICE_TYPE_USB = 1,      /* A MIDI device connected to the Android USB port */
60     AMIDI_DEVICE_TYPE_VIRTUAL = 2,  /* A software object implementing MidiDeviceService */
61     AMIDI_DEVICE_TYPE_BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */
62 };
63 
64 /*
65  * Protocol IDs for various MIDI devices.
66  *
67  * Introduced in API 33.
68  */
69 typedef enum AMidiDevice_Protocol : int32_t {
70     /**
71      * Constant representing a default protocol with Universal MIDI Packets (UMP).
72      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
73      * All UMP data should be a multiple of 4 bytes.
74      * Use UMP to negotiate with the device with MIDI-CI.
75      * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
76      */
77     AMIDI_DEVICE_PROTOCOL_UMP_USE_MIDI_CI = 0,
78 
79     /**
80      * Constant representing a default protocol with Universal MIDI Packets (UMP).
81      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
82      * All UMP data should be a multiple of 4 bytes.
83      * Use MIDI 1.0 through UMP with packet sizes up to 64 bits.
84      */
85     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1,
86 
87     /**
88      * Constant representing a default protocol with Universal MIDI Packets (UMP).
89      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
90      * All UMP data should be a multiple of 4 bytes.
91      * Use MIDI 1.0 through UMP with packet sizes up to 64 bits and jitter reduction timestamps.
92      */
93     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2,
94 
95     /**
96      * Constant representing a default protocol with Universal MIDI Packets (UMP).
97      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
98      * All UMP data should be a multiple of 4 bytes.
99      * Use MIDI 1.0 through UMP with packet sizes up to 128 bits.
100      */
101     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3,
102 
103     /**
104      * Constant representing a default protocol with Universal MIDI Packets (UMP).
105      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
106      * All UMP data should be a multiple of 4 bytes.
107      * Use MIDI 1.0 through UMP with packet sizes up to 128 bits and jitter reduction timestamps.
108      */
109     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4,
110 
111     /**
112      * Constant representing a default protocol with Universal MIDI Packets (UMP).
113      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
114      * All UMP data should be a multiple of 4 bytes.
115      * Use MIDI 2.0 through UMP.
116      */
117     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0 = 17,
118 
119      /**
120      * Constant representing a default protocol with Universal MIDI Packets (UMP).
121      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
122      * All UMP data should be a multiple of 4 bytes.
123      * Use MIDI 2.0 through UMP and jitter reduction timestamps.
124      */
125     AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18,
126 
127     /**
128      * Constant representing a device with an unknown default protocol.
129      * If Universal MIDI Packets (UMP) are needed, use MIDI-CI through MIDI 1.0.
130      * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
131      * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
132      */
133     AMIDI_DEVICE_PROTOCOL_UNKNOWN = -1
134 } AMidiDevice_Protocol;
135 
136 /*
137  * Device API
138  */
139 /**
140  * Connects a native Midi Device object to the associated Java MidiDevice object. Use this
141  * AMidiDevice to access the rest of the native MIDI API. Use AMidiDevice_release() to
142  * disconnect from the Java object when not being used any more.
143  *
144  * @param env   Points to the Java Environment.
145  * @param midiDeviceObj   The Java MidiDevice Object.
146  * @param outDevicePtrPtr  Points to the pointer to receive the AMidiDevice
147  *
148  * @return AMEDIA_OK on success, or a negative error value:
149  *  @see AMEDIA_ERROR_INVALID_OBJECT - the midiDeviceObj
150  *    is null or already connected to a native AMidiDevice
151   *  @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred.
152  */
153 media_status_t AMIDI_API AMidiDevice_fromJava(
154         JNIEnv *env, jobject midiDeviceObj, AMidiDevice **outDevicePtrPtr) __INTRODUCED_IN(29);
155 
156 /**
157  * Disconnects the native Midi Device Object from the associated Java MidiDevice object.
158  *
159  * @param midiDevice Points to the native AMIDI_MidiDevice.
160  *
161  * @return AMEDIA_OK on success,
162  * or a negative error value:
163  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
164  *  @see AMEDIA_ERROR_INVALID_OBJECT - the device is not consistent with the associated Java MidiDevice.
165  *  @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed.
166  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
167  */
168 media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
169 
170 /**
171  * Gets the MIDI device type.
172  *
173  * @param device Specifies the MIDI device.
174  *
175  * @return The identifier of the MIDI device type:
176  *  AMIDI_DEVICE_TYPE_USB
177  *  AMIDI_DEVICE_TYPE_VIRTUAL
178  *  AMIDI_DEVICE_TYPE_BLUETOOTH
179  * or a negative error value:
180  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
181  *  @see AMEDIA_ERROR_UNKNOWN - Unknown error.
182  */
183 int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
184 
185 /**
186  * Gets the number of input (sending) ports available on the specified MIDI device.
187  *
188  * @param device Specifies the MIDI device.
189  *
190  * @return If successful, returns the number of MIDI input (sending) ports available on the
191  * device. If an error occurs, returns a negative value indicating the error:
192  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
193  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
194  */
195 ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
196 
197 /**
198  * Gets the number of output (receiving) ports available on the specified MIDI device.
199  *
200  * @param device Specifies the MIDI device.
201  *
202  * @return If successful, returns the number of MIDI output (receiving) ports available on the
203  * device. If an error occurs, returns a negative value indicating the error:
204  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
205  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
206  */
207 ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
208 
209 /**
210  * Gets the MIDI device default protocol.
211  *
212  * @param device Specifies the MIDI device.
213  *
214  * @return The identifier of the MIDI device default protocol:
215  * AMIDI_DEVICE_PROTOCOL_UMP_USE_MIDI_CI
216  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS
217  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS
218  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS
219  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS
220  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0
221  * AMIDI_DEVICE_PROTOCOL_UMP_MIDI_2_0_AND_JRTS
222  * AMIDI_DEVICE_PROTOCOL_UNKNOWN
223  *
224  * Most devices should return PROTOCOL_UNKNOWN (-1). This is intentional as devices
225  * with default UMP support are not backwards compatible. When the device is null,
226  * return AMIDI_DEVICE_PROTOCOL_UNKNOWN.
227  *
228  * Available since API 33.
229  */
230 AMidiDevice_Protocol AMIDI_API AMidiDevice_getDefaultProtocol(const AMidiDevice *device)
231         __INTRODUCED_IN(33);
232 
233 /*
234  * API for receiving data from the Output port of a device.
235  */
236 /**
237  * Opens the output port so that the client can receive data from it. The port remains open and
238  * valid until AMidiOutputPort_close() is called for the returned AMidiOutputPort.
239  *
240  * @param device    Specifies the MIDI device.
241  * @param portNumber Specifies the zero-based port index on the device to open. This value ranges
242  *                  between 0 and one less than the number of output ports reported by the
243  *                  AMidiDevice_getNumOutputPorts function.
244  * @param outOutputPortPtr Receives the native API port identifier of the opened port.
245  *
246  * @return AMEDIA_OK, or a negative error code:
247  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
248  */
249 media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
250                              AMidiOutputPort **outOutputPortPtr) __INTRODUCED_IN(29);
251 
252 /**
253  * Closes the output port.
254  *
255  * @param outputPort    The native API port identifier of the port.
256  */
257 void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
258 
259 /**
260  * Receives the next pending MIDI message. To retrieve all pending messages, the client should
261  * repeatedly call this method until it returns 0.
262  *
263  * Note that this is a non-blocking call. If there are no Midi messages are available, the function
264  * returns 0 immediately (for 0 messages received).
265  *
266  * @param outputPort   Identifies the port to receive messages from.
267  * @param opcodePtr  Receives the message Op Code.
268  * @param buffer    Points to the buffer to receive the message data bytes.
269  * @param maxBytes  Specifies the size of the buffer pointed to by the buffer parameter.
270  * @param numBytesReceivedPtr  On exit, receives the actual number of bytes stored in buffer.
271  * @param outTimestampPtr  If non-NULL, receives the timestamp associated with the message.
272  *  (the current value of the running Java Virtual Machine's high-resolution time source,
273  *  in nanoseconds)
274  * @return the number of messages received (either 0 or 1), or a negative error code:
275  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
276  */
277 ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
278          uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *outTimestampPtr) __INTRODUCED_IN(29);
279 
280 /*
281  * API for sending data to the Input port of a device.
282  */
283 /**
284  * Opens the input port so that the client can send data to it. The port remains open and
285  * valid until AMidiInputPort_close() is called for the returned AMidiInputPort.
286  *
287  * @param device    Specifies the MIDI device.
288  * @param portNumber Specifies the zero-based port index on the device to open. This value ranges
289  *                  between 0 and one less than the number of input ports reported by the
290  *                  AMidiDevice_getNumInputPorts() function..
291  * @param outInputPortPtr Receives the native API port identifier of the opened port.
292  *
293  * @return AMEDIA_OK, or a negative error code:
294  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
295  */
296 media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
297                             AMidiInputPort **outInputPortPtr) __INTRODUCED_IN(29);
298 
299 /**
300  * Sends data to the specified input port.
301  *
302  * @param inputPort    The identifier of the port to send data to.
303  * @param buffer       Points to the array of bytes containing the data to send.
304  * @param numBytes     Specifies the number of bytes to write.
305  *
306  * @return The number of bytes sent, which could be less than specified or a negative error code:
307  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
308  */
309 ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
310                    size_t numBytes) __INTRODUCED_IN(29);
311 
312 /**
313  * Sends data to the specified input port with a timestamp.
314  *
315  * @param inputPort    The identifier of the port to send data to.
316  * @param buffer       Points to the array of bytes containing the data to send.
317  * @param numBytes     Specifies the number of bytes to write.
318  * @param timestamp    The CLOCK_MONOTONIC time in nanoseconds to associate with the sent data.
319  *
320  * @return The number of bytes sent, which could be less than specified or a negative error code:
321  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
322  */
323 ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
324         const uint8_t *buffer, size_t numBytes, int64_t timestamp) __INTRODUCED_IN(29);
325 
326 /**
327  * Sends a message with a 'MIDI flush command code' to the specified port. This should cause
328  * a receiver to discard any pending MIDI data it may have accumulated and not processed.
329  *
330  * @param inputPort The identifier of the port to send the flush command to.
331  *
332  * @returns @see AMEDIA_OK if successful, otherwise a negative error code:
333  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL
334  * @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't
335  * be sent.
336  */
337 media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
338 
339 /**
340  * Closes the input port.
341  *
342  * @param inputPort Identifies the input (sending) port to close.
343  */
344 void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
345 
346 #ifdef __cplusplus
347 }
348 #endif
349 
350 #endif /* ANDROID_MEDIA_AMIDI_H_ */
351 /**
352 @}
353 */
354