/** * @brief Simulate an incoming message that was sent by another port. * @public @memberof MIDIPort * @param port The target port. * @param source The source port. * @param type The message type that was received. * @param object The message data that was received. * @retval 0 on success. */ int MIDIPortReceiveFrom( struct MIDIPort * port, struct MIDIPort * source, struct MIDITypeSpec * type, void * object ) { int result; MIDIPrecond( port != NULL, EFAULT ); MIDIPrecond( port->mode & MIDI_PORT_IN, EPERM ); if( port->mode & MIDI_PORT_INVALID ) { /* invalidated ports don't receive messages. */ return 0; } else { MIDIAssert( port->target != NULL ); MIDIAssert( port->receive != NULL ); _port_intercept( port, MIDI_PORT_IN, type, object ); if( source != NULL ) { result = (*port->receive)( port->target, source->target, type, object ); } else { result = (*port->receive)( port->target, NULL, type, object ); } if( port->mode & MIDI_PORT_THRU ) { return result + _port_passthrough( port, source, type, object ); } else { return result; } } }
/** * @brief Decode events. * Decode event objects from a buffer. * @public @memberof MIDIEvent * @param event The event. * @param size The size of the memory pointed to by @c buffer. * @param buffer The buffer to decode the event from. * @param read The number of bytes that were actually read. * @retval 0 on success. * @retval 1 if the event could not be encoded. */ int MIDIEventDecode( struct MIDIEvent * event, size_t size, void * buffer, size_t * read ) { MIDIPrecond( event != NULL, EFAULT ); MIDIPrecond( buffer != NULL, EINVAL ); size_t required = 5; MIDIPrecond( size >= required, EINVAL ); /** @todo implement me */ return 1; }
/** * @brief Encode events. * Encode an event to a buffer. * @public @memberof MIDIEvent * @param event The event. * @param size The size of the memory pointed to by @c buffer. * @param buffer The buffer to encode the event into. * @param written The number of bytes that have been written. * @retval 0 on success. * @retval 1 if the event could not be encoded. */ int MIDIEventEncode( struct MIDIEvent * event, size_t size, void * buffer, size_t * written ) { MIDIPrecond( event != NULL, EFAULT ); MIDIPrecond( buffer != NULL, EINVAL ); size_t required = 8 + event->length; MIDIPrecond( size >= required, ENOMEM ); /** @todo implement me */ return 1; }
/** * @brief Send a message to another port. * Send the given message to any other port. The target port does not have to be * connected to the source port. * @public @memberof MIDIPort * @param port The source port. * @param target The target port. * @param type The message type to send. * @param object The message data to send. * @retval 0 on success. */ int MIDIPortSendTo( struct MIDIPort * port, struct MIDIPort * target, struct MIDITypeSpec * type, void * object ) { MIDIPrecond( port != NULL, EFAULT ); MIDIPrecond( port->mode & MIDI_PORT_OUT, EPERM ); if( port->mode & MIDI_PORT_INVALID ) { return 0; } else { _port_intercept( port, MIDI_PORT_OUT, type, object ); return MIDIPortReceiveFrom( target, port, type, object ); } }
/** * @brief Send the given message to all connected ports. * Use the apply mechanism of the list to send the given message * to all connected ports. * @public @memberof MIDIPort * @param port The source port. * @param type The message type to send. * @param object The message data to send. * @retval 0 on success. */ int MIDIPortSend( struct MIDIPort * port, struct MIDITypeSpec * type, void * object ) { struct MIDIPortApplyParams params; MIDIPrecond( port != NULL, EFAULT ); MIDIPrecond( port->mode & MIDI_PORT_OUT, EPERM ); if( port->mode & MIDI_PORT_INVALID ) { return 0; } else { _port_intercept( port, MIDI_PORT_OUT, type, object ); params.port = port; params.type = type; params.object = object; return MIDIListApply( port->ports, ¶ms, &_port_apply_send ); } }
/** * @brief Invalidate the port. * This has to be called by the instance that created the port, * when it is being destroyed or no longer available. A port that * has been invalidated will never again dereference the @c target * pointer that was passed during creation or call the given @c * receive function. * @public @memberof MIDIPort * @param port The port to invalidate. * @retval 0 on success. */ int MIDIPortInvalidate( struct MIDIPort * port ) { MIDIPrecond( port != NULL, EFAULT ); _port_intercept( port, MIDI_PORT_INVALID, NULL, NULL ); port->mode = MIDI_PORT_INVALID; port->target = NULL; port->receive = NULL; return MIDIPortDisconnectAll( port ); }
/** * @brief Send a generic MIDIMessage. * Pass an outgoing message (through the port) to the implementation. * The implementation's @c send callback is responsible for sending the * message. * @public @memberof MIDIDriver * @param driver The driver. * @param message The message. * @retval 0 on success. * @retval >0 if the message could not be sent. */ int MIDIDriverSend( struct MIDIDriver * driver, struct MIDIMessage * message ) { MIDIPrecond( driver != NULL, EFAULT ); MIDIPrecond( message != NULL, EINVAL ); return MIDIPortReceive( driver->port, MIDIMessageType, message ); }
/** * @brief Make the MIDIDriver implement itself as loopback. * The driver's callback will be modified so that it passes * outgoing messages to it's own receive method. * @public @memberof MIDIDriver * @param driver The driver * @retval 0 on success. * @retval >0 if the operation could not be completed. */ int MIDIDriverMakeLoopback( struct MIDIDriver * driver ) { MIDIPrecond( driver != NULL, EFAULT ); /* Ugly but (for now) safe cast ahead... */ driver->send = (int (*)( void *, struct MIDIMessage * )) &MIDIDriverReceive; return 0; }
/** * @brief Get the driver port. * Provide a port that can be used to send and receive MIDI messages * using the driver. * The port that is stored in @c port will have a retain count * of one and should only be released by the user if it was retained * before. * @public @memberof MIDIDriver * @param driver The driver. * @param port The port. * @retval 0 on success. */ int MIDIDriverGetPort( struct MIDIDriver * driver, struct MIDIPort ** port ) { MIDIPrecond( driver != NULL, EFAULT ); MIDIPrecond( port != NULL, EINVAL ); *port = driver->port; return 0; }
/** * @brief Disconnect all ports from another port. * Disconnect all connected ports from another port. * @public @memberof MIDIPort * @param port The source port. */ int MIDIPortDisconnectAll( struct MIDIPort * port ) { MIDIPrecond( port != NULL, EFAULT ); return MIDIListApply( port->ports, port, &_port_apply_disconnect ); }
/** * @brief Get properties. * Get properties of messages with a given format. * @public @memberof MIDIMessageFormat * @param format The message format. * @param data The message data object to read from. * @param property The property to get. * @param size The size of the memory object pointed to by @c value. * @param value A pointer to the memory object who's contents shall be * copied from the message property. * @retval 0 on success. * @retval 1 if the value was not set. */ int MIDIMessageFormatGet( struct MIDIMessageFormat * format, struct MIDIMessageData * data, MIDIProperty property, size_t size, void * value ) { MIDIPrecond( format != NULL, EFAULT ); MIDIPrecond( size > 0 && value != NULL, EINVAL ); MIDIAssert( format->get != NULL ); return (format->get)( data, property, size, value ); }
/** * @brief Test that the format can be used for a given buffer. * Test that the format specified by @c format can be used to * decode the bytes in the buffer. * @public @memberof MIDIMessageFormat * @param format The message format. * @param buffer A pointer to the buffer to test. * @retval 0 on success. * @retval 1 If the format can not be used to access the buffer. */ int MIDIMessageFormatTest( struct MIDIMessageFormat * format, void * buffer ) { MIDIPrecond( format != NULL, EFAULT ); MIDIPrecond( buffer != NULL, EINVAL ); MIDIAssert( format->test != NULL ); return (format->test)( buffer ); }
/** * @brief Get the observer of a port. * @public @memberof MIDIPort * @param port The port. * @param target The target (observer) to be called for each event. * @param intercept The interceptor function. */ int MIDIPortGetObserver( struct MIDIPort * port, void ** target, MIDIPortInterceptFn ** intercept ) { MIDIPrecond( port != NULL, EFAULT ); *target = port->observer; *intercept = port->intercept; return 0; }
/** * @brief Set the observer of a port. * @public @memberof MIDIPort * @param port The port. * @param target The target (observer) to be called for each event. * @param intercept The interceptor function. */ int MIDIPortSetObserver( struct MIDIPort * port, void * target, MIDIPortInterceptFn * intercept ) { MIDIPrecond( port != NULL, EFAULT ); port->observer = target; port->intercept = intercept; return 0; }
/** * @brief Trigger an event that occured in the driver implementation. * @public @memberof MIDIDriver * @param driver The driver. * @param event The event. * @retval 0 on success. */ int MIDIDriverTriggerEvent( struct MIDIDriver * driver, struct MIDIEvent * event ) { MIDIPrecond( driver != NULL, EFAULT ); MIDIPrecond( event != NULL, EINVAL ); return MIDIPortSend( driver->port, MIDIEventType, event ); }
int MIDIRunloopRemoveDriver( struct MIDIRunloop * runloop, struct MIDIDriver * driver ) { MIDIPrecond( runloop != NULL, EFAULT ); MIDIPrecond( driver != NULL, EINVAL ); return MIDIRunloopRemoveSource( runloop, driver->rls ); }
/** * @brief Get the event identifier. * @public @memberof MIDIEvent * @param event The event. * @param id The ID. * @retval 0 on success. */ int MIDIEventGetId( struct MIDIEvent * event, size_t * id ) { MIDIPrecond( event != NULL, EFAULT ); MIDIPrecond( id != NULL, EINVAL ); *id = event->id; return 0; }
/** * @brief Get the size of a given message. * Determine the size of a given message data object using a * given message format. This is constant for all messages except * system exclusive messages. * @public @memberof MIDIMessageFormat * @param format The message format. * @param data The message data. * @param size A pointer to the variable in which to store the result. * @retval 0 on success. * @retval 1 If the size could not be determined. */ int MIDIMessageFormatGetSize( struct MIDIMessageFormat * format, struct MIDIMessageData * data, size_t * size ) { MIDIPrecond( format != NULL, EFAULT ); MIDIAssert( format->size != NULL ); return (format->size)( data, size ); }
/** * @brief Get the event info-object. * @public @memberof MIDIEvent * @param event The event. * @param info The info. * @retval 0 on success. */ int MIDIEventGetInfo( struct MIDIEvent * event, void ** info ) { MIDIPrecond( event != NULL, EFAULT ); MIDIPrecond( info != NULL, EINVAL ); *info = event->info; return 0; }
/** * @brief Decode messages with running status byte. * Decode message data objects from a buffer. * @public @memberof MIDIMessageFormat * @param format The message format. * @param data The message data object to read from. * @param status The running status inherited from previous messages. * @param size The size of the memory pointed to by @c buffer. * @param buffer The buffer to decode the message from. * @param read The number of bytes that were read from the @c buffer. * @retval 0 on success. * @retval 1 if the message could not be encoded. */ int MIDIMessageFormatDecodeRunningStatus( struct MIDIMessageFormat * format, struct MIDIMessageData * data, MIDIRunningStatus * status, size_t size, void * buffer, size_t * read ) { MIDIPrecond( format != NULL, EFAULT ); MIDIPrecond( size > 0 && buffer != NULL, EINVAL ); MIDIAssert( format->decode != NULL ); return (format->decode)( data, status, size, buffer, read ); }
/** * @brief Disconnect a port from another port. * Disconnect a connected port from another port. * @public @memberof MIDIPort * @param port The source port. * @param target The target port. */ int MIDIPortDisconnect( struct MIDIPort * port, struct MIDIPort * target ) { MIDIPrecond( port != NULL, EFAULT ); MIDIPrecond( target != NULL , EINVAL ); return MIDIListRemove( port->ports, target ); }