/* DemoFormatOutputStream.java (c) 2012-2014 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.engine.demos.format; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import v9t9.common.demos.DemoFormat; import v9t9.common.demos.DemoHeader; import v9t9.common.demos.IDemoEvent; import v9t9.common.demos.IDemoEventFormatter; import v9t9.common.demos.IDemoFormatterRegistry; import v9t9.common.demos.IDemoOutputBuffer; import v9t9.common.demos.IDemoOutputEventBuffer; import v9t9.common.demos.IDemoOutputStream; import v9t9.engine.demos.events.TimerTick; import v9t9.engine.demos.stream.BaseDemoOutputStream; /** * Write demos in new format more amenable to a non-memory constrained host and * a variable machine model. * * * @author ejs * */ public class DemoFormatOutputStream extends BaseDemoOutputStream implements IDemoOutputStream { private int timerTicks; private int ticks; private DemoHeader header; private Map<String, IDemoOutputEventBuffer> eventToBufferMap = new HashMap<String, IDemoOutputEventBuffer>(); private byte[] magic; public DemoFormatOutputStream(DemoHeader header, OutputStream os_) throws IOException { super(os_); this.header = header; this.magic = header.getMagic(); os.write(magic); timerTicks = 0; for (Map.Entry<Integer, String> ent : header.getBufferIdentifierMap().entrySet()) { String bufferId = ent.getValue(); final IDemoEventFormatter formatter = IDemoFormatterRegistry.INSTANCE.findFormatterByBuffer(bufferId); if (formatter != null) { int code = header.findOrAllocateIdentifier(bufferId); DemoOutputEventBuffer buffer = new DemoFormatterOutputEventBuffer(os, code, bufferId, formatter); registerBuffer(buffer, formatter.getEventIdentifier()); } else { // callers should invoke #registerBuffer System.out.println(bufferId); } } header.write(os); } /* (non-Javadoc) * @see v9t9.common.demos.IDemoOutputStream#getDemoFormat() */ @Override public byte[] getDemoFormat() { return magic; } /** * Register a custom buffer and event type. * @param buffer * @param eventId * @throws IOException */ public void registerBuffer(IDemoOutputEventBuffer buffer, String eventId) throws IOException { if (!buffers.contains(buffer)) buffers.add((IDemoOutputBuffer) buffer); eventToBufferMap.put(eventId, buffer); } @Override public int getTimerRate() { return header.getTimerRate(); } @Override public long getElapsedTime() { return ticks * 1000L / getTimerRate(); } @Override protected void preClose() throws IOException { super.preClose(); if (timerTicks > 0) { emitTimerTick(); } } @Override public synchronized void writeEvent(IDemoEvent event) throws IOException { if (event instanceof TimerTick) { writeTimerTick(); } else if (event != null) { String id = event.getIdentifier(); IDemoOutputEventBuffer buffer = eventToBufferMap.get(id); if (buffer == null) throw new IOException("unknown buffer/event type: " + id); buffer.encodeEvent(event); } } protected void emitTimerTick() throws IOException { os.write(DemoFormat.TICK); os.write(timerTicks); timerTicks = 0; } @Override protected void writeTimerTick() throws IOException { if (anythingToFlush() || timerTicks == 255) { emitTimerTick(); flushAll(); } ++timerTicks; ticks++; } }