static int _applemidi_idle_timeout( void * drv, struct timespec * ts ) { struct MIDIDriverAppleMIDI * driver = drv; struct sockaddr * addr; socklen_t size; _applemidi_update_runloop_source( driver ); RTPSessionNextPeer( driver->rtp_session, &(driver->peer) ); if( driver->peer != NULL ) { /* check if receiver feedback needs to be sent */ if( driver->sync == 0 ) { /* no sync packets active. start new sync */ RTPPeerGetAddress( driver->peer, &size, &addr ); return _applemidi_start_sync( driver, driver->rtp_socket, size, addr ); } } /* check for messages in dispatch (incoming) queue: * if message needs to be dispatched (timestamp >= now+latency) * call MIDIDriverAppleMIDIReceiveMessage * send receiver feedback * if the last synchronization happened a certain time ago, synchronize again */ return 0; }
void _applemidi_idle_timeout(unsigned long data) { struct sockaddr_in *addr; int size; struct MIDIDriverAppleMIDI *driver = (struct MIDIDriverAppleMIDI *)data; mod_timer(&driver->timer, jiffies + msecs_to_jiffies(1500)); pr_debug("====called timeout (%ld) dat: %lx ====\n", jiffies, data); if (spin_trylock(&(driver->lock))) { RTPSessionNextPeer(driver->rtp_session, &(driver->peer)); if (driver->peer != NULL) { /* check if receiver feedback needs to be sent */ if (driver->sync == 0) { /* no sync packets active. start new sync */ RTPPeerGetAddress(driver->peer, &size, &addr); pr_debug("start sync with client: %pI4\n", &addr->sin_addr.s_addr); _applemidi_start_sync( driver, driver->rtp_socket->sk, size, addr); // no return } } spin_unlock(&(driver->lock)); } else { pr_warn("could not so sync timeout because of midi event\n"); } // // /* check for messages in dispatch (incoming) queue: // * if message needs to be dispatched (timestamp >= now+latency) // * call MIDIDriverAppleMIDIReceiveMessage // * send receiver feedback // * if the last synchronization happened a certain time ago, // synchronize again */ // // return 0; }
/** * @brief Respond to a given AppleMIDI command. * Use the command as response and - if neccessary - send it back to the peer. * @private @memberof MIDIDriverAppleMIDI * @param driver The driver. * @param fd The file descriptor to be used for communication. * @param command The command. * @retval 0 On success. * @retval >0 If the packet could not be sent. */ static int _applemidi_respond( struct MIDIDriverAppleMIDI * driver, int fd, struct AppleMIDICommand * command ) { struct RTPPeer * peer = NULL; struct MIDIEvent * event = NULL; switch( command->type ) { case APPLEMIDI_COMMAND_INVITATION: if( fd == driver->control_socket ) { event = MIDIEventCreate( MIDI_APPLEMIDI_PEER_DID_SEND_INVITATION, NULL, "%s", &(command->data.session.name[0]) ); MIDIDriverTriggerEvent( &(driver->base), event ); MIDIEventRelease( event ); } if( driver->accept ) { command->type = APPLEMIDI_COMMAND_INVITATION_ACCEPTED; if( fd == driver->rtp_socket ) { peer = RTPPeerCreate( command->data.session.ssrc, command->size, (struct sockaddr *) &(command->addr) ); RTPSessionAddPeer( driver->rtp_session, peer ); RTPPeerRelease( peer ); } } else { command->type = APPLEMIDI_COMMAND_INVITATION_REJECTED; } RTPSessionGetSSRC( driver->rtp_session, &(command->data.session.ssrc) ); return _applemidi_send_command( driver, fd, command ); case APPLEMIDI_COMMAND_INVITATION_ACCEPTED: if( command->data.session.token == driver->token ) { if( fd == driver->control_socket ) { _applemidi_rtp_addr( command->size, (struct sockaddr *) &command->addr, (struct sockaddr *) &command->addr ); return _applemidi_invite( driver, driver->rtp_socket, command->size, (struct sockaddr *) &(command->addr) ); } else { peer = RTPPeerCreate( command->data.session.ssrc, command->size, (struct sockaddr *) &(command->addr) ); RTPSessionAddPeer( driver->rtp_session, peer ); event = MIDIEventCreate( MIDI_APPLEMIDI_PEER_DID_ACCEPT_INVITATION, NULL, "%s", &(command->data.session.name[0]) ); MIDIDriverTriggerEvent( &(driver->base), event ); MIDIEventRelease( event ); RTPPeerRelease( peer ); return _applemidi_start_sync( driver, driver->rtp_socket, command->size, (struct sockaddr *) &(command->addr) ); } } break; case APPLEMIDI_COMMAND_INVITATION_REJECTED: event = MIDIEventCreate( MIDI_APPLEMIDI_PEER_DID_REJECT_INVITATION, NULL, "%s", &(command->data.session.name[0]) ); MIDIDriverTriggerEvent( &(driver->base), event ); MIDIEventRelease( event ); break; case APPLEMIDI_COMMAND_ENDSESSION: RTPSessionFindPeerBySSRC( driver->rtp_session, &peer, command->data.session.ssrc ); event = MIDIEventCreate( MIDI_APPLEMIDI_PEER_DID_END_SESSION, NULL, "%s", &(command->data.session.name[0]) ); MIDIDriverTriggerEvent( &(driver->base), event ); MIDIEventRelease( event ); if( peer != NULL ) { RTPSessionRemovePeer( driver->rtp_session, peer ); } break; case APPLEMIDI_COMMAND_SYNCHRONIZATION: return _applemidi_sync( driver, fd, command ); case APPLEMIDI_COMMAND_RECEIVER_FEEDBACK: RTPSessionFindPeerBySSRC( driver->rtp_session, &peer, command->data.feedback.ssrc ); RTPMIDISessionJournalTrunkate( driver->rtpmidi_session, peer, command->data.feedback.seqnum ); break; default: return 1; } return 0; }