Ejemplo n.º 1
0
/**
 * @brief Start or continue a synchronization session.
 * Continue a synchronization session identified by a given command.
 * The command must contain a pointer to a valid peer.
 * @param driver The driver.
 * @param fd The file descriptor to be used for communication.
 * @param command The previous sync command.
 * @retval 0 On success.
 * @retval >0 If the synchronization failed.
 */
static int _applemidi_sync( struct MIDIDriverAppleMIDI * driver, int fd, struct AppleMIDICommand * command ) {
  unsigned long ssrc;
  MIDITimestamp timestamp, diff;
  RTPSessionGetSSRC( driver->rtp_session, &ssrc );
  MIDIClockGetNow( driver->base.clock, &timestamp );

  if( command->type != APPLEMIDI_COMMAND_SYNCHRONIZATION || 
      command->data.sync.ssrc == ssrc ||
      command->data.sync.count > 2 ) {
    command->type = APPLEMIDI_COMMAND_SYNCHRONIZATION;
    command->data.sync.ssrc       = ssrc;
    command->data.sync.count      = 0;
    command->data.sync.timestamp1 = timestamp;
    
    driver->sync = 1;
    return _applemidi_send_command( driver, fd, command );
  } else {
    RTPSessionFindPeerBySSRC( driver->rtp_session, &(driver->peer), command->data.sync.ssrc );

    /* received packet from other peer */
    if( command->data.sync.count == 2 ) {
      /* compute media delay */
      diff = ( command->data.sync.timestamp3 - command->data.sync.timestamp1 ) / 2;
      /* approximate time difference between peer and self */
      diff = command->data.sync.timestamp3 + diff - timestamp;

      /* RTPPeerSetTimestampDiff( command->peer, diff ) */
      /* finished sync */
      command->data.sync.ssrc  = ssrc;
      command->data.sync.count = 3;

      driver->sync = 0;
      return 0;
    }
    if( command->data.sync.count == 1 ) {
      /* compute media delay */
      diff = ( command->data.sync.timestamp3 - command->data.sync.timestamp1 ) / 2;
      /* approximate time difference between peer and self */
      diff = command->data.sync.timestamp2 + diff - timestamp;

      /* RTPPeerSetTimestampDiff( command->peer, diff ) */

      command->data.sync.ssrc       = ssrc;
      command->data.sync.count      = 2;
      command->data.sync.timestamp3 = timestamp;
      
      driver->sync = 0;
      return _applemidi_send_command( driver, fd, command );
    }
    if( command->data.sync.count == 0 ) {
      command->data.sync.ssrc       = ssrc;
      command->data.sync.count      = 1;
      command->data.sync.timestamp2 = timestamp;
      
      driver->sync = 2;
      return _applemidi_send_command( driver, fd, command );
    }
  }
  return 1;
}
Ejemplo n.º 2
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,
			      struct sock *sk, struct AppleMIDICommand *command)
{
	struct RTPPeer *peer = NULL;

	switch (command->type) {
	case APPLEMIDI_COMMAND_INVITATION:
		if (sk == driver->control_socket->sk) {
			// 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 (sk == driver->rtp_socket->sk) {
				peer = RTPPeerCreate(
				    command->data.session.ssrc, command->size,
				    (struct sockaddr_in *)&(command->addr));
				RTPSessionAddPeer(driver->rtp_session, peer);
				RTPPeerRelease(peer);
			}
		} else {
			command->type = APPLEMIDI_COMMAND_INVITATION_REJECTED;
		}
		RTPSessionGetSSRC(driver->rtp_session,
				  &(command->data.session.ssrc));
		pr_debug("processed invitation should now answer\n");
		return _applemidi_send_command(driver, sk, command);
	case APPLEMIDI_COMMAND_INVITATION_ACCEPTED:
		// TODO for receive
		break;
	case APPLEMIDI_COMMAND_INVITATION_REJECTED:
		// TODO for receive
		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, sk, 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;
}
Ejemplo n.º 3
0
static int _applemidi_start_sync( struct MIDIDriverAppleMIDI * driver, int fd, socklen_t size, struct sockaddr * addr ) {
  if( addr != (struct sockaddr *) &(driver->command.addr) ) memcpy( &(driver->command.addr), addr, size );
  driver->command.size = size;
  driver->command.type = APPLEMIDI_COMMAND_SYNCHRONIZATION;
  driver->command.data.sync.count = 3;
  RTPSessionGetSSRC( driver->rtp_session, &(driver->command.data.sync.ssrc) );

  return _applemidi_sync( driver, fd, &(driver->command) );
}
Ejemplo n.º 4
0
static int _applemidi_endsession( struct MIDIDriverAppleMIDI * driver, int fd, socklen_t size, struct sockaddr * addr ) {
  if( addr != (struct sockaddr *) &(driver->command.addr) ) memcpy( &(driver->command.addr), addr, size );
  driver->command.size = size;
  driver->command.type = APPLEMIDI_COMMAND_ENDSESSION;
  driver->command.data.session.version = 2;
  driver->command.data.session.token   = driver->token;
  RTPSessionGetSSRC( driver->rtp_session, &(driver->command.data.session.ssrc) );
  strncpy( &(driver->command.data.session.name[0]), driver->name,
           sizeof(driver->command.data.session.name) );
  
  return _applemidi_send_command( driver, fd, &(driver->command) );
}
Ejemplo n.º 5
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;
}