/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2011 Andreas Maschke This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.create.tina.dance.action; import java.io.File; import java.util.ArrayList; import java.util.List; import org.jwildfire.base.Prefs; import org.jwildfire.create.tina.audio.RecordedFFT; import org.jwildfire.create.tina.base.Flame; import org.jwildfire.create.tina.dance.DancingFlame; import org.jwildfire.create.tina.dance.DancingFlameProject; import org.jwildfire.create.tina.dance.DancingFlameStack; import org.jwildfire.create.tina.dance.FlamePreparer; import org.jwildfire.create.tina.dance.RealtimeAnimRenderThread; import org.jwildfire.create.tina.dance.motion.DanceFlameTransformer; import org.jwildfire.create.tina.io.FlameWriter; public class PostRecordFlameGenerator { private final DancingFlameProject project; private final RealtimeAnimRenderThread thread; private final ActionRecorder recorder; private final Prefs prefs; private final RecordedFFT fftData; private final DanceFlameTransformer transformer; public PostRecordFlameGenerator(Prefs pPrefs, DancingFlameProject pProject, ActionRecorder pRecorder, RealtimeAnimRenderThread pThread, RecordedFFT pFFTData) { project = pProject; prefs = pPrefs; recorder = pRecorder; thread = pThread; fftData = pFFTData; transformer = new DanceFlameTransformer(project); } public void createRecordedFlameFiles(String pAbsolutePath) throws Exception { if (recorder.getRecordedActions().size() >= 2) { List<Flame> flames = new ArrayList<Flame>(); int actionIdx = 0; StartAction startAction = (StartAction) recorder.getRecordedActions().get(actionIdx++); DancingFlameStack flameStack = new DancingFlameStack(prefs); flameStack.addFlame(startAction.getFlame(), 0, project.getMotions(startAction.getFlame())); RecordedAction nextAction = recorder.getRecordedActions().get(actionIdx++); long timeRenderStarted = System.currentTimeMillis(); long nextFrame = (long) (timeRenderStarted + 1000.0 / (double) thread.getFramesPerSecond() + 0.5); while (true) { long time = System.currentTimeMillis(); while (time < nextFrame) { try { Thread.sleep(1); } catch (Exception ex) { ex.printStackTrace(); } time = System.currentTimeMillis(); } nextFrame = (long) (time + 1000.0 / (double) thread.getFramesPerSecond() + 0.5); DancingFlame dancingFlame = flameStack.getFlame(); Flame renderFlame; long currTime = time - timeRenderStarted; short currFFT[]; if (fftData == null) { // t.createTransformedFlame() --> motion.computeValue() handles null currFFT values // if _using_ fftMotion, currFFT == null will result in no change from base offset // if _not_using_ fftMotion, currFFT is ignored currFFT = null; } else { currFFT = fftData.getDataByTimeOffset(currTime); } Flame transformedFlame = transformer.createTransformedFlame(dancingFlame, currFFT, currTime, thread.getFramesPerSecond()); renderFlame = new FlamePreparer(prefs).createRenderFlame(transformedFlame); flames.add(renderFlame); if (time >= timeRenderStarted + nextAction.getTime()) { if (nextAction instanceof StopAction) { break; } else if (nextAction instanceof FlameChangeAction) { Flame nextFlame = ((FlameChangeAction) nextAction).getFlame(); flameStack.addFlame(nextFlame, ((FlameChangeAction) nextAction).getMorphFrameCount(), project.getMotions(nextFlame)); nextAction = recorder.getRecordedActions().get(actionIdx++); } else { throw new Exception("Unknown action type <" + nextAction.getClass() + ">"); } } } if (flames.size() > 0) { File file = new File(pAbsolutePath); String fn = file.getName(); { int p = fn.indexOf(".flame"); if (p > 0 && p == fn.length() - 6) { fn = fn.substring(0, p); } } int fileIdx = 1; for (Flame flame : flames) { String hs = String.valueOf(fileIdx++); while (hs.length() < 5) { hs = "0" + hs; } new FlameWriter().writeFlame(flame, new File(file.getParent(), fn + hs + ".flame").getAbsolutePath()); } } else { throw new Exception("No flame files where created"); } } else { throw new Exception("No valid recording"); } } }