1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.jme3.audio.plugins; 34 35 import de.jarnbjo.ogg.*; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.util.Collection; 39 import java.util.HashMap; 40 import java.util.LinkedList; 41 42 /** 43 * Single-threaded physical ogg stream. Decodes audio in the same thread 44 * that reads. 45 */ 46 public class UncachedOggStream implements PhysicalOggStream { 47 48 private boolean closed = false; 49 private boolean eos = false; 50 private boolean bos = false; 51 private InputStream sourceStream; 52 private LinkedList<OggPage> pageCache = new LinkedList<OggPage>(); 53 private HashMap<Integer, LogicalOggStream> logicalStreams 54 = new HashMap<Integer, LogicalOggStream>(); 55 private OggPage lastPage = null; 56 57 public UncachedOggStream(InputStream in) throws OggFormatException, IOException { 58 this.sourceStream = in; 59 60 // read until beginning of stream 61 while (!bos){ 62 readNextOggPage(); 63 } 64 65 // now buffer up an addition 25 pages 66 // while (pageCache.size() < 25 && !eos){ 67 // readNextOggPage(); 68 // } 69 } 70 71 public OggPage getLastOggPage() { 72 return lastPage; 73 } 74 75 private void readNextOggPage() throws IOException { 76 OggPage op = OggPage.create(sourceStream); 77 if (!op.isBos()){ 78 bos = true; 79 } 80 if (op.isEos()){ 81 eos = true; 82 lastPage = op; 83 } 84 85 LogicalOggStreamImpl los = (LogicalOggStreamImpl) getLogicalStream(op.getStreamSerialNumber()); 86 if (los == null){ 87 los = new LogicalOggStreamImpl(this, op.getStreamSerialNumber()); 88 logicalStreams.put(op.getStreamSerialNumber(), los); 89 los.checkFormat(op); 90 } 91 92 pageCache.add(op); 93 } 94 95 public OggPage getOggPage(int index) throws IOException { 96 if (eos){ 97 return null; 98 } 99 100 // if (!eos){ 101 // int num = pageCache.size(); 102 // long fiveMillis = 5000000; 103 // long timeStart = System.nanoTime(); 104 // do { 105 // readNextOggPage(); 106 // } while ( !eos && (System.nanoTime() - timeStart) < fiveMillis ); 107 // System.out.println( pageCache.size() - num ); 108 109 if (pageCache.size() == 0 /*&& !eos*/){ 110 readNextOggPage(); 111 } 112 // } 113 114 return pageCache.removeFirst(); 115 } 116 117 private LogicalOggStream getLogicalStream(int serialNumber) { 118 return logicalStreams.get(Integer.valueOf(serialNumber)); 119 } 120 121 public Collection<LogicalOggStream> getLogicalStreams() { 122 return logicalStreams.values(); 123 } 124 125 public void setTime(long granulePosition) throws IOException { 126 } 127 128 public boolean isSeekable() { 129 return false; 130 } 131 132 public boolean isOpen() { 133 return !closed; 134 } 135 136 public void close() throws IOException { 137 closed = true; 138 sourceStream.close(); 139 } 140 } 141