source: trunk/src_apollo/org/apollo/items/FramePlaybackLauncher.java@ 375

Last change on this file since 375 was 375, checked in by bjn8, 16 years ago

Lots of minor improvements made prior to evluation study, and small things done afterwards for report :)

File size: 7.7 KB
Line 
1package org.apollo.items;
2
3import java.awt.Color;
4import java.awt.GradientPaint;
5import java.awt.Graphics2D;
6import java.awt.Paint;
7import java.awt.Polygon;
8import java.awt.Stroke;
9
10import org.apollo.ApolloSystem;
11import org.apollo.audio.SampledAudioManager;
12import org.apollo.audio.structure.OverdubbedFrame;
13import org.apollo.audio.structure.TrackGraphLoopException;
14import org.apollo.audio.util.MultiTrackPlaybackController;
15import org.apollo.audio.util.SoundDesk;
16import org.apollo.audio.util.Timeline;
17import org.apollo.audio.util.MultiTrackPlaybackController.MultitrackLoadListener;
18import org.apollo.gui.FrameLayoutDaemon;
19import org.apollo.gui.Strokes;
20import org.apollo.io.IconRepository;
21import org.apollo.util.AudioMath;
22import org.apollo.util.Mutable;
23import org.apollo.util.ODFrameHeirarchyFetcher;
24import org.apollo.util.ODFrameHeirarchyFetcher.ODFrameReceiver;
25import org.apollo.widgets.FramePlayer;
26import org.expeditee.gui.Browser;
27import org.expeditee.gui.DisplayIO;
28import org.expeditee.gui.Frame;
29import org.expeditee.gui.FrameIO;
30import org.expeditee.gui.MessageBay;
31import org.expeditee.items.Item;
32import org.expeditee.items.ItemParentStateChangedEvent;
33
34/**
35 * A transient widget that destroys self once anchored...
36 * once anchored it commences playback of a frame if there is something to play.
37 *
38 * @author Brook Novak
39 *
40 */
41public class FramePlaybackLauncher extends Item {
42
43 private static int WIDTH = 80;
44 private static int HEIGHT = 80;
45 private static Stroke BORDER_STOKE = Strokes.SOLID_1;
46
47 private static final Color BASE_COLOR = new Color(60, 148, 255);
48 private static final Color HIGHLIGHT_COLOR = new Color(253, 255, 201);
49
50 private String frameToPlay = null;
51
52 /**
53 * @param frameToPlay
54 * The frame to begin playback from. Null to play current frame.
55 */
56 public FramePlaybackLauncher(String frameToPlay) {
57 this.setID(getParentOrCurrentFrame().getNextItemID());
58 this.frameToPlay = frameToPlay;
59 }
60
61 @Override
62 public Item copy() {
63 FramePlaybackLauncher copy = new FramePlaybackLauncher(frameToPlay);
64
65 DuplicateItem(this, copy);
66
67 return copy;
68 }
69
70 @Override
71 public Item merge(Item merger, int mouseX, int mouseY) {
72 return null;
73 }
74
75 @Override
76 public void paint(Graphics2D g) {
77 if (Browser._theBrowser == null) return;
78
79 Paint restore = g.getPaint();
80
81 if (ApolloSystem.useQualityGraphics) {
82 GradientPaint gp = new GradientPaint(
83 _x + (WIDTH / 2), _y, HIGHLIGHT_COLOR,
84 _x + (WIDTH / 2), _y + HEIGHT - (HEIGHT / 5), BASE_COLOR);
85 g.setPaint(gp);
86 } else {
87 g.setColor(BASE_COLOR);
88 }
89
90 g.fillRect((int)_x, (int)_y, WIDTH, HEIGHT);
91
92 g.setPaint(restore);
93
94 g.setColor(Color.BLACK);
95 g.setStroke(BORDER_STOKE);
96 g.drawRect((int)_x, (int)_y, WIDTH, HEIGHT);
97
98 IconRepository.getIcon("frameplay.png").paintIcon(
99 Browser._theBrowser.getContentPane(), g, getX() + 25, getY() + 25);
100
101 }
102
103 @Override
104 public void setAnnotation(boolean val) {
105 }
106
107
108 @Override
109 public int getHeight() {
110 return HEIGHT;
111 }
112
113 @Override
114 public int getWidth() {
115 return WIDTH;
116 }
117
118 @Override
119 public void updatePolygon() {
120
121 _poly = new Polygon();
122
123 int x = (int)_x;
124 int y = (int)_y;
125
126 _poly.addPoint(x, y);
127 _poly.addPoint(x + WIDTH, y);
128 _poly.addPoint(x + WIDTH, y + HEIGHT);
129 _poly.addPoint(x, y + HEIGHT);
130
131 }
132
133 @Override
134 public void onParentStateChanged(ItemParentStateChangedEvent e) {
135 super.onParentStateChanged(e);
136
137 switch (e.getEventType()) {
138
139 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED:
140 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY:
141 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN:
142 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY:
143 // todo: Invoke later for concurrent modification possibility?
144 selfDestruct();
145 break;
146
147 }
148 }
149
150 private void selfDestruct() {
151
152 Frame parent = getParent();
153 parent.removeItem(this);
154
155 if (DisplayIO.getCurrentFrame() == null) return;
156
157 Frame audioFrame = null;
158
159 // Flag as null if frame to play is actually current frame
160 if (frameToPlay != null && frameToPlay.equals(DisplayIO.getCurrentFrame().getName()))
161 frameToPlay = null;
162
163 if (frameToPlay == null) {
164 audioFrame = DisplayIO.getCurrentFrame();
165 } else {
166 audioFrame = FrameIO.LoadFrame(frameToPlay);
167 }
168
169 if (audioFrame == null) {
170 if (frameToPlay != null)
171 MessageBay.errorMessage("Unable to play frame \"" + frameToPlay + "\" - unknown frame");
172 else
173 MessageBay.errorMessage("Unable to play current frame");
174
175 } else {
176
177 if (frameToPlay == null) {
178
179 Timeline tl = FrameLayoutDaemon.getInstance().getLastComputedTimeline();
180 if (tl == null)
181 tl = FrameLayoutDaemon.inferTimeline(audioFrame);
182 if (tl == null) return;
183
184 long initiateMS = tl.getMSTimeAtX((int)_x);
185
186 // Clamp
187 if (initiateMS < tl.getFirstInitiationTime())
188 initiateMS = tl.getFirstInitiationTime();
189
190 else if (initiateMS > (tl.getFirstInitiationTime() + tl.getRunningTime()))
191 initiateMS = tl.getFirstInitiationTime() + tl.getRunningTime();
192
193 int startFrame = AudioMath.millisecondsToFrames(
194 initiateMS - tl.getFirstInitiationTime(),
195 SampledAudioManager.getInstance().getDefaultPlaybackFormat());
196
197 playFrame(audioFrame.getName(), startFrame);
198
199 } else {
200 // Fetch the audio graph for the frame
201 GraphReceiver receiver = new GraphReceiver(DisplayIO.getCurrentFrame());
202 ODFrameHeirarchyFetcher.getInstance().doFetch(audioFrame.getName(), receiver);
203 // The callback will later begin playback
204 }
205
206
207 }
208 }
209
210 private void playFrame(String framename, int startFrame) {
211
212 // To ensure that the frame channels are not in use
213 MultiTrackPlaybackController.getInstance().stopPlayback();
214 SoundDesk.getInstance().freeChannels(FramePlayer.FRAME_PLAYERMASTER_CHANNEL_ID);
215
216 FramePlayer.playFrame(
217 new MultitrackLoadListener() {
218
219 public void multiplaybackLoadStatusUpdate(int id, Object state) {
220 // Ignore
221 }
222
223 },
224 framename,
225 false,
226 startFrame,
227 Integer.MAX_VALUE
228 );
229
230 }
231
232 private class GraphReceiver implements ODFrameReceiver {
233
234 private Frame fromFrame;
235
236 public GraphReceiver(Frame fromFrame) {
237 assert(fromFrame != null);
238 this.fromFrame = fromFrame;
239 }
240 public void receiveResult(OverdubbedFrame odFrame, TrackGraphLoopException loopEx) {
241
242 if(odFrame == null){
243 if (loopEx != null)
244 MessageBay.errorMessage("Unable to play frame \"" + frameToPlay + "\" - bad structure");
245 return;
246 }
247
248 OverdubbedFrame fromODFrame = odFrame.getChild(fromFrame.getName());
249
250 int startFrame = 0;
251
252 // Get the timeline for the frame that the playback will be initated from
253 Timeline tl = FrameLayoutDaemon.getInstance().getTimeline(fromFrame);
254
255 if (tl == null || fromODFrame == null) {
256 // The user tried to play a frame, unreachable from some other frame.
257 // Thus the start frame will be hence taken as a percentage of the whole frame
258
259 float percent = _x / Browser._theBrowser.getContentPane().getWidth();
260 if (percent < 0) percent = 0;
261 if (percent > 1) percent = 1;
262
263 startFrame = AudioMath.millisecondsToFrames(
264 (long)((float)odFrame.calculateRunningTime() * percent),
265 SampledAudioManager.getInstance().getDefaultPlaybackFormat());
266
267 } else {
268
269 // Find the frames absolute init time
270 Mutable.Long childFrameABSStartTime = odFrame.getChildFrameInitiationTime(fromFrame.getName());
271
272 if (childFrameABSStartTime == null)
273 return; // nothing to play
274
275 long deltaMS = tl.getMSTimeAtX((int)_x) - fromODFrame.getFirstInitiationTime();
276
277 startFrame = AudioMath.millisecondsToFrames(
278 childFrameABSStartTime.value + deltaMS,
279 SampledAudioManager.getInstance().getDefaultPlaybackFormat());
280
281 }
282
283 playFrame(odFrame.getFrameName(), startFrame);
284
285 }
286 }
287
288}
Note: See TracBrowser for help on using the repository browser.