001package net.kreatious.pianoleopard.midi.event; 002 003/** 004 * Represents an immutable pair of on/off events 005 * 006 * @author Jay-R Studer 007 * @param <T> 008 * the subtype of Event held by this pair 009 */ 010public class EventPair<T extends Event> { 011 private final T on; 012 private final T off; 013 014 /** 015 * Constructs a new {@link EventPair} with the specified pair of events 016 * 017 * @param on 018 * the on event 019 * @param off 020 * the off event 021 * @throws IllegalArgumentException 022 * if events do not represent a correct bounded pair 023 */ 024 public EventPair(T on, T off) { 025 if (!on.isOn()) { 026 throw new IllegalArgumentException("on (" + on + ") was off"); 027 } else if (off.isOn()) { 028 throw new IllegalArgumentException("off (" + off + ") was on"); 029 } else if (on.getChannel() != off.getChannel()) { 030 throw new IllegalArgumentException("on (" + on + ") is not on the same channel as off (" + off + ")"); 031 } else if (!on.getSlot().equals(off.getSlot())) { 032 throw new IllegalArgumentException("on (" + on + ") is not on the same slot as off (" + off + ")"); 033 } else if (on.getTime() > off.getTime()) { 034 this.on = on; 035 this.off = on.createOff(on.getTime()); 036 return; 037 } 038 039 this.on = on; 040 this.off = off; 041 } 042 043 /** 044 * @return the off event 045 */ 046 public T getOff() { 047 return off; 048 } 049 050 /** 051 * @return the on event 052 */ 053 public T getOn() { 054 return on; 055 } 056 057 /** 058 * @return the on time in microseconds 059 */ 060 public long getOnTime() { 061 return on.getTime(); 062 } 063 064 /** 065 * @return the off time in microseconds 066 */ 067 public long getOffTime() { 068 return off.getTime(); 069 } 070 071 /** 072 * @return the nonnegative duration of this event pair in microseconds 073 */ 074 public long getDuration() { 075 return off.getTime() - on.getTime(); 076 } 077 078 /** 079 * @return the slot of this event pair 080 */ 081 public Object getSlot() { 082 return on.getSlot(); 083 } 084 085 /** 086 * @return the channel of this event pair 087 */ 088 public int getChannel() { 089 return on.getChannel(); 090 } 091 092 /** 093 * Creates a new off event pair of the same type and slot with the specified 094 * off timestamp. 095 * 096 * @param offTime 097 * the new off time measured in microseconds, value must be after 098 * the on time. 099 * @return a new event pair with the specified timestamp 100 */ 101 public EventPair<T> withOffTime(long offTime) { 102 if (offTime < on.getTime()) { 103 throw new IllegalArgumentException("The offtime must be on or after the on time"); 104 } 105 return new EventPair<>(on, on.createOff(offTime)); 106 } 107 108 @Override 109 public String toString() { 110 return on + ", " + off; 111 } 112}