/*
* PS3 Media Server, for streaming any medias to your PS3.
* Copyright (C) 2008 A.Brochard
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License only.
*
* This program 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.pms.formats;
import net.pms.configuration.RendererConfiguration;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.InputFile;
import net.pms.network.HTTPResource;
import net.pms.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.StringTokenizer;
/**
* Abstract class to store known information about a given format.
*/
public abstract class Format implements Cloneable {
private static final Logger logger = LoggerFactory.getLogger(Format.class);
private String icon = null;
protected int type = UNKNOWN;
protected Format secondaryFormat;
/**
* The extension or protocol that was matched for a
* particular filename or URL. Requires {@link #match(String)}
* to be called first.
*/
private String matchedExtension;
public enum Identifier {
AUDIO_AS_VIDEO,
DVRMS,
FLAC,
GIF,
ISO,
JPG,
M4A,
MKV,
MP3,
MPG,
OGG,
PNG,
RAW,
TIF,
WAV,
WEB,
CUSTOM
}
public static final int AUDIO = 1;
public static final int IMAGE = 2;
public static final int VIDEO = 4;
public static final int UNKNOWN = 8;
public static final int PLAYLIST = 16;
public static final int ISO = 32;
public int getType() {
return type;
}
/**
* Returns the extension or protocol that was matched
* for a particular filename or URL. Requires {@link #match(String)} to be
* called first.
*
* @return The matched extension or protocol.
*/
public String getMatchedExtension() {
return matchedExtension;
}
/**
* Sets the extension or protocol that was matched
* for a particular filename or URL.
*
* @param extension the extension or protocol that was matched.
* @since 1.90.0
*/
public void setMatchedExtension(String extension) {
matchedExtension = extension;
}
public Format getSecondaryFormat() {
return secondaryFormat;
}
public void setSecondaryFormat(Format secondaryFormat) {
this.secondaryFormat = secondaryFormat;
}
public void setType(int type) {
if (isUnknown()) {
this.type = type;
}
}
/**
* @deprecated Use {@link #getSupportedExtensions} instead.
*/
@Deprecated
public String[] getId() {
return getSupportedExtensions();
}
/**
* Returns a list of file extensions to use to identify
* a particular format e.g. "mp3" or "mpg". Extensions
* are expected to be in lower case. The default value is
* <code>null</code>, indicating no matching should be done
* by file extension.
*
* @return An array of extensions.
* @since 1.90.0
*/
public String[] getSupportedExtensions() {
return null;
}
/**
* @deprecated Use {@link #isCompatible(DLNAMediaInfo, RendererConfiguration)} instead.
* <p>
* Returns whether or not a format can be handled by the PS3 natively.
* This means the format can be streamed to PS3 instead of having to be
* transcoded.
*
* @return True if the format can be handled by PS3, false otherwise.
*/
@Deprecated
public abstract boolean ps3compatible();
/**
* Returns whether or not media can be handled by the renderer natively,
* based on the given media information and renderer. If the format can be
* streamed (as opposed to having to be transcoded), <code>true</code> will
* be returned.
*
* @param media
* The media information.
* @param renderer
* The renderer for which to check. If <code>null</code> is set
* as renderer, the default renderer configuration will be used.
*
* @return True if the format can be handled by the renderer, false
* otherwise.
*
* @since 1.50.1
*/
public boolean isCompatible(DLNAMediaInfo media, RendererConfiguration renderer) {
RendererConfiguration referenceRenderer;
if (renderer != null) {
// Use the provided renderer as reference
referenceRenderer = renderer;
} else {
// Use the default renderer as reference
referenceRenderer = RendererConfiguration.getDefaultConf();
}
// Let the renderer configuration decide on native compatibility
return referenceRenderer.isCompatible(media, this);
}
public abstract boolean transcodable();
public String mimeType() {
return HTTPResource.getDefaultMimeType(type);
}
public void setIcon(String filename) {
icon = filename;
}
public String getIcon() {
return icon;
}
/**
* Returns whether or not this format matches the supplied filename.
* Returns false if the filename is a URI, otherwise matches
* against the file extensions returned by {@link #getSupportedExtensions()}.
*
* @param filename the filename to match
* @return <code>true</code> if the format matches, <code>false</code> otherwise.
*/
public boolean match(String filename) {
if (filename == null) {
return false;
}
filename = filename.toLowerCase();
String[] supportedExtensions = getSupportedExtensions();
if (supportedExtensions != null) {
String protocol = FileUtil.getProtocol(filename);
if (protocol != null) { // URIs are handled by WEB.match
return false;
}
for (String extension : supportedExtensions) {
String ext = extension.toLowerCase();
if (filename.endsWith("." + ext)) {
setMatchedExtension(ext);
return true;
}
}
}
return false;
}
public boolean isVideo() {
return (type & VIDEO) == VIDEO;
}
public boolean isAudio() {
return (type & AUDIO) == AUDIO;
}
public boolean isImage() {
return (type & IMAGE) == IMAGE;
}
public boolean isUnknown() {
return (type & UNKNOWN) == UNKNOWN;
}
@Override
protected Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
logger.error(null, e);
}
return o;
}
public Format duplicate() {
return (Format) this.clone();
}
// method which allows us to fine tune parsing with different formats in the future
public void parse(DLNAMediaInfo media, InputFile file, int type) {
parse(media, file, type, null);
}
// 2010-02-03 now this is useful :p
public void parse(DLNAMediaInfo media, InputFile file, int type, RendererConfiguration renderer) {
if (renderer != null && renderer.isMediaParserV2()) {
renderer.getFormatConfiguration().parse(media, file, this, type);
} else {
media.parse(file, this, type, false);
}
logger.trace("Parsing results for file \"{}\": {}", file.toString(), media.toString());
}
/**
* Returns whether or not the matched extension of this format is among
* the list of supplied extensions.
*
* @param extensions String of comma-separated extensions
* @param moreExtensions String of comma-separated extensions
*
* @return True if this format matches an extension in the supplied lists,
* false otherwise.
*
* @see #match(String)
*/
public boolean skip(String extensions, String moreExtensions) {
if (extensions != null && extensions.length() > 0) {
StringTokenizer st = new StringTokenizer(extensions, ",");
while (st.hasMoreTokens()) {
String id = st.nextToken().toLowerCase();
if (matchedExtension != null && matchedExtension.toLowerCase().equals(id)) {
return true;
}
}
}
if (moreExtensions != null && moreExtensions.length() > 0) {
StringTokenizer st = new StringTokenizer(moreExtensions, ",");
while (st.hasMoreTokens()) {
String id = st.nextToken().toLowerCase();
if (matchedExtension != null && matchedExtension.toLowerCase().equals(id)) {
return true;
}
}
}
return false;
}
/**
* Return the class name for string representation.
* @return The name.
*/
@Override
public String toString() {
return getClass().getSimpleName();
}
/**
* Returns the specific identifier for the format.
*
* @return The identifier.
*/
public abstract Identifier getIdentifier();
}