/* * @(#)MemeticDataSource.java * Created: 2 Nov 2007 * Version: 1.0 * Copyright (c) 2005-2006, University of Manchester All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. Redistributions in binary * form must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials * provided with the distribution. Neither the name of the University of * Manchester nor the names of its contributors may be used to endorse or * promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package javax.media.protocol.recorded; import java.io.IOException; import java.net.DatagramPacket; import javax.media.Time; import javax.media.format.UnsupportedFormatException; import javax.media.protocol.Positionable; import javax.media.protocol.PushBufferDataSource; import javax.media.protocol.PushBufferStream; /** * @author Andrew G D Rowley * @version 1.0 */ public class DataSource extends PushBufferDataSource implements Positionable { // The rtp stream private DatagramForwarder rtpStream = new DatagramForwarder(); private StreamSource streamSource = null; private String filename = null; private long seek = 0; private double scale = 1.0; private boolean playing = false; /** * @see javax.media.protocol.PushDataSource#getStreams() */ public PushBufferStream[] getStreams() { return new PushBufferStream[]{rtpStream}; } /** * @see javax.media.protocol.DataSource#connect() */ public void connect() throws IOException { String locator = getLocator().getRemainder().substring(2); String[] parts = locator.split("\\?", 2); filename = parts[0]; if (parts.length > 1) { String query = parts[1]; String[] values = query.split("&"); for (int i = 0; i < values.length; i++) { String[] value = values[i].split("=", 2); if (value[0].equals("scale")) { scale = Double.parseDouble(value[1]); } else if (value[0].equals("seek")) { seek = Long.parseLong(value[1]); } } } streamSource = new StreamSource(this, filename); try { rtpStream.setFormat(streamSource.getRtpFormat()); } catch (UnsupportedFormatException e) { throw new IOException(e.getMessage()); } } /** * @see javax.media.protocol.DataSource#disconnect() */ public void disconnect() { stop(); rtpStream.close(); } /** * @see javax.media.protocol.DataSource#getContentType() */ public String getContentType() { return "raw"; } /** * @see javax.media.protocol.DataSource#getControl(java.lang.String) */ public Object getControl(String cls) { return rtpStream.getControl(cls); } /** * @see javax.media.protocol.DataSource#getControls() */ public Object[] getControls() { return new Object[0]; } /** * @see javax.media.protocol.DataSource#start() */ public void start() { playing = true; streamSource.play(scale, seek); } /** * @see javax.media.protocol.DataSource#stop() */ public void stop() { playing = false; seek = streamSource.getCurrentTime(); streamSource.teardown(); streamSource = new StreamSource(this, filename); } /** * Handles an RTP Packet * @param packet The packet to handle */ public void handleRTPPacket(DatagramPacket packet) { rtpStream.handlePacket(packet); } /** * Seeks to a new time * @param seek The new time to seek to * @param scale The new scale to play at */ public void seek(long seek, double scale) { this.seek = seek; this.scale = scale; streamSource.teardown(); streamSource = new StreamSource(this, filename); if (playing) { streamSource.play(scale, seek); } } /** * Gets the current time of the playback * @return The current time in milliseconds */ public long getCurrentTime() { return streamSource.getCurrentTime(); } /** * @see javax.media.protocol.DataSource#getDuration() */ public Time getDuration() { return new Time(streamSource.getDuration() * 1000000); } /** * * @see javax.media.protocol.Positionable#isRandomAccess() */ public boolean isRandomAccess() { return true; } /** * * @see javax.media.protocol.Positionable#setPosition(javax.media.Time, int) */ public Time setPosition(Time where, int rounding) { boolean wasPlaying = playing; stop(); seek = where.getNanoseconds() / 1000000; playing = wasPlaying; start(); return where; } }