/*****************************************************************************
|
* Media.java
|
*****************************************************************************
|
* Copyright © 2011-2013 VLC authors and VideoLAN
|
*
|
* 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; either version 2 of the License, or
|
* (at your option) any later version.
|
*
|
* 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 org.videolan.libvlc;
|
|
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Method;
|
import java.util.HashSet;
|
import java.util.Locale;
|
|
import android.content.Context;
|
import android.graphics.Bitmap;
|
import android.util.Log;
|
|
public class Media {
|
public final static String TAG = "VLC/LibVLC/Media";
|
|
public final static HashSet<String> VIDEO_EXTENSIONS;
|
public final static HashSet<String> AUDIO_EXTENSIONS;
|
public final static String EXTENSIONS_REGEX;
|
public final static HashSet<String> FOLDER_BLACKLIST;
|
|
|
static {
|
String[] video_extensions = {
|
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".avi", ".divx", "drc", ".dv",
|
".f4v", ".flv", ".gvi", ".gxf", ".ismv", ".iso", ".m1v", ".m2v", ".m2t", ".m2ts",
|
".m4v", ".mkv", ".mov", ".mp2", ".mp2v", ".mp4", ".mp4v", ".mpe", ".mpeg",
|
".mpeg1", ".mpeg2", ".mpeg4", ".mpg", ".mpv2", ".mts", ".mtv", ".mxf", ".mxg",
|
".nsv", ".nut", ".nuv", ".ogm", ".ogv", ".ogx", ".ps", ".rec", ".rm", ".rmvb",
|
".tod", ".ts", ".tts", ".vob", ".vro", ".webm", ".wm", ".wmv", ".wtv", ".xesc" };
|
|
String[] audio_extensions = {
|
".3ga", ".a52", ".aac", ".ac3", ".adt", ".adts", ".aif", ".aifc", ".aiff", ".amr",
|
".aob", ".ape", ".awb", ".caf", ".dts", ".flac", ".it", ".m4a", ".m4p",
|
".mid", ".mka", ".mlp", ".mod", ".mpa", ".mp1", ".mp2", ".mp3", ".mpc", ".mpga",
|
".oga", ".ogg", ".oma", ".opus", ".ra", ".ram", ".rmi", ".s3m", ".spx", ".tta",
|
".voc", ".vqf", ".w64", ".wav", ".wma", ".wv", ".xa", ".xm" };
|
|
String[] folder_blacklist = {
|
"/alarms",
|
"/notifications",
|
"/ringtones",
|
"/media/alarms",
|
"/media/notifications",
|
"/media/ringtones",
|
"/media/audio/alarms",
|
"/media/audio/notifications",
|
"/media/audio/ringtones",
|
"/Android/data/" };
|
|
VIDEO_EXTENSIONS = new HashSet<String>();
|
for (String item : video_extensions)
|
VIDEO_EXTENSIONS.add(item);
|
AUDIO_EXTENSIONS = new HashSet<String>();
|
for (String item : audio_extensions)
|
AUDIO_EXTENSIONS.add(item);
|
|
StringBuilder sb = new StringBuilder(115);
|
sb.append(".+(\\.)((?i)(");
|
sb.append(video_extensions[0].substring(1));
|
for(int i = 1; i < video_extensions.length; i++) {
|
sb.append('|');
|
sb.append(video_extensions[i].substring(1));
|
}
|
for(int i = 0; i < audio_extensions.length; i++) {
|
sb.append('|');
|
sb.append(audio_extensions[i].substring(1));
|
}
|
sb.append("))");
|
EXTENSIONS_REGEX = sb.toString();
|
FOLDER_BLACKLIST = new HashSet<String>();
|
for (String item : folder_blacklist)
|
FOLDER_BLACKLIST.add(android.os.Environment.getExternalStorageDirectory().getPath() + item);
|
}
|
|
public final static int TYPE_ALL = -1;
|
public final static int TYPE_VIDEO = 0;
|
public final static int TYPE_AUDIO = 1;
|
public final static int TYPE_GROUP = 2;
|
|
/** Metadata from libvlc_media */
|
protected String mTitle;
|
private String mArtist;
|
private String mGenre;
|
private String mCopyright;
|
private String mAlbum;
|
private String mTrackNumber;
|
private String mDescription;
|
private String mRating;
|
private String mDate;
|
private String mSettings;
|
private String mNowPlaying;
|
private String mPublisher;
|
private String mEncodedBy;
|
private String mTrackID;
|
private String mArtworkURL;
|
|
private final String mLocation;
|
private String mFilename;
|
private long mTime = 0;
|
private int mAudioTrack = -1;
|
private int mSpuTrack = -2;
|
private long mLength = 0;
|
private int mType;
|
private int mWidth = 0;
|
private int mHeight = 0;
|
private Bitmap mPicture;
|
private boolean mIsPictureParsed;
|
|
/**
|
* Create a new Media
|
* @param libVLC A pointer to the libVLC instance. Should not be NULL
|
* @param URI The URI of the media.
|
*/
|
public Media(LibVLC libVLC, String URI) {
|
if(libVLC == null)
|
throw new NullPointerException("libVLC was null");
|
|
mLocation = URI;
|
|
mType = TYPE_ALL;
|
TrackInfo[] tracks = libVLC.readTracksInfo(mLocation);
|
|
extractTrackInfo(tracks);
|
|
}
|
|
|
|
private void extractTrackInfo(TrackInfo[] tracks) {
|
if (tracks == null)
|
return;
|
|
for (TrackInfo track : tracks) {
|
if (track.Type == TrackInfo.TYPE_VIDEO) {
|
mType = TYPE_VIDEO;
|
mWidth = track.Width;
|
mHeight = track.Height;
|
} else if (mType == TYPE_ALL && track.Type == TrackInfo.TYPE_AUDIO){
|
mType = TYPE_AUDIO;
|
} else if (track.Type == TrackInfo.TYPE_META) {
|
mLength = track.Length;
|
mTitle = track.Title;
|
mArtist = getValueWrapper(track.Artist, UnknownStringType.Artist);
|
mAlbum = getValueWrapper(track.Album, UnknownStringType.Album);
|
mGenre = getValueWrapper(track.Genre, UnknownStringType.Genre);
|
mArtworkURL = track.ArtworkURL;
|
Log.d(TAG, "Title " + mTitle);
|
Log.d(TAG, "Artist " + mArtist);
|
Log.d(TAG, "Genre " + mGenre);
|
Log.d(TAG, "Album " + mAlbum);
|
}
|
}
|
|
/* No useful ES found */
|
if (mType == TYPE_ALL) {
|
int dotIndex = mLocation.lastIndexOf(".");
|
if (dotIndex != -1) {
|
String fileExt = mLocation.substring(dotIndex);
|
if( Media.VIDEO_EXTENSIONS.contains(fileExt) ) {
|
mType = TYPE_VIDEO;
|
} else if (Media.AUDIO_EXTENSIONS.contains(fileExt)) {
|
mType = TYPE_AUDIO;
|
}
|
}
|
}
|
}
|
|
public Media(String location, long time, long length, int type,
|
Bitmap picture, String title, String artist, String genre, String album,
|
int width, int height, String artworkURL, int audio, int spu) {
|
mLocation = location;
|
mFilename = null;
|
mTime = time;
|
mAudioTrack = audio;
|
mSpuTrack = spu;
|
mLength = length;
|
mType = type;
|
mPicture = picture;
|
mWidth = width;
|
mHeight = height;
|
|
mTitle = title;
|
mArtist = getValueWrapper(artist, UnknownStringType.Artist);
|
mGenre = getValueWrapper(genre, UnknownStringType.Genre);
|
mAlbum = getValueWrapper(album, UnknownStringType.Album);
|
mArtworkURL = artworkURL;
|
}
|
|
private enum UnknownStringType { Artist , Genre, Album };
|
/**
|
* Uses introspection to read VLC l10n databases, so that we can sever the
|
* hard-coded dependency gracefully for 3rd party libvlc apps while still
|
* maintaining good l10n in VLC for Android.
|
*
|
* @see org.videolan.vlc.Util#getValue(String, int)
|
*
|
* @param string The default string
|
* @param type Alias for R.string.xxx
|
* @return The default string if not empty or string from introspection
|
*/
|
private static String getValueWrapper(String string, UnknownStringType type) {
|
if(string != null && string.length() > 0) return string;
|
|
try {
|
Class<?> stringClass = Class.forName("org.videolan.vlc.R$string");
|
Class<?> utilClass = Class.forName("org.videolan.vlc.Util");
|
|
Integer value;
|
switch(type) {
|
case Album:
|
value = (Integer)stringClass.getField("unknown_album").get(null);
|
break;
|
case Genre:
|
value = (Integer)stringClass.getField("unknown_genre").get(null);
|
break;
|
case Artist:
|
default:
|
value = (Integer)stringClass.getField("unknown_artist").get(null);
|
break;
|
}
|
|
Method getValueMethod = utilClass.getDeclaredMethod("getValue", String.class, Integer.TYPE);
|
// Util.getValue(string, R.string.xxx);
|
return (String) getValueMethod.invoke(null, string, value);
|
} catch (ClassNotFoundException e) {
|
} catch (IllegalArgumentException e) {
|
} catch (IllegalAccessException e) {
|
} catch (NoSuchFieldException e) {
|
} catch (NoSuchMethodException e) {
|
} catch (InvocationTargetException e) {
|
}
|
|
// VLC for Android translations not available (custom app perhaps)
|
// Use hardcoded English phrases.
|
switch(type) {
|
case Album:
|
return "Unknown Album";
|
case Genre:
|
return "Unknown Genre";
|
case Artist:
|
default:
|
return "Unknown Artist";
|
}
|
}
|
|
/**
|
* Compare the filenames to sort items
|
*/
|
|
|
public String getLocation() {
|
return mLocation;
|
}
|
|
public void updateMeta() {
|
|
}
|
|
public String getFileName() {
|
if (mFilename == null) {
|
mFilename = LibVlcUtil.URItoFileName(mLocation);
|
}
|
return mFilename;
|
}
|
|
public long getTime() {
|
return mTime;
|
}
|
|
public void setTime(long time) {
|
mTime = time;
|
}
|
|
public int getAudioTrack() {
|
return mAudioTrack;
|
}
|
|
public void setAudioTrack(int track) {
|
mAudioTrack = track;
|
}
|
|
public int getSpuTrack() {
|
return mSpuTrack;
|
}
|
|
public void setSpuTrack(int track) {
|
mSpuTrack = track;
|
}
|
|
public long getLength() {
|
return mLength;
|
}
|
|
public int getType() {
|
return mType;
|
}
|
|
public int getWidth() {
|
return mWidth;
|
}
|
|
public int getHeight() {
|
return mHeight;
|
}
|
|
/**
|
* Returns the raw picture object. Likely to be NULL in VLC for Android
|
* due to lazy-loading.
|
*
|
* Use {@link org.videolan.vlc.Util#getPictureFromCache(Media)} instead.
|
*
|
* @return The raw picture or NULL
|
*/
|
public Bitmap getPicture() {
|
return mPicture;
|
}
|
|
/**
|
* Sets the raw picture object.
|
*
|
* In VLC for Android, use {@link org.videolan.vlc.Util#setPicture(Context, Media, Bitmap)} instead.
|
*
|
* @param p
|
*/
|
public void setPicture(Bitmap p) {
|
mPicture = p;
|
}
|
|
public boolean isPictureParsed() {
|
return mIsPictureParsed;
|
}
|
|
public void setPictureParsed(boolean isParsed) {
|
mIsPictureParsed = isParsed;
|
}
|
|
public String getTitle() {
|
if (mTitle != null && mType != TYPE_VIDEO)
|
return mTitle;
|
else {
|
int end = getFileName().lastIndexOf(".");
|
if (end <= 0)
|
return getFileName();
|
return getFileName().substring(0, end);
|
}
|
}
|
|
public String getSubtitle() {
|
return mType != TYPE_VIDEO ? mArtist + " - " + mAlbum : "";
|
}
|
|
public String getArtist() {
|
return mArtist;
|
}
|
|
public String getGenre() {
|
if(mGenre == getValueWrapper(null, UnknownStringType.Genre))
|
return mGenre;
|
else if( mGenre.length() > 1)/* Make genres case insensitive via normalisation */
|
return Character.toUpperCase(mGenre.charAt(0)) + mGenre.substring(1).toLowerCase(Locale.getDefault());
|
else
|
return mGenre;
|
}
|
|
public String getCopyright() {
|
return mCopyright;
|
}
|
|
public String getAlbum() {
|
return mAlbum;
|
}
|
|
public String getTrackNumber() {
|
return mTrackNumber;
|
}
|
|
public String getDescription() {
|
return mDescription;
|
}
|
|
public String getRating() {
|
return mRating;
|
}
|
|
public String getDate() {
|
return mDate;
|
}
|
|
public String getSettings() {
|
return mSettings;
|
}
|
|
public String getNowPlaying() {
|
return mNowPlaying;
|
}
|
|
public String getPublisher() {
|
return mPublisher;
|
}
|
|
public String getEncodedBy() {
|
return mEncodedBy;
|
}
|
|
public String getTrackID() {
|
return mTrackID;
|
}
|
|
public String getArtworkURL() {
|
return mArtworkURL;
|
}
|
}
|