Source code: jreceiver/server/stream/capture/MusicInputStreamFactory.java
1 /* $Header: /cvsroot/jreceiver/jreceiver/src/jreceiver/server/stream/capture/MusicInputStreamFactory.java,v 1.8 2002/12/29 00:44:07 reedesau Exp $ */
2
3 /*
4 JRECEIVER MODIFIED BSD LICENSE
5
6 Copyright (c) 2001, Reed Esau (reed.esau@pobox.com) All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11
12 Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14
15 Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
18
19 Neither the name of the JReceiver Project
20 (http://jreceiver.sourceforge.net) nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 package jreceiver.server.stream.capture;
38
39 import java.io.*;
40 import java.net.URL;
41 import java.util.Hashtable;
42 import java.util.LinkedList;
43 import java.util.List;
44 import java.util.ListIterator;
45
46 import org.apache.commons.logging.*;
47
48 /**
49 * This provides support for getting MusicInputStream objects. It stores them
50 * and then returns the correct object at a later date. It can store multiple
51 * MusicInputStream objects for a single URL -- think multiple players playing
52 * the same stream. It serves up the object that has a correct offset. This is
53 * not quite the optimal strategy -- it probably ought to preferentially return the stream
54 * where the requested offset is at the 'end'.
55 *
56 * @author Philip Gladstone
57 * @version $Revision: 1.8 $ $Date: 2002/12/29 00:44:07 $
58 */
59 public final class MusicInputStreamFactory {
60
61 /**
62 * A table of current MusicInputStream objects -- indexed by URL
63 */
64 private static Hashtable table = new Hashtable();
65
66 /**
67 * Obtains a MusicInputStream object for the requested URL
68 * at the requested position. This allows us to disabiguate
69 * two people asking for the same stream.
70 *
71 * @param url the requested URL
72 * @param pos the requested byte offset.
73 * @param mimeType the required mime type (or null for native)
74 * @returns the requested MusicInputStream object or null if not possible
75 * @exception IOException if the MusicInputStream object cannot be created.
76 */
77
78 public static synchronized MusicInputStream getStream(URL url, int pos, String mimeType)
79 throws IOException
80 {
81 return getStream(url, pos, mimeType, null);
82 }
83
84 /**
85 * Obtains a MusicInputStream object for the requested URL
86 * at the requested position. This allows us to disabiguate
87 * two people asking for the same stream.
88 *
89 * @param url the requested URL
90 * @param pos the requested byte offset.
91 * @param mimeType the required mime type (or null for native)
92 * @param srcMimeType the type of the source (in case we cannot figure it out)
93 * @returns the requested MusicInputStream object or null if not possible
94 * @exception IOException if the MusicInputStream object cannot be created.
95 */
96
97 public static synchronized MusicInputStream getStream(URL url, int pos, String mimeType, String srcMimeType)
98 throws IOException
99 {
100 MusicInputStream s = null;
101
102 List l;
103
104 l = (List) table.get(url);
105
106 if (l != null) {
107 /* See if we can find our stream */
108 ListIterator li;
109
110 for (li = l.listIterator(0); li.hasNext(); ) {
111 s = (MusicInputStream) li.next();
112
113 if (s.posInRange(pos)) {
114 s.seek(pos);
115 break;
116 }
117 s = null;
118 }
119 }
120 if (s == null) {
121 if (log.isDebugEnabled())
122 log.debug("Creating new MusicInputStream object for " + url.toString() + "@" + pos);
123 s = new MusicInputStream(url, pos, mimeType, srcMimeType);
124 if (s != null) {
125 if (l == null) {
126 l = new LinkedList();
127 table.put(url, l);
128 }
129 l.add(0, s); // Put new object at front
130 }
131 }
132 if (s == null) {
133 if (log.isDebugEnabled())
134 log.debug("Failed to find MusicInputStream object for " + url.toString() + " with offset " + pos);
135 } else {
136 s.lock();
137 }
138
139 return s;
140 }
141
142 public static synchronized void removeStream(URL url, int pos)
143 {
144 List l;
145
146 l = (List) table.get(url);
147
148 if (l != null) {
149 /* See if we can find our stream */
150 ListIterator li;
151
152 for (li = l.listIterator(0); li.hasNext(); ) {
153 MusicInputStream s = (MusicInputStream) li.next();
154
155 if (s.posInRange(pos)) {
156 li.remove();
157 s.shutdown();
158 break;
159 }
160 }
161 if (l.isEmpty()) {
162 table.remove(url);
163 }
164 }
165 }
166
167 /**
168 * Removes a music stream from the table. This is only called by the
169 * MusicInputStream object itself on a timeout.
170 *
171 * @param url the URL of the stream
172 * @param stream the MusicInputStream object itself
173 */
174 public static synchronized void removeMusicInputStream(URL url, MusicInputStream stream)
175 {
176 List l;
177
178 l = (List) table.get(url);
179
180 if (l != null) {
181 /* See if we can find our stream */
182 ListIterator li;
183
184 for (li = l.listIterator(0); li.hasNext(); ) {
185 MusicInputStream s = (MusicInputStream) li.next();
186
187 if (s == stream) {
188 if (log.isDebugEnabled())
189 log.debug(stream.toString() + ": Removing MusicInputStream object");
190 li.remove();
191 stream = null;
192 break;
193 }
194 }
195 if (l.isEmpty()) {
196 table.remove(url);
197 }
198 }
199 if (stream != null) {
200 if (log.isDebugEnabled())
201 log.debug(stream.toString() + ": Failed to remove MusicInputStream object");
202 }
203 }
204
205 /**
206 * logging object
207 */
208
209 protected static Log log = LogFactory.getLog(MusicInputStreamFactory.class);
210 }