| 1 | package tmcsim.cadsimulator.videocontrol; |
|---|
| 2 | |
|---|
| 3 | import java.io.IOException; |
|---|
| 4 | import java.util.Observable; |
|---|
| 5 | import java.util.Vector; |
|---|
| 6 | |
|---|
| 7 | /** |
|---|
| 8 | * DVDController is an abstract class used for controlling a remote DVD player. |
|---|
| 9 | * All player specific control methods must be overloaded according to the |
|---|
| 10 | * requirements of that device. This base class handles starting and repeating |
|---|
| 11 | * range or incident titles according to current speed updates or incident toggles. |
|---|
| 12 | * |
|---|
| 13 | * The addRange() and addIncident() methods are used to register more titles with |
|---|
| 14 | * the DVDController class. The updatePlayer() and toggleIncident() methods are |
|---|
| 15 | * used to control which titles are being played. A title will continuously |
|---|
| 16 | * repeat until a new title is chosen through one of these methods. |
|---|
| 17 | * |
|---|
| 18 | * @author Matthew Cechini |
|---|
| 19 | * @version |
|---|
| 20 | */ |
|---|
| 21 | public abstract class DVDController extends Observable { |
|---|
| 22 | |
|---|
| 23 | /** Number of consecutive requests for change until the title will change. */ |
|---|
| 24 | private static final int CHANGE_TOLERANCE = 2; |
|---|
| 25 | |
|---|
| 26 | /** |
|---|
| 27 | * Boolean flag to designate whether a connection has been established with |
|---|
| 28 | * the DVD player. |
|---|
| 29 | */ |
|---|
| 30 | protected boolean isConnected = false; |
|---|
| 31 | |
|---|
| 32 | /** Vector of all DVDRanges in the current simulation. */ |
|---|
| 33 | protected Vector<DVDRange> ranges = null; |
|---|
| 34 | |
|---|
| 35 | /** Vector of all DVDIncidents in the current simulation. */ |
|---|
| 36 | protected Vector<DVDIncident> incidents = null; |
|---|
| 37 | |
|---|
| 38 | /** Current range being played. Null if none have played. */ |
|---|
| 39 | protected DVDRange currentRange = null; |
|---|
| 40 | |
|---|
| 41 | /** Current incident being played. */ |
|---|
| 42 | protected DVDIncident currentIncident = null; |
|---|
| 43 | |
|---|
| 44 | /** Boolean flag to designate whether an incident is currently playing. */ |
|---|
| 45 | protected boolean isPlayingIncident = false; |
|---|
| 46 | |
|---|
| 47 | /** |
|---|
| 48 | * DVDRange object to cache the last "new range" that the controller |
|---|
| 49 | * has chosen as a result of a speed update. This allows for a tolerance |
|---|
| 50 | * value to be used to control frequent title changes. |
|---|
| 51 | */ |
|---|
| 52 | protected DVDRange changeRange; |
|---|
| 53 | |
|---|
| 54 | /** |
|---|
| 55 | * Count value to count the number of consecutive updates that |
|---|
| 56 | * result in the same DVDRange. |
|---|
| 57 | */ |
|---|
| 58 | protected int changeRangeCounter; |
|---|
| 59 | |
|---|
| 60 | /** |
|---|
| 61 | * Constructor. Initialize lists and title repeat timer. |
|---|
| 62 | */ |
|---|
| 63 | public DVDController() { |
|---|
| 64 | ranges = new Vector<DVDRange>(); |
|---|
| 65 | incidents = new Vector<DVDIncident>(); |
|---|
| 66 | |
|---|
| 67 | changeRange = null; |
|---|
| 68 | changeRangeCounter = 0; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | /** |
|---|
| 72 | * Add a new DVDRange to the local list. |
|---|
| 73 | * |
|---|
| 74 | * @param newRange DVDRange to add. |
|---|
| 75 | */ |
|---|
| 76 | public void addRange(DVDRange newRange) { |
|---|
| 77 | ranges.add(newRange); |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | /** |
|---|
| 81 | * Add a new DVDIncident to the local list. |
|---|
| 82 | * |
|---|
| 83 | * @param newRange DVDIncident to add. |
|---|
| 84 | */ |
|---|
| 85 | public void addIncident(DVDIncident newIncident) { |
|---|
| 86 | incidents.add(newIncident); |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | /** |
|---|
| 90 | * Toggle the dvd player to start or stop playing an incident track. The |
|---|
| 91 | * boolean parameter is used to designate whether the incident is being |
|---|
| 92 | * toggled to start(true) or stop (false). If the toggle flag is true, |
|---|
| 93 | * then the DVDIncident with log number equal to the parameter log_num |
|---|
| 94 | * will be played. The currentIncident and isPlayeingIncident member data |
|---|
| 95 | * objects are updated. |
|---|
| 96 | * |
|---|
| 97 | * If the toggle flag is false, and the incident being toggled is playing, |
|---|
| 98 | * then it is stopped. |
|---|
| 99 | * |
|---|
| 100 | * @param log_num Incident log number to toggle. |
|---|
| 101 | * @param toggle Boolean flag. True = start incident, false = stop incident. |
|---|
| 102 | * @throws Exception if the method is unable to toggle the incident. |
|---|
| 103 | */ |
|---|
| 104 | public void toggleIncident(int log_num, boolean toggle) throws Exception { |
|---|
| 105 | if(toggle) { |
|---|
| 106 | for(DVDIncident incident : incidents) { |
|---|
| 107 | if(incident.incidentNumber == log_num) { |
|---|
| 108 | currentIncident = incident; |
|---|
| 109 | isPlayingIncident = true; |
|---|
| 110 | |
|---|
| 111 | playCurrentTitle(); |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | } |
|---|
| 115 | else if(currentIncident != null && currentIncident.incidentNumber == log_num) { |
|---|
| 116 | isPlayingIncident = false; |
|---|
| 117 | |
|---|
| 118 | playCurrentTitle(); |
|---|
| 119 | } |
|---|
| 120 | else { |
|---|
| 121 | throw new Exception("DVDController: Unable to toggle incident #" + log_num); |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | /** |
|---|
| 126 | * Update this DVD player with a new traffic speed after the tolerance of |
|---|
| 127 | * range changes has been met. If the parameter speed falls within a |
|---|
| 128 | * different DVDRange than is being played, remember the new range. If this |
|---|
| 129 | * new range was not detected during the last update, reset the change |
|---|
| 130 | * counter to 0. If this range was detected during the last update, |
|---|
| 131 | * increment the change counter. If the change counter is greater than |
|---|
| 132 | * the tolerance value specified, set the current range to the new range, |
|---|
| 133 | * reset the change counter, and set the updated flag to true. If the range |
|---|
| 134 | * has been updated, and an incident is not being shown, return true. Else |
|---|
| 135 | * return false. |
|---|
| 136 | * |
|---|
| 137 | * @param newSpeed New traffic speed for this DVD's camera location. |
|---|
| 138 | * @return True if a new DVDRange is to be played, false if not. |
|---|
| 139 | */ |
|---|
| 140 | public boolean updatePlayer(float newSpeed) { |
|---|
| 141 | |
|---|
| 142 | boolean updated = false; |
|---|
| 143 | DVDRange newRange = null; |
|---|
| 144 | |
|---|
| 145 | for(DVDRange range : ranges) { |
|---|
| 146 | if(range.isWithin(newSpeed)) { |
|---|
| 147 | if(currentRange == null || !currentRange.equals(range)) { |
|---|
| 148 | newRange = range; |
|---|
| 149 | break; |
|---|
| 150 | } |
|---|
| 151 | } |
|---|
| 152 | } |
|---|
| 153 | |
|---|
| 154 | if(newRange == null) { |
|---|
| 155 | //do nothing |
|---|
| 156 | } |
|---|
| 157 | else if(changeRange == null || !changeRange.equals(newRange)) { |
|---|
| 158 | changeRange = newRange; |
|---|
| 159 | changeRangeCounter = 0; |
|---|
| 160 | } |
|---|
| 161 | else { |
|---|
| 162 | changeRangeCounter++; |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | if(currentRange == null || |
|---|
| 166 | changeRangeCounter >= CHANGE_TOLERANCE) |
|---|
| 167 | { |
|---|
| 168 | changeRangeCounter = 0; |
|---|
| 169 | currentRange = changeRange; |
|---|
| 170 | updated = true; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | |
|---|
| 174 | //even if the currentRange is updated, an incident trumps this |
|---|
| 175 | return updated & !isPlayingIncident; |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | /** |
|---|
| 179 | * This method starts a new title. If the DVD Controller is playing an incident, |
|---|
| 180 | * then the incident title will be started. Else, if a DVD range has been found, |
|---|
| 181 | * then it's title will be started in repeat mode. |
|---|
| 182 | * |
|---|
| 183 | * @throws Exception if the method is not able to play the current title. |
|---|
| 184 | */ |
|---|
| 185 | public void playCurrentTitle() throws Exception { |
|---|
| 186 | |
|---|
| 187 | if(!isConnected) { |
|---|
| 188 | throw new Exception("Cannot play title, connection has not been established to DVD Controller"); |
|---|
| 189 | } |
|---|
| 190 | else if(isPlayingIncident) { |
|---|
| 191 | repeatTitle(currentIncident.dvdTitle); |
|---|
| 192 | |
|---|
| 193 | setChanged(); |
|---|
| 194 | notifyObservers(new DVDTitleUpdate( |
|---|
| 195 | getConnectionInfo(), currentRange, |
|---|
| 196 | currentIncident, isPlayingIncident, false)); |
|---|
| 197 | } |
|---|
| 198 | else if(currentRange != null) { |
|---|
| 199 | repeatTitle(currentRange.dvdTitle); |
|---|
| 200 | |
|---|
| 201 | setChanged(); |
|---|
| 202 | notifyObservers(new DVDTitleUpdate( |
|---|
| 203 | getConnectionInfo(), currentRange, |
|---|
| 204 | currentIncident, isPlayingIncident, false)); |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | public abstract void setConnectionInfo(String host, int port); |
|---|
| 210 | public abstract String getConnectionInfo(); |
|---|
| 211 | public abstract boolean isConnected(); |
|---|
| 212 | public abstract void connect() throws IOException; |
|---|
| 213 | public abstract void disconnect(); |
|---|
| 214 | |
|---|
| 215 | |
|---|
| 216 | public abstract void open() throws IOException; |
|---|
| 217 | public abstract void close() throws IOException; |
|---|
| 218 | |
|---|
| 219 | public abstract void start() throws IOException; |
|---|
| 220 | public abstract void play() throws IOException; |
|---|
| 221 | public abstract void playChapter(int chapter) throws IOException; |
|---|
| 222 | public abstract void playTitle(int title) throws IOException; |
|---|
| 223 | public abstract void repeatTitle(int title) throws IOException; |
|---|
| 224 | public abstract void pause() throws IOException; |
|---|
| 225 | public abstract void still() throws IOException; |
|---|
| 226 | |
|---|
| 227 | public abstract void stepForward() throws IOException; |
|---|
| 228 | public abstract void stepReverse() throws IOException; |
|---|
| 229 | public abstract void scanForward() throws IOException; |
|---|
| 230 | public abstract void scanReverse() throws IOException; |
|---|
| 231 | public abstract void scanStop() throws IOException; |
|---|
| 232 | |
|---|
| 233 | //multi-speed forward/reverse |
|---|
| 234 | |
|---|
| 235 | //speed |
|---|
| 236 | //search |
|---|
| 237 | //search&play |
|---|
| 238 | |
|---|
| 239 | //frame |
|---|
| 240 | |
|---|
| 241 | //time |
|---|
| 242 | //track |
|---|
| 243 | |
|---|
| 244 | } |
|---|