/*
* Copyright 2007 Sun Microsystems, Inc.
*
* This file is part of jVoiceBridge.
*
* jVoiceBridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation and distributed hereunder
* to you.
*
* jVoiceBridge is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied this
* code.
*/
package com.sun.voip;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
/**
* Abstract superclass of audio sources that read data from a file.
* @author jkaplan
*/
public abstract class FileAudioSource implements AudioSource {
private static Map<String, Class<? extends FileAudioSource>> types =
new HashMap<String, Class<? extends FileAudioSource>>();
// initialize the map
static {
types.put(".au", DotAuAudioSource.class);
}
/**
* Get a file audio source for the given file. This looks at
* the extension of the source and decides which AudioSource type
* to load.
* <p>
* All audio sources are expected to have a constructor that takes
* the path as an argument and throws an IOException in the case of
* an error.
*
* @param path the path to the audio file
* @return a FileAudioSource for playing the path or null if there is
* an error finding an audio source for the given type
*/
public static FileAudioSource getAudioSource(String path) {
// get the extension
int extIdx = path.lastIndexOf(".");
if (extIdx == -1) {
Logger.error("Unable to determine extension of " + path);
return null;
}
String ext = path.substring(extIdx);
Class<? extends FileAudioSource> clazz = types.get(ext);
if (clazz == null) {
Logger.error("No player for extension " + ext);
return null;
}
try {
Constructor<? extends FileAudioSource> c =
clazz.getConstructor(String.class);
return c.newInstance(path);
} catch (Exception e) {
if (e instanceof IOException) {
Logger.println("getAudioSource for " + path + " got IOException: "
+ e.getMessage());
} else {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.exception("Error instantiating class " + clazz, e);
}
}
return null;
}
}
/**
* Register a new type of audio source. There can be one
* decoder for each audio file type, identified by extension.
* @param extension the extension of files to decode, e.g. ".au"
* @param clazz the class to use to decode the given audio source
*/
public static void registerAudioSource(String extension,
Class<? extends FileAudioSource> clazz)
{
types.put(extension, clazz);
}
/**
* Load the audio source from the given path. The path may be either
* in the jar file which FileAudioSource is read from or in the
* file system. The jar file is checked first.
* @param path the path to load from
* @return an InputStream read from the given path
* @throws IOException if there is an error loading the stream
*/
protected InputStream getInputStream(String path) throws IOException {
/*
* replace back slashes with slash.
*/
path = path.replaceAll(Matcher.quoteReplacement("\\"), "/");
// try to load the stream as a resource
InputStream in = getClass().getResourceAsStream(path);
if (in != null) {
in = new BufferedInputStream(in, 16*1024);
if (Logger.logLevel >= Logger.LOG_MOREINFO) {
Logger.println("Successfully opened as stream '" + path + "'");
}
} else {
// no luck, try the file system
if (File.separator.equals("\\")) {
/*
* Replace slash with back slash
*/
path = path.replaceAll("/", Matcher.quoteReplacement("\\"));
}
if (Logger.logLevel >= Logger.LOG_MOREINFO) {
Logger.println("can't read audio resource, trying as a file: "
+ path);
}
try {
in = new FileInputStream(path);
} catch (FileNotFoundException e) {
throw new IOException("DotAuAudioSource error " + path + ": " +
e.getMessage());
}
}
return in;
}
}