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 #if __ANDROID_API__ >= 29
65 
66 /*
67  * Device API
68  */
69 /**
70  * Connects a native Midi Device object to the associated Java MidiDevice object. Use this
71  * AMidiDevice to access the rest of the native MIDI API. Use AMidiDevice_release() to
72  * disconnect from the Java object when not being used any more.
73  *
74  * @param env   Points to the Java Environment.
75  * @param midiDeviceObj   The Java MidiDevice Object.
76  * @param outDevicePtrPtr  Points to the pointer to receive the AMidiDevice
77  *
78  * @return AMEDIA_OK on success, or a negative error value:
79  *  @see AMEDIA_ERROR_INVALID_OBJECT - the midiDeviceObj
80  *    is null or already connected to a native AMidiDevice
81   *  @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred.
82  */
83 media_status_t AMIDI_API AMidiDevice_fromJava(
84         JNIEnv *env, jobject midiDeviceObj, AMidiDevice **outDevicePtrPtr) __INTRODUCED_IN(29);
85 
86 /**
87  * Disconnects the native Midi Device Object from the associated Java MidiDevice object.
88  *
89  * @param midiDevice Points to the native AMIDI_MidiDevice.
90  *
91  * @return AMEDIA_OK on success,
92  * or a negative error value:
93  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
94  *  @see AMEDIA_ERROR_INVALID_OBJECT - the device is not consistent with the associated Java MidiDevice.
95  *  @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed.
96  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
97  */
98 media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
99 
100 /**
101  * Gets the MIDI device type.
102  *
103  * @param device Specifies the MIDI device.
104  *
105  * @return The identifier of the MIDI device type:
106  *  AMIDI_DEVICE_TYPE_USB
107  *  AMIDI_DEVICE_TYPE_VIRTUAL
108  *  AMIDI_DEVICE_TYPE_BLUETOOTH
109  * or a negative error value:
110  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
111  *  @see AMEDIA_ERROR_UNKNOWN - Unknown error.
112  */
113 int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
114 
115 /**
116  * Gets the number of input (sending) ports available on the specified MIDI device.
117  *
118  * @param device Specifies the MIDI device.
119  *
120  * @return If successful, returns the number of MIDI input (sending) ports available on the
121  * device. If an error occurs, returns a negative value indicating the error:
122  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
123  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
124  */
125 ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
126 
127 /**
128  * Gets the number of output (receiving) ports available on the specified MIDI device.
129  *
130  * @param device Specifies the MIDI device.
131  *
132  * @return If successful, returns the number of MIDI output (receiving) ports available on the
133  * device. If an error occurs, returns a negative value indicating the error:
134  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
135  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
136  */
137 ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
138 
139 /*
140  * API for receiving data from the Output port of a device.
141  */
142 /**
143  * Opens the output port so that the client can receive data from it. The port remains open and
144  * valid until AMidiOutputPort_close() is called for the returned AMidiOutputPort.
145  *
146  * @param device    Specifies the MIDI device.
147  * @param portNumber Specifies the zero-based port index on the device to open. This value ranges
148  *                  between 0 and one less than the number of output ports reported by the
149  *                  AMidiDevice_getNumOutputPorts function.
150  * @param outOutputPortPtr Receives the native API port identifier of the opened port.
151  *
152  * @return AMEDIA_OK, or a negative error code:
153  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
154  */
155 media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
156                              AMidiOutputPort **outOutputPortPtr) __INTRODUCED_IN(29);
157 
158 /**
159  * Closes the output port.
160  *
161  * @param outputPort    The native API port identifier of the port.
162  */
163 void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
164 
165 /**
166  * Receives the next pending MIDI message. To retrieve all pending messages, the client should
167  * repeatedly call this method until it returns 0.
168  *
169  * Note that this is a non-blocking call. If there are no Midi messages are available, the function
170  * returns 0 immediately (for 0 messages received).
171  *
172  * @param outputPort   Identifies the port to receive messages from.
173  * @param opcodePtr  Receives the message Op Code.
174  * @param buffer    Points to the buffer to receive the message data bytes.
175  * @param maxBytes  Specifies the size of the buffer pointed to by the buffer parameter.
176  * @param numBytesReceivedPtr  On exit, receives the actual number of bytes stored in buffer.
177  * @param outTimestampPtr  If non-NULL, receives the timestamp associated with the message.
178  *  (the current value of the running Java Virtual Machine's high-resolution time source,
179  *  in nanoseconds)
180  * @return the number of messages received (either 0 or 1), or a negative error code:
181  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
182  */
183 ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
184          uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *outTimestampPtr) __INTRODUCED_IN(29);
185 
186 /*
187  * API for sending data to the Input port of a device.
188  */
189 /**
190  * Opens the input port so that the client can send data to it. The port remains open and
191  * valid until AMidiInputPort_close() is called for the returned AMidiInputPort.
192  *
193  * @param device    Specifies the MIDI device.
194  * @param portNumber Specifies the zero-based port index on the device to open. This value ranges
195  *                  between 0 and one less than the number of input ports reported by the
196  *                  AMidiDevice_getNumInputPorts() function..
197  * @param outInputPortPtr Receives the native API port identifier of the opened port.
198  *
199  * @return AMEDIA_OK, or a negative error code:
200  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
201  */
202 media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
203                             AMidiInputPort **outInputPortPtr) __INTRODUCED_IN(29);
204 
205 /**
206  * Sends data to the specified input port.
207  *
208  * @param inputPort    The identifier of the port to send data to.
209  * @param buffer       Points to the array of bytes containing the data to send.
210  * @param numBytes     Specifies the number of bytes to write.
211  *
212  * @return The number of bytes sent, which could be less than specified or a negative error code:
213  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
214  */
215 ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
216                    size_t numBytes) __INTRODUCED_IN(29);
217 
218 /**
219  * Sends data to the specified input port with a timestamp.
220  *
221  * @param inputPort    The identifier of the port to send data to.
222  * @param buffer       Points to the array of bytes containing the data to send.
223  * @param numBytes     Specifies the number of bytes to write.
224  * @param timestamp    The CLOCK_MONOTONIC time in nanoseconds to associate with the sent data.
225  *
226  * @return The number of bytes sent, which could be less than specified or a negative error code:
227  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
228  */
229 ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
230         const uint8_t *buffer, size_t numBytes, int64_t timestamp) __INTRODUCED_IN(29);
231 
232 /**
233  * Sends a message with a 'MIDI flush command code' to the specified port. This should cause
234  * a receiver to discard any pending MIDI data it may have accumulated and not processed.
235  *
236  * @param inputPort The identifier of the port to send the flush command to.
237  *
238  * @returns @see AMEDIA_OK if successful, otherwise a negative error code:
239  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL
240  * @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't
241  * be sent.
242  */
243 media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
244 
245 /**
246  * Closes the input port.
247  *
248  * @param inputPort Identifies the input (sending) port to close.
249  */
250 void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
251 
252 #endif /* __ANDROID_API__ >= 29 */
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif /* ANDROID_MEDIA_AMIDI_H_ */
259 /**
260 @}
261 */
262