summaryrefslogtreecommitdiff
path: root/songdbj/de/jarnbjo/ogg
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/de/jarnbjo/ogg')
-rw-r--r--songdbj/de/jarnbjo/ogg/BasicStream.java121
-rw-r--r--songdbj/de/jarnbjo/ogg/CachedUrlStream.java252
-rw-r--r--songdbj/de/jarnbjo/ogg/EndOfOggStreamException.java45
-rw-r--r--songdbj/de/jarnbjo/ogg/FileStream.java154
-rw-r--r--songdbj/de/jarnbjo/ogg/LogicalOggStream.java151
-rw-r--r--songdbj/de/jarnbjo/ogg/LogicalOggStreamImpl.java213
-rw-r--r--songdbj/de/jarnbjo/ogg/OggFormatException.java50
-rw-r--r--songdbj/de/jarnbjo/ogg/OggPage.java431
-rw-r--r--songdbj/de/jarnbjo/ogg/OnDemandUrlStream.java127
-rw-r--r--songdbj/de/jarnbjo/ogg/PhysicalOggStream.java124
-rw-r--r--songdbj/de/jarnbjo/ogg/UncachedUrlStream.java207
11 files changed, 0 insertions, 1875 deletions
diff --git a/songdbj/de/jarnbjo/ogg/BasicStream.java b/songdbj/de/jarnbjo/ogg/BasicStream.java
deleted file mode 100644
index 9939524d6c..0000000000
--- a/songdbj/de/jarnbjo/ogg/BasicStream.java
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.3 2004/09/21 12:09:45 shred
22 * *** empty log message ***
23 *
24 * Revision 1.2 2004/09/21 06:38:45 shred
25 * Importe reorganisiert, damit Eclipse Ruhe gibt. ;-)
26 *
27 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
28 * First Import
29 *
30 *
31 */
32
33package de.jarnbjo.ogg;
34
35import java.io.IOException;
36import java.io.InputStream;
37import java.util.Collection;
38import java.util.HashMap;
39import java.util.LinkedList;
40
41/**
42 * Implementation of the <code>PhysicalOggStream</code> interface for reading
43 * an Ogg stream from a URL. This class performs
44 * no internal caching, and will not read data from the network before
45 * requested to do so. It is intended to be used in non-realtime applications
46 * like file download managers or similar.
47 */
48
49public class BasicStream implements PhysicalOggStream {
50
51 private boolean closed=false;
52 private InputStream sourceStream;
53 private Object drainLock=new Object();
54 private LinkedList pageCache=new LinkedList();
55 private long numberOfSamples=-1;
56 private int position=0;
57
58 private HashMap logicalStreams=new HashMap();
59 private OggPage firstPage;
60
61 public BasicStream(InputStream sourceStream) throws OggFormatException, IOException {
62 firstPage=OggPage.create(sourceStream);
63 position+=firstPage.getTotalLength();
64 LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
65 logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
66 los.checkFormat(firstPage);
67 }
68
69 public Collection getLogicalStreams() {
70 return logicalStreams.values();
71 }
72
73 public boolean isOpen() {
74 return !closed;
75 }
76
77 public void close() throws IOException {
78 closed=true;
79 sourceStream.close();
80 }
81
82 public int getContentLength() {
83 return -1;
84 }
85
86 public int getPosition() {
87 return position;
88 }
89
90 int pageNumber=2;
91
92 public OggPage getOggPage(int index) throws IOException {
93 if(firstPage!=null) {
94 OggPage tmp=firstPage;
95 firstPage=null;
96 return tmp;
97 }
98 else {
99 OggPage page=OggPage.create(sourceStream);
100 position+=page.getTotalLength();
101 return page;
102 }
103 }
104
105 private LogicalOggStream getLogicalStream(int serialNumber) {
106 return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
107 }
108
109 public void setTime(long granulePosition) throws IOException {
110 throw new UnsupportedOperationException("Method not supported by this class");
111 }
112
113 /**
114 * @return always <code>false</code>
115 */
116
117 public boolean isSeekable() {
118 return false;
119 }
120
121} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/CachedUrlStream.java b/songdbj/de/jarnbjo/ogg/CachedUrlStream.java
deleted file mode 100644
index 86f792e272..0000000000
--- a/songdbj/de/jarnbjo/ogg/CachedUrlStream.java
+++ /dev/null
@@ -1,252 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.1 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 *
28 */
29
30package de.jarnbjo.ogg;
31
32import java.io.*;
33import java.net.*;
34import java.util.*;
35
36/**
37 * Implementation of the <code>PhysicalOggStream</code> interface for reading
38 * and caching an Ogg stream from a URL. This class reads the data as fast as
39 * possible from the URL, caches it locally either in memory or on disk, and
40 * supports seeking within the available data.
41 */
42
43public class CachedUrlStream implements PhysicalOggStream {
44
45 private boolean closed=false;
46 private URLConnection source;
47 private InputStream sourceStream;
48 private Object drainLock=new Object();
49 private RandomAccessFile drain;
50 private byte[] memoryCache;
51 private ArrayList pageOffsets=new ArrayList();
52 private ArrayList pageLengths=new ArrayList();
53 private long numberOfSamples=-1;
54 private long cacheLength;
55
56 private HashMap logicalStreams=new HashMap();
57
58 private LoaderThread loaderThread;
59
60 /**
61 * Creates an instance of this class, using a memory cache.
62 */
63
64 public CachedUrlStream(URL source) throws OggFormatException, IOException {
65 this(source, null);
66 }
67
68 /**
69 * Creates an instance of this class, using the specified file as cache. The
70 * file is not automatically deleted when this class is disposed.
71 */
72
73 public CachedUrlStream(URL source, RandomAccessFile drain) throws OggFormatException, IOException {
74
75 this.source=source.openConnection();
76
77 if(drain==null) {
78 int contentLength=this.source.getContentLength();
79 if(contentLength==-1) {
80 throw new IOException("The URLConncetion's content length must be set when operating with a in-memory cache.");
81 }
82 memoryCache=new byte[contentLength];
83 }
84
85 this.drain=drain;
86 this.sourceStream=this.source.getInputStream();
87
88 loaderThread=new LoaderThread(sourceStream, drain, memoryCache);
89 new Thread(loaderThread).start();
90
91 while(!loaderThread.isBosDone() || pageOffsets.size()<20) {
92 System.out.print("pageOffsets.size(): "+pageOffsets.size()+"\r");
93 try {
94 Thread.sleep(200);
95 }
96 catch (InterruptedException ex) {
97 }
98 }
99 System.out.println();
100 System.out.println("caching "+pageOffsets.size()+"/20 pages\r");
101 }
102
103 public Collection getLogicalStreams() {
104 return logicalStreams.values();
105 }
106
107 public boolean isOpen() {
108 return !closed;
109 }
110
111 public void close() throws IOException {
112 closed=true;
113 sourceStream.close();
114 }
115
116 public long getCacheLength() {
117 return cacheLength;
118 }
119
120 /*
121 private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
122 return getNextPage(false);
123 }
124
125 private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
126 return OggPage.create(sourceStream, skipData);
127 }
128 */
129
130 public OggPage getOggPage(int index) throws IOException {
131 synchronized(drainLock) {
132 Long offset=(Long)pageOffsets.get(index);
133 Long length=(Long)pageLengths.get(index);
134 if(offset!=null) {
135 if(drain!=null) {
136 drain.seek(offset.longValue());
137 return OggPage.create(drain);
138 }
139 else {
140 byte[] tmpArray=new byte[length.intValue()];
141 System.arraycopy(memoryCache, offset.intValue(), tmpArray, 0, length.intValue());
142 return OggPage.create(tmpArray);
143 }
144 }
145 else {
146 return null;
147 }
148 }
149 }
150
151 private LogicalOggStream getLogicalStream(int serialNumber) {
152 return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
153 }
154
155 public void setTime(long granulePosition) throws IOException {
156 for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
157 LogicalOggStream los=(LogicalOggStream)iter.next();
158 los.setTime(granulePosition);
159 }
160 }
161
162 public class LoaderThread implements Runnable {
163
164 private InputStream source;
165 private RandomAccessFile drain;
166 private byte[] memoryCache;
167
168 private boolean bosDone=false;
169
170 private int pageNumber;
171
172 public LoaderThread(InputStream source, RandomAccessFile drain, byte[] memoryCache) {
173 this.source=source;
174 this.drain=drain;
175 this.memoryCache=memoryCache;
176 }
177
178 public void run() {
179 try {
180 boolean eos=false;
181 byte[] buffer=new byte[8192];
182 while(!eos) {
183 OggPage op=OggPage.create(source);
184 synchronized (drainLock) {
185 int listSize=pageOffsets.size();
186
187 long pos=
188 listSize>0?
189 ((Long)pageOffsets.get(listSize-1)).longValue()+
190 ((Long)pageLengths.get(listSize-1)).longValue():
191 0;
192
193 byte[] arr1=op.getHeader();
194 byte[] arr2=op.getSegmentTable();
195 byte[] arr3=op.getData();
196
197 if(drain!=null) {
198 drain.seek(pos);
199 drain.write(arr1);
200 drain.write(arr2);
201 drain.write(arr3);
202 }
203 else {
204 System.arraycopy(arr1, 0, memoryCache, (int)pos, arr1.length);
205 System.arraycopy(arr2, 0, memoryCache, (int)pos+arr1.length, arr2.length);
206 System.arraycopy(arr3, 0, memoryCache, (int)pos+arr1.length+arr2.length, arr3.length);
207 }
208
209 pageOffsets.add(new Long(pos));
210 pageLengths.add(new Long(arr1.length+arr2.length+arr3.length));
211 }
212
213 if(!op.isBos()) {
214 bosDone=true;
215 //System.out.println("bosDone=true;");
216 }
217 if(op.isEos()) {
218 eos=true;
219 }
220
221 LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
222 if(los==null) {
223 los=new LogicalOggStreamImpl(CachedUrlStream.this, op.getStreamSerialNumber());
224 logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
225 los.checkFormat(op);
226 }
227
228 los.addPageNumberMapping(pageNumber);
229 los.addGranulePosition(op.getAbsoluteGranulePosition());
230
231 pageNumber++;
232 cacheLength=op.getAbsoluteGranulePosition();
233 //System.out.println("read page: "+pageNumber);
234 }
235 }
236 catch(EndOfOggStreamException e) {
237 // ok
238 }
239 catch(IOException e) {
240 e.printStackTrace();
241 }
242 }
243
244 public boolean isBosDone() {
245 return bosDone;
246 }
247 }
248
249 public boolean isSeekable() {
250 return true;
251 }
252} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/EndOfOggStreamException.java b/songdbj/de/jarnbjo/ogg/EndOfOggStreamException.java
deleted file mode 100644
index 4a0c3200f4..0000000000
--- a/songdbj/de/jarnbjo/ogg/EndOfOggStreamException.java
+++ /dev/null
@@ -1,45 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.2 2005/02/09 23:10:47 shred
22 * Serial UID für jarnbjo
23 *
24 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
25 * First Import
26 *
27 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
28 * no message
29 *
30 */
31
32 package de.jarnbjo.ogg;
33
34import java.io.IOException;
35
36/**
37 * Exception thrown when reaching the end of an Ogg stream
38 */
39
40public class EndOfOggStreamException extends IOException {
41 private static final long serialVersionUID = 3907210438109444408L;
42
43 public EndOfOggStreamException() {
44 }
45} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/FileStream.java b/songdbj/de/jarnbjo/ogg/FileStream.java
deleted file mode 100644
index 5a526300bf..0000000000
--- a/songdbj/de/jarnbjo/ogg/FileStream.java
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.1 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 *
28 */
29
30package de.jarnbjo.ogg;
31
32import java.io.*;
33import java.util.*;
34
35/**
36 * Implementation of the <code>PhysicalOggStream</code> interface for accessing
37 * normal disk files.
38 */
39
40public class FileStream implements PhysicalOggStream {
41
42 private boolean closed=false;
43 private RandomAccessFile source;
44 private long[] pageOffsets;
45 private long numberOfSamples=-1;
46
47 private HashMap logicalStreams=new HashMap();
48
49 /**
50 * Creates access to the specified file through the <code>PhysicalOggStream</code> interface.
51 * The specified source file must have been opened for reading.
52 *
53 * @param source the file to read from
54 *
55 * @throws OggFormatException if the stream format is incorrect
56 * @throws IOException if some other IO error occurs when reading the file
57 */
58
59 public FileStream(RandomAccessFile source) throws OggFormatException, IOException {
60 this.source=source;
61
62 ArrayList po=new ArrayList();
63 int pageNumber=0;
64 try {
65 while(true) {
66 po.add(new Long(this.source.getFilePointer()));
67
68 // skip data if pageNumber>0
69 OggPage op=getNextPage(pageNumber>0);
70 if(op==null) {
71 break;
72 }
73
74 LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
75 if(los==null) {
76 los=new LogicalOggStreamImpl(this, op.getStreamSerialNumber());
77 logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
78 }
79
80 if(pageNumber==0) {
81 los.checkFormat(op);
82 }
83
84 los.addPageNumberMapping(pageNumber);
85 los.addGranulePosition(op.getAbsoluteGranulePosition());
86
87 if(pageNumber>0) {
88 this.source.seek(this.source.getFilePointer()+op.getTotalLength());
89 }
90
91 pageNumber++;
92 }
93 }
94 catch(EndOfOggStreamException e) {
95 // ok
96 }
97 catch(IOException e) {
98 throw e;
99 }
100 //System.out.println("pageNumber: "+pageNumber);
101 this.source.seek(0L);
102 pageOffsets=new long[po.size()];
103 int i=0;
104 Iterator iter=po.iterator();
105 while(iter.hasNext()) {
106 pageOffsets[i++]=((Long)iter.next()).longValue();
107 }
108 }
109
110 public Collection getLogicalStreams() {
111 return logicalStreams.values();
112 }
113
114 public boolean isOpen() {
115 return !closed;
116 }
117
118 public void close() throws IOException {
119 closed=true;
120 source.close();
121 }
122
123 private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
124 return getNextPage(false);
125 }
126
127 private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
128 return OggPage.create(source, skipData);
129 }
130
131 public OggPage getOggPage(int index) throws IOException {
132 source.seek(pageOffsets[index]);
133 return OggPage.create(source);
134 }
135
136 private LogicalOggStream getLogicalStream(int serialNumber) {
137 return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
138 }
139
140 public void setTime(long granulePosition) throws IOException {
141 for(Iterator iter=logicalStreams.values().iterator(); iter.hasNext(); ) {
142 LogicalOggStream los=(LogicalOggStream)iter.next();
143 los.setTime(granulePosition);
144 }
145 }
146
147 /**
148 * @return always <code>true</code>
149 */
150
151 public boolean isSeekable() {
152 return true;
153 }
154} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/LogicalOggStream.java b/songdbj/de/jarnbjo/ogg/LogicalOggStream.java
deleted file mode 100644
index 2f97b2a728..0000000000
--- a/songdbj/de/jarnbjo/ogg/LogicalOggStream.java
+++ /dev/null
@@ -1,151 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.2 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
28 * no message
29 *
30 */
31
32package de.jarnbjo.ogg;
33
34import java.io.IOException;
35
36/**
37 * Interface providing access to a logical Ogg stream as part of a
38 * physical Ogg stream.
39 */
40
41
42public interface LogicalOggStream {
43
44 public static final String FORMAT_UNKNOWN = "application/octet-stream";
45
46 public static final String FORMAT_VORBIS = "audio/x-vorbis";
47 public static final String FORMAT_FLAC = "audio/x-flac";
48 public static final String FORMAT_THEORA = "video/x-theora";
49
50 /**
51 * <i>Note:</i> To read from the stream, you must use either
52 * this method or the method <code>getNextOggPacket</code>.
53 * Mixing calls to the two methods will cause data corruption.
54 *
55 * @return the next Ogg page
56 *
57 * @see #getNextOggPacket()
58 *
59 * @throws OggFormatException if the ogg stream is corrupted
60 * @throws IOException if some other IO error occurs
61 */
62
63 public OggPage getNextOggPage() throws OggFormatException, IOException;
64
65 /**
66 * <i>Note:</i> To read from the stream, you must use either
67 * this method or the method <code>getNextOggPage</code>.
68 * Mixing calls to the two methods will cause data corruption.
69 *
70 * @return the next packet as a byte array
71 *
72 * @see #getNextOggPage()
73 *
74 * @throws OggFormatException if the ogg stream is corrupted
75 * @throws IOException if some other IO error occurs
76 */
77
78 public byte[] getNextOggPacket() throws OggFormatException, IOException;
79
80 /**
81 * Checks if this stream is open for reading.
82 *
83 * @return <code>true</code> if this stream is open for reading,
84 * <code>false</code> otherwise
85 */
86
87 public boolean isOpen();
88
89 /**
90 * Closes this stream. After invoking this method, no further access
91 * to the streams data is possible.
92 *
93 * @throws IOException if an IO error occurs
94 */
95
96 public void close() throws IOException;
97
98 /**
99 * Sets the stream's position to the beginning of the stream.
100 * This method does not work if the physical Ogg stream is not
101 * seekable.
102 *
103 * @throws OggFormatException if the ogg stream is corrupted
104 * @throws IOException if some other IO error occurs
105 */
106
107 public void reset() throws OggFormatException, IOException;
108
109 /**
110 * This method does not work if the physical Ogg stream is not
111 * seekable.
112 *
113 * @return the granule position of the last page within
114 * this stream
115 */
116
117 public long getMaximumGranulePosition();
118
119 /**
120 * This method is invoked on all logical streams when
121 * calling the same method on the physical stream. The
122 * same restrictions as mentioned there apply.
123 * This method does not work if the physical Ogg stream is not
124 * seekable.
125 *
126 * @param granulePosition
127 *
128 * @see PhysicalOggStream#setTime(long)
129 *
130 * @throws IOException if an IO error occurs
131 */
132
133 public void setTime(long granulePosition) throws IOException;
134
135 /**
136 * @return the last parsed granule position of this stream
137 */
138
139 public long getTime();
140
141 /**
142 * @return the content type of this stream
143 *
144 * @see #FORMAT_UNKNOWN
145 * @see #FORMAT_VORBIS
146 * @see #FORMAT_FLAC
147 * @see #FORMAT_THEORA
148 */
149
150 public String getFormat();
151} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/LogicalOggStreamImpl.java b/songdbj/de/jarnbjo/ogg/LogicalOggStreamImpl.java
deleted file mode 100644
index 1a503e91ca..0000000000
--- a/songdbj/de/jarnbjo/ogg/LogicalOggStreamImpl.java
+++ /dev/null
@@ -1,213 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.3 2003/03/31 00:23:04 jarnbjo
25 * no message
26 *
27 * Revision 1.2 2003/03/16 01:11:26 jarnbjo
28 * no message
29 *
30 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
31 * no message
32 *
33 */
34
35package de.jarnbjo.ogg;
36
37import java.io.*;
38import java.util.*;
39
40public class LogicalOggStreamImpl implements LogicalOggStream {
41
42 private PhysicalOggStream source;
43 private int serialNumber;
44
45 private ArrayList pageNumberMapping=new ArrayList();
46 private ArrayList granulePositions=new ArrayList();
47
48 private int pageIndex=0;
49 private OggPage currentPage;
50 private int currentSegmentIndex;
51
52 private boolean open=true;
53
54 private String format=FORMAT_UNKNOWN;
55
56 public LogicalOggStreamImpl(PhysicalOggStream source, int serialNumber) {
57 this.source=source;
58 this.serialNumber=serialNumber;
59 }
60
61 public void addPageNumberMapping(int physicalPageNumber) {
62 pageNumberMapping.add(new Integer(physicalPageNumber));
63 }
64
65 public void addGranulePosition(long granulePosition) {
66 granulePositions.add(new Long(granulePosition));
67 }
68
69 public synchronized void reset() throws OggFormatException, IOException {
70 currentPage=null;
71 currentSegmentIndex=0;
72 pageIndex=0;
73 }
74
75 public synchronized OggPage getNextOggPage() throws EndOfOggStreamException, OggFormatException, IOException {
76 if(source.isSeekable()) {
77 currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
78 }
79 else {
80 currentPage=source.getOggPage(-1);
81 }
82 return currentPage;
83 }
84
85 public synchronized byte[] getNextOggPacket() throws EndOfOggStreamException, OggFormatException, IOException {
86 ByteArrayOutputStream res=new ByteArrayOutputStream();
87 int segmentLength=0;
88
89 if(currentPage==null) {
90 currentPage=getNextOggPage();
91 }
92
93 do {
94 if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
95 currentSegmentIndex=0;
96
97 if(!currentPage.isEos()) {
98 if(source.isSeekable() && pageNumberMapping.size()<=pageIndex) {
99 while(pageNumberMapping.size()<=pageIndex+10) {
100 try {
101 Thread.sleep(1000);
102 }
103 catch (InterruptedException ex) {
104 }
105 }
106 }
107 currentPage=getNextOggPage();
108
109 if(res.size()==0 && currentPage.isContinued()) {
110 boolean done=false;
111 while(!done) {
112 if(currentPage.getSegmentLengths()[currentSegmentIndex++]!=255) {
113 done=true;
114 }
115 if(currentSegmentIndex>currentPage.getSegmentTable().length) {
116 currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
117 }
118 }
119 }
120 }
121 else {
122 throw new EndOfOggStreamException();
123 }
124 }
125 segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
126 res.write(currentPage.getData(), currentPage.getSegmentOffsets()[currentSegmentIndex], segmentLength);
127 currentSegmentIndex++;
128 } while(segmentLength==255);
129
130 return res.toByteArray();
131 }
132
133 public boolean isOpen() {
134 return open;
135 }
136
137 public void close() throws IOException {
138 open=false;
139 }
140
141 public long getMaximumGranulePosition() {
142 Long mgp=(Long)granulePositions.get(granulePositions.size()-1);
143 return mgp.longValue();
144 }
145
146 public synchronized long getTime() {
147 return currentPage!=null?currentPage.getAbsoluteGranulePosition():-1;
148 }
149
150 public synchronized void setTime(long granulePosition) throws IOException {
151
152 int page=0;
153 for(page=0; page<granulePositions.size(); page++) {
154 Long gp=(Long)granulePositions.get(page);
155 if(gp.longValue()>granulePosition) {
156 break;
157 }
158 }
159
160 pageIndex=page;
161 currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
162 currentSegmentIndex=0;
163 int segmentLength=0;
164 do {
165 if(currentSegmentIndex>=currentPage.getSegmentOffsets().length) {
166 currentSegmentIndex=0;
167 if(pageIndex>=pageNumberMapping.size()) {
168 throw new EndOfOggStreamException();
169 }
170 currentPage=source.getOggPage(((Integer)pageNumberMapping.get(pageIndex++)).intValue());
171 }
172 segmentLength=currentPage.getSegmentLengths()[currentSegmentIndex];
173 currentSegmentIndex++;
174 } while(segmentLength==255);
175 }
176
177 public void checkFormat(OggPage page) {
178 byte[] data=page.getData();
179
180 if(data.length>=7 &&
181 data[1]==0x76 &&
182 data[2]==0x6f &&
183 data[3]==0x72 &&
184 data[4]==0x62 &&
185 data[5]==0x69 &&
186 data[6]==0x73) {
187
188 format=FORMAT_VORBIS;
189 }
190 else if(data.length>=7 &&
191 data[1]==0x74 &&
192 data[2]==0x68 &&
193 data[3]==0x65 &&
194 data[4]==0x6f &&
195 data[5]==0x72 &&
196 data[6]==0x61) {
197
198 format=FORMAT_THEORA;
199 }
200 else if (data.length==4 &&
201 data[0]==0x66 &&
202 data[1]==0x4c &&
203 data[2]==0x61 &&
204 data[3]==0x43) {
205
206 format=FORMAT_FLAC;
207 }
208 }
209
210 public String getFormat() {
211 return format;
212 }
213} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/OggFormatException.java b/songdbj/de/jarnbjo/ogg/OggFormatException.java
deleted file mode 100644
index a6b2466b92..0000000000
--- a/songdbj/de/jarnbjo/ogg/OggFormatException.java
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.2 2005/02/09 23:10:47 shred
22 * Serial UID für jarnbjo
23 *
24 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
25 * First Import
26 *
27 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
28 * no message
29 *
30 */
31
32package de.jarnbjo.ogg;
33
34import java.io.IOException;
35
36/**
37 * Exception thrown when trying to read a corrupted Ogg stream.
38 */
39
40public class OggFormatException extends IOException {
41 private static final long serialVersionUID = 3544953238333175349L;
42
43 public OggFormatException() {
44 super();
45 }
46
47 public OggFormatException(String message) {
48 super(message);
49 }
50} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/OggPage.java b/songdbj/de/jarnbjo/ogg/OggPage.java
deleted file mode 100644
index cc965cc7a9..0000000000
--- a/songdbj/de/jarnbjo/ogg/OggPage.java
+++ /dev/null
@@ -1,431 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.3 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 * Revision 1.2 2003/03/31 00:23:04 jarnbjo
28 * no message
29 *
30 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
31 * no message
32 *
33 */
34
35package de.jarnbjo.ogg;
36
37import java.io.*;
38
39import de.jarnbjo.util.io.*;
40
41/**
42 * <p>An instance of this class represents an ogg page read from an ogg file
43 * or network stream. It has no public constructor, but instances can be
44 * created by the <code>create</code> methods, supplying a JMF stream or
45 * a <code>RandomAccessFile</code>
46 * which is positioned at the beginning of an Ogg page.</p>
47 *
48 * <p>Furtheron, the class provides methods for accessing the raw page data,
49 * as well as data attributes like segmenting information, sequence number,
50 * stream serial number, chechsum and wether this page is the beginning or
51 * end of a logical bitstream (BOS, EOS) and if the page data starts with a
52 * continued packet or a fresh data packet.</p>
53 */
54
55public class OggPage {
56
57 private int version;
58 private boolean continued, bos, eos;
59 private long absoluteGranulePosition;
60 private int streamSerialNumber, pageSequenceNumber, pageCheckSum;
61 private int[] segmentOffsets;
62 private int[] segmentLengths;
63 private int totalLength;
64 private byte[] header, segmentTable, data;
65
66 protected OggPage() {
67 }
68
69 private OggPage(
70 int version,
71 boolean continued,
72 boolean bos,
73 boolean eos,
74 long absoluteGranulePosition,
75 int streamSerialNumber,
76 int pageSequenceNumber,
77 int pageCheckSum,
78 int[] segmentOffsets,
79 int[] segmentLengths,
80 int totalLength,
81 byte[] header,
82 byte[] segmentTable,
83 byte[] data) {
84
85 this.version=version;
86 this.continued=continued;
87 this.bos=bos;
88 this.eos=eos;
89 this.absoluteGranulePosition=absoluteGranulePosition;
90 this.streamSerialNumber=streamSerialNumber;
91 this.pageSequenceNumber=pageSequenceNumber;
92 this.pageCheckSum=pageCheckSum;
93 this.segmentOffsets=segmentOffsets;
94 this.segmentLengths=segmentLengths;
95 this.totalLength=totalLength;
96 this.header=header;
97 this.segmentTable=segmentTable;
98 this.data=data;
99 }
100
101 /**
102 * this method equals to create(RandomAccessFile source, false)
103 *
104 * @see #create(RandomAccessFile, boolean)
105 */
106
107 public static OggPage create(RandomAccessFile source) throws IOException, EndOfOggStreamException, OggFormatException {
108 return create(source, false);
109 }
110
111 /**
112 * This method is called to read data from the current position in the
113 * specified RandomAccessFile and create a new OggPage instance based on the data
114 * read. If the parameter <code>skipData</code> is set to <code>true</code>,
115 * the actual page segments (page data) is skipped and not read into
116 * memory. This mode is useful when scanning through an ogg file to build
117 * a seek table.
118 *
119 * @param source the source from which the ogg page is generated
120 * @param skipData if set to <code>true</code>, the actual page data is not read into memory
121 * @return an ogg page created by reading data from the specified source, starting at the current position
122 * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
123 * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
124 * @throws IOException if some other I/O error is detected when reading from the source
125 *
126 * @see #create(RandomAccessFile)
127 */
128
129 public static OggPage create(RandomAccessFile source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
130 return create((Object)source, skipData);
131 }
132
133 /**
134 * this method equals to create(InputStream source, false)
135 *
136 * @see #create(InputStream, boolean)
137 */
138
139 public static OggPage create(InputStream source) throws IOException, EndOfOggStreamException, OggFormatException {
140 return create(source, false);
141 }
142
143 /**
144 * This method is called to read data from the current position in the
145 * specified InpuStream and create a new OggPage instance based on the data
146 * read. If the parameter <code>skipData</code> is set to <code>true</code>,
147 * the actual page segments (page data) is skipped and not read into
148 * memory. This mode is useful when scanning through an ogg file to build
149 * a seek table.
150 *
151 * @param source the source from which the ogg page is generated
152 * @param skipData if set to <code>true</code>, the actual page data is not read into memory
153 * @return an ogg page created by reading data from the specified source, starting at the current position
154 * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
155 * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
156 * @throws IOException if some other I/O error is detected when reading from the source
157 *
158 * @see #create(InputStream)
159 */
160
161 public static OggPage create(InputStream source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
162 return create((Object)source, skipData);
163 }
164
165 /**
166 * this method equals to create(byte[] source, false)
167 *
168 * @see #create(byte[], boolean)
169 */
170
171 public static OggPage create(byte[] source) throws IOException, EndOfOggStreamException, OggFormatException {
172 return create(source, false);
173 }
174
175 /**
176 * This method is called to
177 * create a new OggPage instance based on the specified byte array.
178 *
179 * @param source the source from which the ogg page is generated
180 * @param skipData if set to <code>true</code>, the actual page data is not read into memory
181 * @return an ogg page created by reading data from the specified source, starting at the current position
182 * @throws FormatException if the data read from the specified source is not matching the specification for an ogg page
183 * @throws EndOfStreamException if it is not possible to read an entire ogg page from the specified source
184 * @throws IOException if some other I/O error is detected when reading from the source
185 *
186 * @see #create(byte[])
187 */
188
189 public static OggPage create(byte[] source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
190 return create((Object)source, skipData);
191 }
192
193 private static OggPage create(Object source, boolean skipData) throws IOException, EndOfOggStreamException, OggFormatException {
194
195 try {
196 int sourceOffset=27;
197
198 byte[] header=new byte[27];
199 if(source instanceof RandomAccessFile) {
200 RandomAccessFile raf=(RandomAccessFile)source;
201 if(raf.getFilePointer()==raf.length()) {
202 return null;
203 }
204 raf.readFully(header);
205 }
206 else if(source instanceof InputStream) {
207 readFully((InputStream)source, header);
208 }
209 else if(source instanceof byte[]) {
210 System.arraycopy((byte[])source, 0, header, 0, 27);
211 }
212
213 BitInputStream bdSource=new ByteArrayBitInputStream(header);
214
215 int capture=bdSource.getInt(32);
216
217 if(capture!=0x5367674f) {
218 //throw new FormatException("Ogg page does not start with 'OggS' (0x4f676753)");
219
220 /*
221 ** This condition is IMHO an error, but older Ogg files often contain
222 ** pages with a different capture than OggS. I am not sure how to
223 ** manage these pages, but the decoder seems to work properly, if
224 ** the incorrect capture is simply ignored.
225 */
226
227 String cs=Integer.toHexString(capture);
228 while(cs.length()<8) {
229 cs="0"+cs;
230 }
231 cs=cs.substring(6, 8)+cs.substring(4, 6)+cs.substring(2, 4)+cs.substring(0, 2);
232 char c1=(char)(Integer.valueOf(cs.substring(0, 2), 16).intValue());
233 char c2=(char)(Integer.valueOf(cs.substring(2, 4), 16).intValue());
234 char c3=(char)(Integer.valueOf(cs.substring(4, 6), 16).intValue());
235 char c4=(char)(Integer.valueOf(cs.substring(6, 8), 16).intValue());
236 System.out.println("Ogg packet header is 0x"+cs+" ("+c1+c2+c3+c4+"), should be 0x4f676753 (OggS)");
237 }
238
239 int version=bdSource.getInt(8);
240 byte tmp=(byte)bdSource.getInt(8);
241 boolean bf1=(tmp&1)!=0;
242 boolean bos=(tmp&2)!=0;
243 boolean eos=(tmp&4)!=0;
244 long absoluteGranulePosition=bdSource.getLong(64);
245 int streamSerialNumber=bdSource.getInt(32);
246 int pageSequenceNumber=bdSource.getInt(32);
247 int pageCheckSum=bdSource.getInt(32);
248 int pageSegments=bdSource.getInt(8);
249
250 //System.out.println("OggPage: "+streamSerialNumber+" / "+absoluteGranulePosition+" / "+pageSequenceNumber);
251
252 int[] segmentOffsets=new int[pageSegments];
253 int[] segmentLengths=new int[pageSegments];
254 int totalLength=0;
255
256 byte[] segmentTable=new byte[pageSegments];
257 byte[] tmpBuf=new byte[1];
258
259 for(int i=0; i<pageSegments; i++) {
260 int l=0;
261 if(source instanceof RandomAccessFile) {
262 l=((int)((RandomAccessFile)source).readByte()&0xff);
263 }
264 else if(source instanceof InputStream) {
265 l=(int)((InputStream)source).read();
266 }
267 else if(source instanceof byte[]) {
268 l=(int)((byte[])source)[sourceOffset++];
269 l&=255;
270 }
271 segmentTable[i]=(byte)l;
272 segmentLengths[i]=l;
273 segmentOffsets[i]=totalLength;
274 totalLength+=l;
275 }
276
277 byte[] data=null;
278
279 if(!skipData) {
280
281 //System.out.println("createPage: "+absoluteGranulePosition*1000/44100);
282
283 data=new byte[totalLength];
284 //source.read(data, 0, totalLength);
285 if(source instanceof RandomAccessFile) {
286 ((RandomAccessFile)source).readFully(data);
287 }
288 else if(source instanceof InputStream) {
289 readFully((InputStream)source, data);
290 }
291 else if(source instanceof byte[]) {
292 System.arraycopy(source, sourceOffset, data, 0, totalLength);
293 }
294 }
295
296 return new OggPage(version, bf1, bos, eos, absoluteGranulePosition, streamSerialNumber, pageSequenceNumber, pageCheckSum, segmentOffsets, segmentLengths, totalLength, header, segmentTable, data);
297 }
298 catch(EOFException e) {
299 throw new EndOfOggStreamException();
300 }
301 }
302
303 private static void readFully(InputStream source, byte[] buffer) throws IOException {
304 int total=0;
305 while(total<buffer.length) {
306 int read=source.read(buffer, total, buffer.length-total);
307 if(read==-1) {
308 throw new EndOfOggStreamException();
309 }
310 total+=read;
311 }
312 }
313
314 /**
315 * Returns the absolute granule position of the last complete
316 * packet contained in this Ogg page, or -1 if the page contains a single
317 * packet, which is not completed on this page. For pages containing Vorbis
318 * data, this value is the sample index within the Vorbis stream. The Vorbis
319 * stream does not necessarily start with sample index 0.
320 *
321 * @return the absolute granule position of the last packet completed on
322 * this page
323 */
324
325
326 public long getAbsoluteGranulePosition() {
327 return absoluteGranulePosition;
328 }
329
330 /**
331 * Returns the stream serial number of this ogg page.
332 *
333 * @return this page's serial number
334 */
335
336 public int getStreamSerialNumber() {
337 return streamSerialNumber;
338 }
339
340 /**
341 * Return the sequnce number of this ogg page.
342 *
343 * @return this page's sequence number
344 */
345
346 public int getPageSequenceNumber() {
347 return pageSequenceNumber;
348 }
349
350 /**
351 * Return the check sum of this ogg page.
352 *
353 * @return this page's check sum
354 */
355
356 public int getPageCheckSum() {
357 return pageCheckSum;
358 }
359
360 /**
361 * @return the total number of bytes in the page data
362 */
363
364
365 public int getTotalLength() {
366 if(data!=null) {
367 return 27+segmentTable.length+data.length;
368 }
369 else {
370 return totalLength;
371 }
372 }
373
374 /**
375 * @return a ByteBuffer containing the page data
376 */
377
378
379 public byte[] getData() {
380 return data;
381 }
382
383 public byte[] getHeader() {
384 return header;
385 }
386
387 public byte[] getSegmentTable() {
388 return segmentTable;
389 }
390
391 public int[] getSegmentOffsets() {
392 return segmentOffsets;
393 }
394
395 public int[] getSegmentLengths() {
396 return segmentLengths;
397 }
398
399 /**
400 * @return <code>true</code> if this page begins with a continued packet
401 */
402
403 public boolean isContinued() {
404 return continued;
405 }
406
407 /**
408 * @return <code>true</code> if this page begins with a fresh packet
409 */
410
411 public boolean isFresh() {
412 return !continued;
413 }
414
415 /**
416 * @return <code>true</code> if this page is the beginning of a logical stream
417 */
418
419 public boolean isBos() {
420 return bos;
421 }
422
423 /**
424 * @return <code>true</code> if this page is the end of a logical stream
425 */
426
427 public boolean isEos() {
428 return eos;
429 }
430
431} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/OnDemandUrlStream.java b/songdbj/de/jarnbjo/ogg/OnDemandUrlStream.java
deleted file mode 100644
index 98159c4e7c..0000000000
--- a/songdbj/de/jarnbjo/ogg/OnDemandUrlStream.java
+++ /dev/null
@@ -1,127 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.1 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 * Revision 1.1 2003/03/31 00:23:04 jarnbjo
28 * no message
29 *
30 */
31
32package de.jarnbjo.ogg;
33
34import java.io.*;
35import java.net.*;
36import java.util.*;
37
38/**
39 * Implementation of the <code>PhysicalOggStream</code> interface for reading
40 * an Ogg stream from a URL. This class performs
41 * no internal caching, and will not read data from the network before
42 * requested to do so. It is intended to be used in non-realtime applications
43 * like file download managers or similar.
44 */
45
46public class OnDemandUrlStream implements PhysicalOggStream {
47
48 private boolean closed=false;
49 private URLConnection source;
50 private InputStream sourceStream;
51 private Object drainLock=new Object();
52 private LinkedList pageCache=new LinkedList();
53 private long numberOfSamples=-1;
54 private int contentLength=0;
55 private int position=0;
56
57 private HashMap logicalStreams=new HashMap();
58 private OggPage firstPage;
59
60 private static final int PAGECACHE_SIZE = 20;
61
62 public OnDemandUrlStream(URL source) throws OggFormatException, IOException {
63 this.source=source.openConnection();
64 this.sourceStream=this.source.getInputStream();
65
66 contentLength=this.source.getContentLength();
67
68 firstPage=OggPage.create(sourceStream);
69 position+=firstPage.getTotalLength();
70 LogicalOggStreamImpl los=new LogicalOggStreamImpl(this, firstPage.getStreamSerialNumber());
71 logicalStreams.put(new Integer(firstPage.getStreamSerialNumber()), los);
72 los.checkFormat(firstPage);
73 }
74
75 public Collection getLogicalStreams() {
76 return logicalStreams.values();
77 }
78
79 public boolean isOpen() {
80 return !closed;
81 }
82
83 public void close() throws IOException {
84 closed=true;
85 sourceStream.close();
86 }
87
88 public int getContentLength() {
89 return contentLength;
90 }
91
92 public int getPosition() {
93 return position;
94 }
95
96 int pageNumber=2;
97
98 public OggPage getOggPage(int index) throws IOException {
99 if(firstPage!=null) {
100 OggPage tmp=firstPage;
101 firstPage=null;
102 return tmp;
103 }
104 else {
105 OggPage page=OggPage.create(sourceStream);
106 position+=page.getTotalLength();
107 return page;
108 }
109 }
110
111 private LogicalOggStream getLogicalStream(int serialNumber) {
112 return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
113 }
114
115 public void setTime(long granulePosition) throws IOException {
116 throw new UnsupportedOperationException("Method not supported by this class");
117 }
118
119 /**
120 * @return always <code>false</code>
121 */
122
123 public boolean isSeekable() {
124 return false;
125 }
126
127} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/PhysicalOggStream.java b/songdbj/de/jarnbjo/ogg/PhysicalOggStream.java
deleted file mode 100644
index 5f342a38b7..0000000000
--- a/songdbj/de/jarnbjo/ogg/PhysicalOggStream.java
+++ /dev/null
@@ -1,124 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.3 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 * Revision 1.2 2003/03/31 00:23:04 jarnbjo
28 * no message
29 *
30 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
31 * no message
32 *
33 */
34
35package de.jarnbjo.ogg;
36
37import java.io.IOException;
38import java.util.Collection;
39
40/**
41 * Interface providing access to a physical Ogg stream. Typically this is
42 * a file.
43 */
44
45public interface PhysicalOggStream {
46
47 /**
48 * Returns a collection of objects implementing <code>LogicalOggStream</code>
49 * for accessing the separate logical streams within this physical Ogg stream.
50 *
51 * @return a collection of objects implementing <code>LogicalOggStream</code>
52 * which are representing the logical streams contained within this
53 * physical stream
54 *
55 * @see LogicalOggStream
56 */
57
58 public Collection getLogicalStreams();
59
60 /**
61 * Return the Ogg page with the absolute index <code>index</code>,
62 * independent from the logical structure of this stream or if the
63 * index parameter is -1, the next Ogg page is returned.
64 * This method should only be used by implementations of <code>LogicalOggStream</code>
65 * to access the raw pages.
66 *
67 * @param index the absolute index starting from 0 at the beginning of
68 * the file or stream or -1 to get the next page in a non-seekable
69 * stream
70 *
71 * @return the Ogg page with the physical absolute index <code>index</code>
72 *
73 * @throws OggFormatException if the ogg stream is corrupted
74 * @throws IOException if some other IO error occurs
75 */
76
77 public OggPage getOggPage(int index) throws OggFormatException, IOException;
78
79 /**
80 * Checks if this stream is open for reading.
81 *
82 * @return <code>true</code> if this stream is open for reading,
83 * <code>false</code> otherwise
84 */
85
86 public boolean isOpen();
87
88 /**
89 * Closes this stream. After invoking this method, no further access
90 * to the streams data is possible.
91 *
92 * @throws IOException
93 */
94
95 public void close() throws IOException;
96
97 /**
98 * Sets this stream's (and its logical stream's) position to the granule
99 * position. The next packet read from any logical stream will be the
100 * first packet beginning on the first page with a granule position higher
101 * than the argument.<br><br>
102 *
103 * At the moment, this method only works correctly for Ogg files with
104 * a single logical Vorbis stream, and due to the different interpretations
105 * of the granule position, depending on mixed content, this method will
106 * never be able to work for mixed streams. Chained and interleaved streams are
107 * also not yet supported. Actually, this method is only a hack to support
108 * seeking from JMF, but may of course be abused otherwise too :)
109 *
110 * @param granulePosition
111 *
112 * @throws OggFormatException if the ogg stream is corrupted
113 * @throws IOException if some other IO error occurs
114 */
115
116 public void setTime(long granulePosition) throws OggFormatException, IOException;
117
118 /**
119 * @return <code>true</code> if the stream is seekable, <code>false</code>
120 * otherwise
121 */
122
123 public boolean isSeekable();
124} \ No newline at end of file
diff --git a/songdbj/de/jarnbjo/ogg/UncachedUrlStream.java b/songdbj/de/jarnbjo/ogg/UncachedUrlStream.java
deleted file mode 100644
index a07f0ac00e..0000000000
--- a/songdbj/de/jarnbjo/ogg/UncachedUrlStream.java
+++ /dev/null
@@ -1,207 +0,0 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.1 2003/04/10 19:48:22 jarnbjo
25 * no message
26 *
27 */
28
29package de.jarnbjo.ogg;
30
31import java.io.*;
32import java.net.*;
33import java.util.*;
34
35/**
36 * Implementation of the <code>PhysicalOggStream</code> interface for reading
37 * an Ogg stream from a URL. This class performs only the necessary caching
38 * to provide continous playback. Seeking within the stream is not supported.
39 */
40
41public class UncachedUrlStream implements PhysicalOggStream {
42
43 private boolean closed=false;
44 private URLConnection source;
45 private InputStream sourceStream;
46 private Object drainLock=new Object();
47 private LinkedList pageCache=new LinkedList();
48 private long numberOfSamples=-1;
49
50 private HashMap logicalStreams=new HashMap();
51
52 private LoaderThread loaderThread;
53
54 private static final int PAGECACHE_SIZE = 10;
55
56 /** Creates an instance of the <code>PhysicalOggStream</code> interface
57 * suitable for reading an Ogg stream from a URL.
58 */
59
60 public UncachedUrlStream(URL source) throws OggFormatException, IOException {
61
62 this.source=source.openConnection();
63 this.sourceStream=this.source.getInputStream();
64
65 loaderThread=new LoaderThread(sourceStream, pageCache);
66 new Thread(loaderThread).start();
67
68 while(!loaderThread.isBosDone() || pageCache.size()<PAGECACHE_SIZE) {
69 try {
70 Thread.sleep(200);
71 }
72 catch (InterruptedException ex) {
73 }
74 //System.out.print("caching "+pageCache.size()+"/"+PAGECACHE_SIZE+" pages\r");
75 }
76 //System.out.println();
77 }
78
79 public Collection getLogicalStreams() {
80 return logicalStreams.values();
81 }
82
83 public boolean isOpen() {
84 return !closed;
85 }
86
87 public void close() throws IOException {
88 closed=true;
89 sourceStream.close();
90 }
91
92 /*
93 public long getCacheLength() {
94 return cacheLength;
95 }
96 */
97
98 /*
99 private OggPage getNextPage() throws EndOfOggStreamException, IOException, OggFormatException {
100 return getNextPage(false);
101 }
102
103 private OggPage getNextPage(boolean skipData) throws EndOfOggStreamException, IOException, OggFormatException {
104 return OggPage.create(sourceStream, skipData);
105 }
106 */
107
108 public OggPage getOggPage(int index) throws IOException {
109 while(pageCache.size()==0) {
110 try {
111 Thread.sleep(100);
112 }
113 catch (InterruptedException ex) {
114 }
115 }
116 synchronized(drainLock) {
117 //OggPage page=(OggPage)pageCache.getFirst();
118 //pageCache.removeFirst();
119 //return page;
120 return (OggPage)pageCache.removeFirst();
121 }
122 }
123
124 private LogicalOggStream getLogicalStream(int serialNumber) {
125 return (LogicalOggStream)logicalStreams.get(new Integer(serialNumber));
126 }
127
128 public void setTime(long granulePosition) throws IOException {
129 throw new UnsupportedOperationException("Method not supported by this class");
130 }
131
132 public class LoaderThread implements Runnable {
133
134 private InputStream source;
135 private LinkedList pageCache;
136 private RandomAccessFile drain;
137 private byte[] memoryCache;
138
139 private boolean bosDone=false;
140
141 private int pageNumber;
142
143 public LoaderThread(InputStream source, LinkedList pageCache) {
144 this.source=source;
145 this.pageCache=pageCache;
146 }
147
148 public void run() {
149 try {
150 boolean eos=false;
151 byte[] buffer=new byte[8192];
152 while(!eos) {
153 OggPage op=OggPage.create(source);
154 synchronized (drainLock) {
155 pageCache.add(op);
156 }
157
158 if(!op.isBos()) {
159 bosDone=true;
160 }
161 if(op.isEos()) {
162 eos=true;
163 }
164
165 LogicalOggStreamImpl los=(LogicalOggStreamImpl)getLogicalStream(op.getStreamSerialNumber());
166 if(los==null) {
167 los=new LogicalOggStreamImpl(UncachedUrlStream.this, op.getStreamSerialNumber());
168 logicalStreams.put(new Integer(op.getStreamSerialNumber()), los);
169 los.checkFormat(op);
170 }
171
172 //los.addPageNumberMapping(pageNumber);
173 //los.addGranulePosition(op.getAbsoluteGranulePosition());
174
175 pageNumber++;
176
177 while(pageCache.size()>PAGECACHE_SIZE) {
178 try {
179 Thread.sleep(200);
180 }
181 catch (InterruptedException ex) {
182 }
183 }
184 }
185 }
186 catch(EndOfOggStreamException e) {
187 // ok
188 }
189 catch(IOException e) {
190 e.printStackTrace();
191 }
192 }
193
194 public boolean isBosDone() {
195 return bosDone;
196 }
197 }
198
199 /**
200 * @return always <code>false</code>
201 */
202
203 public boolean isSeekable() {
204 return false;
205 }
206
207} \ No newline at end of file