1 | package org.apollo.gui;
|
---|
2 |
|
---|
3 | import java.util.LinkedList;
|
---|
4 | import java.util.List;
|
---|
5 |
|
---|
6 | import org.apollo.audio.ApolloPlaybackMixer;
|
---|
7 | import org.apollo.audio.ApolloSubjectChangedEvent;
|
---|
8 | import org.apollo.audio.structure.OverdubbedFrame;
|
---|
9 | import org.apollo.audio.util.MultiTrackPlaybackController;
|
---|
10 | import org.apollo.audio.util.PlaybackClock;
|
---|
11 | import org.apollo.audio.util.Timeline;
|
---|
12 | import org.apollo.audio.util.PlaybackClock.PlaybackClockListener;
|
---|
13 | import org.apollo.mvc.Observer;
|
---|
14 | import org.apollo.mvc.Subject;
|
---|
15 | import org.apollo.mvc.SubjectChangedEvent;
|
---|
16 | import org.apollo.util.AudioMath;
|
---|
17 | import org.apollo.widgets.FramePlayer;
|
---|
18 | import org.expeditee.core.Colour;
|
---|
19 | import org.expeditee.core.Stroke;
|
---|
20 | import org.expeditee.core.bounds.AxisAlignedBoxBounds;
|
---|
21 | import org.expeditee.gio.EcosystemManager;
|
---|
22 | import org.expeditee.gio.GraphicsManager;
|
---|
23 | import org.expeditee.gui.Browser;
|
---|
24 | import org.expeditee.gui.DisplayController;
|
---|
25 | import org.expeditee.gui.Frame;
|
---|
26 |
|
---|
27 | /**
|
---|
28 | * Renders playback bars while the multi playback controller is playing.
|
---|
29 | * Depending on which frame the user is on etc...
|
---|
30 | *
|
---|
31 | * @author Brook Novak
|
---|
32 | *
|
---|
33 | */
|
---|
34 | public class FramePlaybackBarRenderer implements PlaybackClockListener, Observer {
|
---|
35 |
|
---|
36 | /** Relative to the current multi-track groups root frame. */
|
---|
37 | private long currentMSPosition = 0;
|
---|
38 |
|
---|
39 | //private long liveFrameOffset = 0;
|
---|
40 |
|
---|
41 | private List<Integer> pixelPositions = new LinkedList<Integer>();
|
---|
42 | private String pixelPositionsParent = null; // framename
|
---|
43 |
|
---|
44 | private Timeline currentTimeline = null;
|
---|
45 |
|
---|
46 | private PlaybackFrameBarUpdator updator = new PlaybackFrameBarUpdator();
|
---|
47 |
|
---|
48 | private static final int BAR_STROKE_THICKNESS = 2;
|
---|
49 | private static final Stroke BAR_STROKE = new Stroke(BAR_STROKE_THICKNESS);
|
---|
50 | private static final Colour BAR_COLOR = Colour.DARK_GREY;
|
---|
51 |
|
---|
52 | private static FramePlaybackBarRenderer instance = new FramePlaybackBarRenderer();
|
---|
53 |
|
---|
54 | private FramePlaybackBarRenderer() {
|
---|
55 | MultiTrackPlaybackController.getInstance().addObserver(this);
|
---|
56 | //DisplayIO.addDisplayIOObserver(this);
|
---|
57 | FrameLayoutDaemon.getInstance().addObserver(this);
|
---|
58 | }
|
---|
59 |
|
---|
60 | public static FramePlaybackBarRenderer getInstance() {
|
---|
61 | return instance;
|
---|
62 | }
|
---|
63 |
|
---|
64 | /**
|
---|
65 | * {@inheritDoc}
|
---|
66 | */
|
---|
67 | public Subject getObservedSubject() {
|
---|
68 | return null;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | * {@inheritDoc}
|
---|
73 | */
|
---|
74 | public void setObservedSubject(Subject parent) {
|
---|
75 | }
|
---|
76 |
|
---|
77 | /**
|
---|
78 | * {@inheritDoc}
|
---|
79 | */
|
---|
80 | public void modelChanged(Subject source, SubjectChangedEvent event) {
|
---|
81 |
|
---|
82 | if (source == FrameLayoutDaemon.getInstance()) {
|
---|
83 | currentTimeline = FrameLayoutDaemon.getInstance().getLastComputedTimeline();
|
---|
84 |
|
---|
85 | updator.run();
|
---|
86 | // Asumming refresh will occur
|
---|
87 |
|
---|
88 | return;
|
---|
89 | }
|
---|
90 |
|
---|
91 | switch (event.getID()) {
|
---|
92 | case ApolloSubjectChangedEvent.PLAYBACK_STARTED:
|
---|
93 |
|
---|
94 | /*liveFrameOffset = ApolloPlaybackMixer.getInstance().getLiveFramePosition();
|
---|
95 | if (liveFrameOffset < 0) liveFrameOffset = 0;
|
---|
96 | System.out.println("liveFrameOffset=" + liveFrameOffset);*/
|
---|
97 |
|
---|
98 | PlaybackClock.getInstance().addPlaybackClockListener(this);
|
---|
99 | break;
|
---|
100 |
|
---|
101 | case ApolloSubjectChangedEvent.PLAYBACK_STOPPED:
|
---|
102 | PlaybackClock.getInstance().removePlaybackClockListener(this);
|
---|
103 |
|
---|
104 | if (MultiTrackPlaybackController.getInstance().isMarkedAsPaused() &&
|
---|
105 | FramePlayer.FRAME_PLAYERMASTER_CHANNEL_ID.equals(
|
---|
106 | MultiTrackPlaybackController.getInstance().getCurrentMasterChannelID())) {
|
---|
107 |
|
---|
108 | currentMSPosition = AudioMath.framesToMilliseconds(
|
---|
109 | MultiTrackPlaybackController.getInstance().getLastSuspendedFrame(),
|
---|
110 | ApolloPlaybackMixer.getInstance().getLiveAudioFormat());
|
---|
111 |
|
---|
112 | updator.run();
|
---|
113 |
|
---|
114 | } else {
|
---|
115 | invalidate();
|
---|
116 | currentMSPosition = -1;
|
---|
117 | pixelPositions.clear();
|
---|
118 | }
|
---|
119 |
|
---|
120 | DisplayController.requestRefresh(true);
|
---|
121 |
|
---|
122 |
|
---|
123 | break;
|
---|
124 |
|
---|
125 | case ApolloSubjectChangedEvent.PAUSE_MARK_CHANGED:
|
---|
126 |
|
---|
127 |
|
---|
128 | invalidate();
|
---|
129 | currentMSPosition = -1;
|
---|
130 | pixelPositions.clear();
|
---|
131 | DisplayController.requestRefresh(true);
|
---|
132 |
|
---|
133 | break;
|
---|
134 | }
|
---|
135 |
|
---|
136 |
|
---|
137 | }
|
---|
138 |
|
---|
139 | private void invalidate()
|
---|
140 | {
|
---|
141 | if (Browser._theBrowser == null) return;
|
---|
142 |
|
---|
143 | int height = EcosystemManager.getGraphicsManager().getWindowSize().getHeight();
|
---|
144 |
|
---|
145 | for (Integer n : pixelPositions) {
|
---|
146 | DisplayController.invalidateArea(new AxisAlignedBoxBounds(n - 1, 0, BAR_STROKE_THICKNESS + 2, height));
|
---|
147 | }
|
---|
148 | }
|
---|
149 |
|
---|
150 | public void paint()
|
---|
151 | {
|
---|
152 | if (Browser._theBrowser == null) return;
|
---|
153 |
|
---|
154 | Frame currentFrame = DisplayController.getCurrentFrame();
|
---|
155 |
|
---|
156 | if (currentFrame == null || currentFrame.getName() == null || pixelPositionsParent == null ||
|
---|
157 | !currentFrame.getName().equals(pixelPositionsParent)) return;
|
---|
158 |
|
---|
159 | int height = EcosystemManager.getGraphicsManager().getWindowSize().getHeight();
|
---|
160 |
|
---|
161 | GraphicsManager gm = EcosystemManager.getGraphicsManager();
|
---|
162 |
|
---|
163 | for (Integer n : pixelPositions) {
|
---|
164 | gm.drawLine(n, 0, n, height, BAR_COLOR, BAR_STROKE);
|
---|
165 | }
|
---|
166 | }
|
---|
167 |
|
---|
168 | /**
|
---|
169 | * {@inheritDoc}
|
---|
170 | */
|
---|
171 | public void onTick(long framePosition, long msPosition) {
|
---|
172 |
|
---|
173 | if (framePosition < 0) return; // let stop event handle it
|
---|
174 |
|
---|
175 | //framePosition -= liveFrameOffset;
|
---|
176 |
|
---|
177 | // Convert the audio mixers frame position to the multiplaybacks frame position
|
---|
178 |
|
---|
179 | int fpos = (int)(framePosition
|
---|
180 | - MultiTrackPlaybackController.getInstance().getLastInitiationFrame()
|
---|
181 | + MultiTrackPlaybackController.getInstance().getLastStartFrame());
|
---|
182 |
|
---|
183 | // Clamp
|
---|
184 | if (fpos > MultiTrackPlaybackController.getInstance().getLastEndFrame())
|
---|
185 | fpos = MultiTrackPlaybackController.getInstance().getLastEndFrame();
|
---|
186 |
|
---|
187 | currentMSPosition = AudioMath.framesToMilliseconds(
|
---|
188 | fpos,
|
---|
189 | ApolloPlaybackMixer.getInstance().getLiveAudioFormat());
|
---|
190 |
|
---|
191 | // Notes: the clock will queue a refresh for the frame after this
|
---|
192 | // event proccesses ...
|
---|
193 | EcosystemManager.getMiscManager().runOnGIOThread(updator);
|
---|
194 | }
|
---|
195 |
|
---|
196 | /**
|
---|
197 | * Note: refreshing is up to caller
|
---|
198 | *
|
---|
199 | * @author Brook Novak
|
---|
200 | */
|
---|
201 | private class PlaybackFrameBarUpdator implements Runnable
|
---|
202 | {
|
---|
203 | public void run() {
|
---|
204 |
|
---|
205 | if (currentMSPosition == -1 || currentTimeline == null) return;
|
---|
206 |
|
---|
207 | Frame currentFrame = DisplayController.getCurrentFrame();
|
---|
208 |
|
---|
209 | if (currentFrame == null || currentFrame.getName() == null) return;
|
---|
210 |
|
---|
211 | OverdubbedFrame od = MultiTrackPlaybackController.getInstance().getCurrentODFrame();
|
---|
212 | if (od == null) return;
|
---|
213 |
|
---|
214 | // Invalidate old positions
|
---|
215 | invalidate();
|
---|
216 | pixelPositions.clear();
|
---|
217 |
|
---|
218 | long firstInitTime = od.getFirstInitiationTime();
|
---|
219 |
|
---|
220 | List<Integer> msPositions = od.getMSPositions(
|
---|
221 | currentFrame.getName(),
|
---|
222 | currentMSPosition + firstInitTime);
|
---|
223 |
|
---|
224 | // Convert ms positions to pixel positions according to the current timeline
|
---|
225 | for (Integer n : msPositions) {
|
---|
226 | pixelPositions.add(new Integer(currentTimeline.getXAtMSTime(n + currentTimeline.getFirstInitiationTime())));
|
---|
227 | }
|
---|
228 |
|
---|
229 | pixelPositionsParent = currentFrame.getName();
|
---|
230 |
|
---|
231 | // Invalidate new positions
|
---|
232 | invalidate();
|
---|
233 | }
|
---|
234 | }
|
---|
235 |
|
---|
236 |
|
---|
237 |
|
---|
238 | }
|
---|