/**
* **************************************************************************
* Media.java
* ****************************************************************************
* Copyright © 2011-2013 VLC authors and VideoLAN
* <p/>
* 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.
* <p/>
* 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.
* <p/>
* 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 android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Locale;
public class Media implements Comparable<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
*/
@Override
public int compareTo(Media another)
{
return mTitle.toUpperCase(Locale.getDefault()).compareTo(another.getTitle().toUpperCase
(Locale.getDefault()));
}
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;
}
}